Today I am happy to announce the release of a C++ buffer class that is of special use for interfacing with Windows system functions. The class is a template class and thus only one header file is needed. The template argument is the “character type”. However, please note that the “character type” can be literally anything, including unsigned int
or even an arbitrary struct
.
Friðrik, my boss at FRISK Software International (FRISK), was so generous to allow the release of this C++ utility class under a non-copyleft license. He agreed on the new (simplified) BSD license. This allows everyone to use this code for free, with the only “restriction” being that attribution has to be given. Even Microsoft is using code under BSD license (TCP/IP stack and utilities).
So, what does the class offer? Well, first of all the standard operations you’d expect from a simple string class such as concatenation and assignment (those are based on the idea of C-strings being zero-terminated) . But what sets this class apart from other simple buffer classes that I have found, as well as from the string classes which tend to be very restrictive when it comes to modifying the buffer they encapsulate is the fact that it can be used seamlessly with most APIs. The only exception from the rule are APIs which expect an untyped pointer (including ellipsis arguments), in which case you have to use the Buffer()
member function. It offers resizing of the buffer (ReAlloc(x);
) as well as completely freeing it (ReAlloc(0);
) or zeroing it out with Clear();
.
There are three ctors, one taking the size of the buffer to allocate and a second one that takes a zero-terminated buffer of elements of the given template argument type and the third is the copy-ctor. It also behaves correctly when given an empty string in that it will actually represent an empty string, not a NULL pointer. The default behavior, however, is to allocate a zero-size buffer, which translates to a NULL pointer. Since the class indirectly exposes the buffer it contains through the typecast operator (operator value_type*() const
), this means that it can be passed directly, where the pointer to the “character type” is expected. Similarly to a normal pointer of value_type*
you can apply the bool operator!() const
for tests concerning the buffer, e.g.:
CSimpleBufx; // x contains NULL pointer (because of default ctor) // ... if(!x) { x = _T("C:"); } x += _T("\\boot.ini"); HANDLE hFile = ::CreateFile(x, GENERIC_READ, 0, ...); // ...
For obvious reasons the class contains its own functions to retrieve the length of the buffer:
LengthSZ
: retrieves the length in elements up to the zero-terminating element.() Length
: Usable length of the buffer in elements.() LengthBytes
: same as() Length
, but multiplied withsizeof(value_type)
.
To give an example:
CSimpleBufx(MAX_PATH); // x contains empty buffer while(x.Length () == ::GetModuleFileName(NULL, x, x.Length ())) { if(ERROR_INSUFFICIENT_BUFFER == ::GetLastError()) { x.ReAlloc(x.Length () * 2); // double the buffer size } }
The class is very versatile, especially when it comes to interfacing with system routines. I will probably create a more detailed document about this class as a PDF soon, so stay tuned 😉
Download it here.
// Oliver
PS: If you’re curious, FRISK has also sponsored the development of the Anomy mail sanitizer by Bjarni Rúnar Einarsson.
Doesn’t Microsoft have perfectly good string classes that we can use?
Why do we need another one?
a.) what does that have to do with MS? With no big effort this class is fully portable, for example right now it also works with BCB 6.
b.) it isn’t just a good buffer for strings, it can hold arrays of just about anything.
c.) Let’s say you don’t use MFC/ATL already, then this class offers a slim substitute that can also be abused for strings, but also as ordinary buffer.
d.) Let’s say you use MFC/ATL: have you ever worked with CString as a buffer to be passed to APIs? It’s tedious.
In all those cases this buffer class comes in. Surely, in most projects I’d go for std:string (and friends), not even CString, but even there, the c_str() member function gives you a constant buffer, so you’d have to cast that away (ugly!) or use std::stringbuf (where it gets tedious again) in order to talk to APIs that want buffers.
Oops – my <sarcasm> and </sarcasm> tags got clobbered during submit…
You should know the reference.
😆
Any objections against a conversion to Delphi?…if I ever got time.