How to append a char* to the end of a void*? - c++

Assume we have defined a char* as follow:
char *x;
And we have a function like it:
void append(void *y, char *z);
This function appends it's second parameter (where the pointer z is pointing at) to the end of a string that the pointer y is pointing to it's beginning. The reason that I am restricted to have the first parameter to be void* is that I need to override a libcurl function:
size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata);
Any time the header_callback function is called I need to append buffer to the end of userdata. The userdata pointer is pointing to beginning of a string.

According to documentation you linked, userdata is a pointer previously supplied to CURLOPT_HEADERDATA. Something like this might work for you.
size_t header_callback(char *buffer, size_t size, size_t nitems, vector<string> *userdata)
{
userdata->push_back(string(buffer, size*nitems));
return size*nitems;
}
//...
vector<string> headers;
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &headers);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
//...

It is impossible to implement your
void append(void *y, char *z);
in such a way that it could append a non-null terminated character sequence.
The char *buffer given to the callback is non-null terminated.
Also, you can convert the void pointer to the correct type of the buffer in the callback, before calling the append. That must be done eventually, since you cannot append anything to void.
You hardly need an external function since appending is quite trivial. Assuming your void* points to a std::string:
auto bytes = size * nitems;
auto str = (std::string*)userdata;
str->append(buffer, bytes);

