I have checked the documentation:
https://github.com/DaveGamble/cJSON#parsing-json and https://github.com/DaveGamble/cJSON#printing-json.
My question is I have a function void foo (char *JSON); that can only accept size_t JSON string representation at a time. The JSON String is larger than size_t.
Either I can parse the full JSON and print it in size_t chunks or I would have to split the JSON string into size_t and sanitize it to retain it in well-formed JSON format.
Is there a CJSON API that could help me in any of the scenarios?
Related
I developing a C embedded software that build a JSON string with several parameters ( string and integer ). For my purpose I used cJSON ) in future I need to parse complex JSON).
I build my json with this code:
jsonObject = cJSON_CreateObject();
cJSON_AddNumberToObject( jsonObject, "Version", 1 );
cJSON_AddStringToObject( jsonObject, "ID", "xyz" );
cJSON_AddStringToObject( jsonObject, "Local", "1234" );
cJSON_AddNumberToObject( jsonObject, "Type", 1 );
cJSON_AddStringToObject( jsonObject, "Message", "Hello" );
Next I print the JSON into a dynamic buffer using:
cJSON_PrintPreallocated( jsonObject, *jsonMessage, *jsonMessageLen, 0 )
When I visualise the jsonMessage on a terminal, the property "Type" hasn't a value.
This is the built json:
{"Version":1,"ID":"xyz","Local":"123","Type":,"Message":"Hello"}
I try to use a different print method, for example I used:
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
And the JSON is built correctly. The problem is that I need to allocate the memory by myself and not using cJSON_PrintBuffered. This because I cannot use malloc and free function.
Any suggestions?
Thanks
I updated the cJSON module and now it works fine.
This is kind of interesting, I believe I know what is going on. Sorry for any inconveniences I caused by writing that bug ...
In version 1.4.0 I introduced a bug to cJSON that the function that prints numbers didn't fail when it couldn't allocate enough memory.
print_number will try to allocate 64 bytes of memory before printing a number, because it doesn't know how many bytes sprintf will need and snprintf is not available in ANSI C. Your preallocated buffer probably wasn't long enough for the 64 bytes, so it didn't print the number one, but then continued printing the rest of the JSON normally because it didn't fail (the bug).
I added a note to the header file today: Your preallocated has to be 63 bytes longer than what you expect the printed json to be if you want to avoid any kind of out of situation where cJSON aborts because it thinks it doesn't have enough memory in the preallocated buffer.
I have given an array of structs:
typedef struct sRawMsg{
int a;
}sRawMsg;
sRawMsg RawMsg[10];
First the struct array entries are filled with data. Then the data is copied to an output buffer given as a 2D array.
// sending buffer which allocates memory for the array struct
static unsigned char sendingBuffer[10][sizeof(sRawMsg)];
for(int i = 0; i < 10; ++i)
{
sRawMsg* pMsg = &(RawMsg[i]);
// data is now stored in the struct array # pos i
...
// data from the struct entry is now saved in the output sending buffer
memcopy(&(sendingBuffer[i][0]), pMsg, sizeof(sRawMsg));
}
The obtained output buffer is transmitted as an plain byte array over an wireless connection. Since I am new to C programming I want to ask whether a more efficient / elegant / secure way exist to handle the struct array data.
Since you don't have any padding in the structure (one element structures don't have padding with any normal compiler), you could simply pass the
(unsigned char *)&RawMsg[0]
as the argument to your sending function.
If you were converting the data to a fixed format (e.g. network order), or if your structure included a mixture of types with padding between the elements, or if your structure included pointers to strings (or other pointers to data), you'd have to work harder — use serialization analogous to what you are doing. With pointers to strings, you'd probably need a protocol that knows how to identify the lengths of strings. One such convention is known as TLV (Type, length, value). Another (vastly more complex) one is ASN.1. Or you can use a format such as JSON or BSON, or maybe Google's Protocol buffers.
I am building a program that reads an XML configuration file. The XML configuration file contains several variables. One of which is
<bin_file>/some/file/path/file.bin</bin_file>
In my code I have the following struct
struct buildConofig {
char foo[3];
char bar[2];
char bin_file[?];
};
The code looks at the XML file and fills in the struct as it finds the matching elements in XML. I'm not sure what the length of the bin_file field should be. Is there a limit to file path size?
Or should I make bin_file a pointer and then malloc enough bytes after I check the XML field?
Thanks for your help.
As others pointed out, using malloc() would probably be the safest way. In this particular case, it might even be dangerous relying on constants/macros like FILENAME_MAX. When reading that path from the XML document, it is still just a string, so it can be of virtually any length (and thus happily overflow your char buffer[FILENAME_MAX] if you don't cut it off manually).
in different system there are a little different
such as:
ubuntu 12.04:
NAME_MAX: 255 //file max length
PATH_MAX: 4096 // path max length
as showed above the max size may be 255*4096= 1044480? that means you should do like
char bin_file[1044480];
but this is not recommended.
you can include string.h and do like below
#include<string.h>
struct buildConofig {
char foo[3];
char bar[2];
string bin_file;
};
If I am reading a C string such as:
char myData[100];
and I want to process this data and produce a copy out of it, so my code looks like:
char myData[100], processedData[50];
loop
fill myData from file...
setProcessedData(myData, processedData);
store processedData to file...
where setProcessedData is a function that returns a processed string. let's say for simplicity it returns a substring
void setProcessedData (char *myData, char *processedData) {
memCopy( processedData, myData, 5);
}
Is what I am doing something wrong? Like creating extra objects/strings? is there a better way to do it?
Let's say I read string from file which contains *
I am* A T*est String* But Ho*w to Process*.
I want to get substring which has the first 3 s. So my processedData
I am A t*est String*
and I want to do this for all lines of a file as efficient as possible.
Thanks
Problem is that your function is inherently unsafe, this because you make assumption about the allocated memory by parameters you pass to the function.
If someone is going to call setProcessedData by passing a string which is shorter than 5 bytes then bad things will happen.
In addition you are copying memory with memcpy by using a raw dimension, a safer approach, even if it is quite picky in this situation, is to use sizeof(char)*5.
Best thing you can do, though, is to follow the same approach used by safer functions of standard library like strcpy vs strncpy: you pass a third parameter which is the maximum length that should be copied, eg:
void processData(const char *data, char *processedData, unsigned int length) {
memcpy(processedData,data,length*sizeof(char));
}
I think you can improve your code:
Making the input string pointer const (i.e. const char* myData), to mark that myData is an input string and its content is not modified by the function.
Pass the size of the destination buffer, so in your function you can do proper checks and avoid buffer overruns (a security enemy).
How do I read response headers from a response using libCurl in C?
The MAN page says this:
size_t function( void *ptr, size_t size, size_t nmemb, void *stream)
What is the stream here? Do I read headers from stream or from ptr?
I am currently trying to read code from ptr and passing a struct for stream.
And the only response header is see is http/1. 0 ok. Nothing else and I am pretty sure the response has more headers
The last parameter isn't a stream, it's a void* to your userdata if used. The data to read is in *ptr, and this function will be called once for each header received.
(The last parameter is often used to point back to an C++ object instance through a static method using the C-style API...)
One example here:
http://permalink.gmane.org/gmane.comp.web.curl.library/28803