Using Data
The Data class encapsulates a buffer of bytes. It is similar in functionality to many common string classes, except that it operates on collections of bytes instead of collections of characters. In particular, Data is meant to operate on buffers that may or may not contain binary data. That said, there are a number of operations on Data which are written with manipulation of text in mind, and many methods go out of their way to ensure that the buffer is often null-terminated. It's a bit schizophrenic that way.
Contents
Buffer Management
At any given time, a Data is associated with a single buffer which contains the bytes inside the Data. This buffer may be owned by the Data object itself, or owned by an external party. Additionally, data owned by an external party can be considered changeable or unchangeable.
Sharing Style | Buffer Ownership | Buffer Mutable? |
---|---|---|
Share | External to Data class | Yes |
Borrow | External to Data class | No |
Take | Owned by Data class | Yes |
If a Data containing an immutable buffer (i.e. Sharing Mode is Borrow) is changed, then a new buffer is allocated by the Data, the contents of the existing (immutable) buffer are copied into it, and the modification is performed on the new buffer. This newly allocated buffer is owned by the Data.
If a modification is performed on a Data which requires more space than is available in the underlying buffer, then a larger buffer is allocated, the existing data is copied into the new buffer, and the modification is performed on the new buffer. If the old buffer was owned by the Data, it will be deallocated.
Note that all deallocation performed by the Data uses delete[]; consequently, any data owned by the Data (e.g. Sharing Mode is Take) must be allocated from the normal heap using new[], lest you anger the portability gods.
Finally, users of Data should note that a Data created from a buffer with Share or Borrow sharing must outlive the Data itself.
Creating a Data
Data conveniently has fifteen constructors for your creation pleasure.
Creating from Another Type
(Note: automatic conversion will not happen)
char *mySignedCharPtr = "Hello"; resip::Data data1 = new Data(mySignedCharPtr); // data1 contains "Hello"
unsigned char *myUnsignedCharPtr = "Hej"; resip::Data data2 = new Data(myUnsignedCharPtr); // data2 contains "Hej"
std::string myString = "Hola"; resip::Data data3 = new Data(myString); // data3 contains "Hola"
int myInt = -75; resip::Data data4 = new Data(myInt); // data4 contains "-75"
unsigned long myUnsignedLong = 12345; resip::Data data5 = new Data(myUnsignedLong); // data5 contains "12345"
unsigned int myUnsignedInt = 75; resip::Data data6 = new Data(myUnsignedLong); // data6 contains "-75"
Conversion to double takes a precision which indicates the number of digits after the decimal point. Trailing zeros are omitted. If not specified, the default precision is 4.
double myDouble = 7.12345; resip::Data data7 = new Data(myUnsignedLong); // data7 contains "7.1234" resip::Data data8 = new Data(myUnsignedLong,2); // data8 contains "7.12" resip::Data data9 = new Data(myUnsignedLong,6); // data9 contains "7.12345"
bool myBool = true; resip::Data data10 = new Data(myBool); // data10 contains "true"
char myChar = 'a'; resip::Data data11 = new Data(myChar); // data11 contains "true"
Creating from an Existing Buffer
(Share is assumed)
char buffer[2048]; int bytes = read(fd, buffer, sizeof(buffer)); resip::Data myData = new Data(buffer, bytes);
(Or you can explicitly call out a sharing mode)
char buffer[2048]; int bytes = read(fd, buffer, sizeof(buffer)); resip::Data myData = new Data(resip::Data::Borrow, buffer, bytes);
(Lazy copy-like constructor)
Data Comparisons
equal, <, >, prefix, postfix, substr
Data Manipulations
concat, xor,
Data Transformations
hash, hex, escaping, md5