To append data to buffer those things should be defined:
allowed size of destination buffer
amount of data in buffer present in destination buffer
amount of data to be copied to destination buffer
In C realloc() can be used to create new buffer with content of old one.. that may or may not change location of buffer. In C++ there is flavor of new operator that allows similar action.
If we assume that data stored is strictly null-terminated string (but even that wasn't specified!) then 2nd and 3rd are known - the size of buffer is unknown to append() is size of buffer. Therefore, the function
void append(void *y, char *z);
looks either unfit for the task or very unsafe and possibly ill-defined, unless void y is actually some structure or class (but passing that as void???) .
You did not provide implementation OR description of it. By the look is should be rather limited one. We should pre-allocate a buffer of proper size and ensure that append() won't run outside of its bounds. It cannot reallocate target buffer, so it is limited by already allocated memory. To actually reallocate target buffer append would have void **y or void &* y as formal parameter (realloc() may change pointer and does copy data from old buffer to new buffer)
This poses an architecture problem - ownership of buffer. If we pass buffer we control, we can allocate it properly and pass it to append() OR pass ownership to append() so it would reallocate it. If we don't, we have to create a temporal buffer... but can we use that temporal buffer afterwards?
The point is moot unless you are using custom header write function. user data pointer is CURLOPT_HEADERDATA, which is either pointer to valid FILE and you should _fwrite() data to it... Or, if you are implementing CURLOPT_WRITEFUNCTION and CURLOPT_READFUNCTION callback, that pointer can be used at discretion of designer of callbacks, as a pointer to some useful data container (libcurl uses fwrite as default callback).

Your question looks more referring to C (not C++) approach. Then you need the following:
know the size of the y
realloc the y to be of the size + 1
memcpy/memmove y to the new place
set the last byte of the new buffer to z
return to the user the pointer and the size of the new buffer
free the old buffer y (depends on the need).
In C++ hovewer you need to use some container like std::vector, which will allow you to append one byte.

Related

Char passing to other function best practice

I want to pass string to second function where it fills the character array and gives the value back. In the first function I want to take the string length after second function fills it.
first step
Planning to pass the character array
char data[10]="";
GetData(data); // Here Iam doing memset value to data
strlen(data);
second step
Planning to pass the character pointer
char *data;
GetData(data); // what I should do
strlen(data);
Can someone suggest which is the best practice
You want to use std::string, something like:
std::string data;
void GetData(std::string& str);
passing by non-const reference allows GetData to alter str.
Ideally the character pointer should be owned by the caller, and should take care of allocation (if possible, or callee has to do that on behalf of the caller) and deallocation
char *data = (char *) NULL; // should initialize to know allocated or not
the prototype of the call, GetData should be:
void GetData(char *& d); // pointer passed as reference
Within GetData, d shoud be allocated as:
d = new char[size]; //size should be appropriately decided including null terminating character
for example, if you wish to store a "hello" say, d should be allocated as :
d = new char[5+1]; // example
once done, in the caller, you must deallocate as:
if (data) delete [] data;
data = (char *) NULL;
The "classic", C-compatible method in Windows (where Visual C++ is most used) is to have a function that takes the buffer size as argument, and returns the size or length of data copied. Example:
//Inputs:
// buffer: [out/opt] If not null, write data here.
// size: [in] Buffer size including null terminator, ignored if buffer is null.
//Outputs:
// buffer: The data.
// Return Value: Length of data written to the buffer, without null terminator.
int GetData(char *buffer, size_t bufferSize);
This allows calling the function with a null buffer to obtain the length to allocate, allocate the data, and call the function again.
However, it's not very C++ and it's error-prone. Passing a pointer/reference to the pointer to allocate is better from a language standpoint, but has its drawbacks when crossing a DLL boundary, where it's recommended that any data allocated by a DLL be deallocated by the same DLL (preventing the use of ordinary smart pointers).

Confusion with void* type memory allocation?

I am pretty inexperienced in C++ programming and now I'm trying to make a small program using dctmk to modify the pixel data of the dicom image. In doing so while reading documentation I found a c++ method about which I'm not quite clear. In the documention for the class DicomImage I found the following method:
int DicomImage::getOutputData ( void * buffer,
const unsigned long size,
const int bits = 0,
const unsigned long frame = 0,
const int planar = 0
)
My confusion is about buffer. It's quoted in the link as
buffer : pointer to memory buffer (must already be allocated)
Here my confusion is how do a I allocate? I'm not sure how I could allocate a memory that's a pointer of void type. Could you please explain. Thank you.
You can do it in the following way (for example):
void * mem = malloc(1024); // 1 kb
image.GetOutputData(mem, 1024);
// Don't forget to free(mem);
Another way:
char * mem = new char[1024];
image.GetOutputData((void *)mem, 1024);
// Don't forget to delete[] mem;
Another way:
char mem[1024];
image.GetOutputData((void *)&mem, 1024);
A pointer to void can point to anything, it's a generic nondescript anonymous pointer to some memory. This means that you can pass any kind of pointer as the first argument of the function, as all pointers can implicitly be converted to void*.
You can allocate any type of buffer. It will be converted using void*. However you will need to pass proper size of element. You will need to refer to documentation of api for size of each buffer element. In the example below it is 1 byte. And total buffer size is 10.
int size_of_buffer = 10;
unsigned char *buffer = malloc(sizeof(unsigned char)*size_of_buffer);
It looks like DicomImage::getOutputData does not care how you allocated your bytes. Simply take take the pointer to some blob of your choice (object, struct, array, whatever) and cast it to void*. You can get the memory with new, malloc or it can be a local variable.
Thing to be sure of:
Make sure you allocate enough space.
Make sure you accurately send the size parameter.
Make sure that you understand what format of data DicomImage::getOutputData works with.

discover char* parameter size

I have a function that have a char* as parameter to receive some informations from inside the function. (int foo(char* param1))
How can I be sure that this parameter have the enough allocated space to receive all the information I need to put in?
I can be sure if it is, or not, a valid pointer, but I haven't found a way to be sure about the size/length allocated to the parameter.
I can't change the function (can't add another parameter with the size).
AFIAK, C++ does not have any facility to verify the amount of space allocated to a pointer. If the input points to a NULL-terminated array of chracters (i.e. a c-string), then you can use strlen(). Typically these kinds of functions in C and C++ must be well-documented as to what is expected from the parameters. The function is typically implemented assuming the the caller honors the documented contract.
If I have understood the question correctly, there is no way for you to ascertain the size of valid memory associated with the pointer. If this was pointing to an array of data, the usual way to pass a size parameter but if you do not have that option, you do not know what you will be accessing
Easy answer: you can't.
Little more complicated C-style answer: if that array of chars has a terminating NUL (0) byte, you can use strlen().
OS-specific answer: if the memory for the array was obtained using malloc(), you can use malloc_size() and malloc_usable_size() at least on OS X and Linux, respectively. On windows, for applications that use the Microsoft C Runtime, there's the _msize() function.
You can't be sure. Not really. The only practical check you can do for pointer validity is to check if it is not NULL.
As far as knowing size of the the buffer param1 points to, the only thing that comes to mind is this stupid hack. Before callting function, put the size of the buffer in at the beginning of the buffer that param1 points to. Then, copy your data into the buffer, overwriting the size when you are done with checks.
Like this:
*(unsigned int*)param1 = buf_size;
foo(param1);
int foo(char* param1)
{
if (0 == param1)
{
// fail
}
unsigned int buf_size = *(unsigned int*)param1;
if (buf_size < whateverlimit)
{
// fail
}
// copy data into the buffer
}
I have not compiled this code so it might need some corrections.

Copy unsigned char * to unsigned char*

I need to save packet state for a while.
So I read the packet data which is represented as unsigned char* and than I create a record with this data and save the record in the list for a while.
Which will be a better way to represent the packet in the record as char* or as char[].
How do i copy the read data ( unsigned char ) to both options :
To unsigned char[] and to unsigned char*
I need to copy the data because each time I read packet it will be readed to the same char*,so when I save it for a while I need to copy data first
If the packet data is binary I'd prefer using std::vector to store the data, as opposed to one of the C strXXX functions, to avoid issues with a potential NULL character existing in the data stream. Most strXXX functions look for NULL characters and truncate their operation. Since the data is not a string, I'd also avoid std::string for this task.
std::vector<unsigned char> v( buf, buf + datalen );
The vector constructor will copy all the data from buf[0] to buf[datalen - 1] and will deallocate the memory when the vector goes out of scope. You can get a pointer to the underlying buffer using v.data() or &v[0].
So, it sounds like you need to save the data from multiple packets in a list until some point in the future.
If it was me, I'd use std::string or std::vector normally because that removes allocation issues and is generally plenty fast.
If you do intend to use char* or char[], then you'd want to use char*. Declaring a variable like "char buf[1024];" allocates it on the stack, which means that when that function returns it goes away. To save it in a list, you'd need to dynamically allocate it, so you would do something like "char *buf = new char[packet.size];" and then copy the data and store the pointer and the length of the data in your list (or, as I said before, use std::string which avoids keeping the length separately).
How do you copy the data?
Probably memcpy. The strcpy function would have problems with data which can have nul characters in it, which is common in networking situations. So, something like:
char *buf = new char[packet_length];
memcpy(buf, packet_data, packet_length);
// Put buf and packet_length into a structure in your list.

Determining the correct size for a C++ array

I need to be able to set the size of an array based on the number of bytes in a file.
For example, I want to do this:
// Obtain the file size.
fseek (fp, 0, SEEK_END);
size_t file_size = ftell(fp);
rewind(fp);
// Create the buffer to hold the file contents.
char buff[file_size];
However, I get a compile time error saying that the size of the buffer has to be a constant.
How can I accomplish this?
Use a vector.
std::vector<char> buff(file_size);
The entire vector is filled with '\0' first, automatically. But the performance "lost" might not be noticable. It's certainly safer and more comfortable. Then access it like a usual array. You may even pass the pointer to the data to legacy C functions
legacy(&buff[0]); // valid!
You should use a std::vector and not an array.
Real arrays require you to specify their size so that the compiler can create some space for them -- this is why the compiler complains when you don't supply a constant integer. Dynamic arrays are represented by a pointer to the base of the array -- and you have to retrieve the memory for the dynamic array yourself. You may then use the pointer with subscript notation. e.g.,
int * x;
x = (int *) malloc( sizeof(int) *
getAmountOfArrayElements() /* non-const result*/
);
x[5] = 10;
This leads to two types of problems:
Buffer over/under flows : you might subscript-index past either end of the array.
You might forget to release the memory.
Vector provides a nice little interface to hide these problems from you -- if used correctly.
Replace
char buff[file_size];
with
char *buff = new char[file_size];
and once the use of the buff is done..you can free the memory using:
delete[] buff;
There are two points in your question I'd like to cover.
The actual question, how do you create the array. Johannes answered this. You use a std::vector and create it with a size allocation.
Your error message. When you declare an array of some type, you must declare it with a constant size. So for example
const int FileSize = 1000;
// stuff
char buffer[FileSize];
is perfectly legitimate.
On the other hand, what you did, attempting to declare an array with variable size, and then not allocating with new, generates an error.
Problem is that buff needs be created on the heap (instead of stack). Compiler want s to know the exact size to create on the stack.
char* buff = new char[file_size];