I need to parse manually, without external libraries, a JSON message coming from a server, in C language.
The message coming from server would be like:
{[CR+LF]
"Tmg": "R",[CR+LF]
"STP": 72[CR+LF]
}[CR+LF]
or
{[CR+LF]
"Tmg": "R",[CR+LF]
"STP": 150[CR+LF]
}[CR+LF]
I need the number after STP:. The number is different in each message structure, so I need to get that number from the JSON structure. I can't use external libraries because this code is in an embedded system and exernal code is not allowed.
I tried this following:
int main (){
const char response_message[35] = "{\r\n\"Tmg\":\"R\",\r\n\"STP\":72,\r\n}";
const char needle[8] = "P\":";
char *ret;
ret = strstr(response_message, needle);
printf("The number is: %s\n", ret);
return 0;
}
But obviously, I am getting this result:
The number is: P":72,
}
So I need to only get the number, how can I get this?
Thanks
You can use a hacked solution. Use strstr () to find "STP": then find the following , or } and extract the digits in between.
And that's a hack. Not guaranteed to work. For something that's guaranteed to work, you use a JSON parser.
Related
I am working on a IOT project using MSP430F5529LP and CC3100Boost. The hardware is successfully connecting to the cloud and exchanging data. The response to the IOT devices is XML based. I am trying to parse the data. The following printf("\n%.*s\n", pch2-pch1-8, pch1 +8); extracts the data and prints to the console. Now in need to save this data to a variable. Here is my code snippet. The answer might be obvious, unfortunately I am failing to see it.
_i8 * databuffer;
char * pch0;
char * pch1;
char * pch2;
char data[7];
pch0 = strstr((char *)dataBuffer,"textResponse");
pch1 = strstr(pch0,"<text_1>");
pch2 = strstr(pch1,"</text_1>");
printf("\n%.*s\n", pch2-pch1-8, pch1 +8);
References:
Extract data between two delimiters
parsing the value in between two XML tags
MSP430G2121: looking for a xml library to parse xml text
Ensure that the data received is valid and of a length that will fit.
Print it to a string using sprintf() or equivalent function.
Print this string to the console with puts(the_string).
I am trying to parse the URL in C using microhttpd library.
daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, PORT, NULL, NULL, &answer_to_connection, NULL, MHD_OPTION_HTTPS_MEM_KEY, key_pem, MHD_OPTION_HTTPS_MEM_CERT, cert_pem, MHD_OPTION_END);
When I run the function MHD_start_daemon a call back function answer_to_connection is called.
static int answer_to_connection(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls)
{
printf("URL:%s\n", url);
}
One of the parameters of answer_to_connection is const char *url. The url variable contains the string after https://localhost:port example: for http://128.19.24.123:8888/cars/ferrari the url value will be /cars/ferrari
But in case of http://128.19.24.123:8888/cars?value=ferrari the url is printing only cars.
I want to print cars?value=ferrari. How can I do that?
There is a tutorial on microhttpd library at https://www.gnu.org/software/libmicrohttpd/tutorial.html
But I can't find any solution to this problem there.
CAVEAT EMPTOR: I have not used this library, this answer is based on a quick perusal of the API.
It looks like you can't access the whole original URL, because microhttpd parses it for you. Instead you access the individual query string values using MHD_lookup_connection_value, like this:
value = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "value");
That would return a pointer to the value of the query string argument, or null if not found.
You can also use MHD_get_connection_values to iterate over the query string components. In that case you would call it like this:
num = MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, iterator, cls);
iterator would be a callback function to receive the GET query arguments, one by one.
See also: the Handling requests section in the manual.
I want to make a program (network server-client).
One of the specification for this program is next:
The server will receive the sent packages and save it into a file, with a unique name (generated by the server at the moment the transfer starts.
Ex __tf_"unique_random_string".txt
I made a function that returns a pointer to a "unique" string created.
The problem is: If i stop the server and then start it again it will generate the same names.
Ex:this file names were generated and then i stopped the server.
__ft_apqfwk.txt
__ft_arzowk.txt
__ft_cdyggx.txt
I start it again and i try to generate 3 file names. Them will be the same.
Sorry for my english. I'm still learning it.
My function to generate this "unique string" is:
char *create_random_name(void)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyz";
char *file_name;
int i=0;
int key;
if((file_name = malloc(16 * sizeof ( char )) ) == NULL)
{
printf("Failed to alloc memory space\n");
return NULL;
}
strcpy(file_name,"__ft_");
for(i=5 ; i<11 ; i++)
{
key = rand() % (int)(sizeof(charset)-1);
file_name[i]=charset[key];
}
strcat(file_name,".txt");
file_name[15] = '\0';
return file_name;
}
One option is saving to a file the names that have been used, and using them as a checklist. You also want to seed rand with something like srand(time(NULL)).
another is ignoring the randomisation, and just going in order, e.g. aaa, aab aac...aba ,abb etc. Again, save where your cycle is up to on a file.
Your question seems a little bit unclear but if you want to generate a unique string there are a couple of things you can consider:
Get System timestamp ( yyyy-MM-dd-HH-mm-ss-fff-tt)
Use Random function to generate a random number
Combine this with your function and I am sure you will get a unique string.
Hope it helps !
If it's available, you could avoid manually generating random names that might collide and let the system do it for you (and handle collision resolution by creating a new name) by using mkstemps. This is also safer because it opens the file for you, removing the risk of a random name being generated, verified to be unique, then trying to open it and discovering another thread/process raced in and created it.
char name[] = "/path/to/put/files/in/__ft_XXXXXX.txt";
int fd = mkstemps(name, strlen(".txt"));
if (fd == -1) { ... handle error ... }
After mkstemps succeeds, name will hold the path to the file (it's mutated in place, replacing the XXXXXX string), and fd will be an open file descriptor to that newly created file; if you need a FILE*, use fdopen to convert to a stdio type.
Before calling rand(),--- once and only once---, call srand(time()) to initialize the random number generator.
Before settling on any specific file name, call stat() to assure that file name does not already exist.
I have the following Config.cfg
[DD]
user=**
password=***
database=***
IPServidor=****
port=***
[Controller]
Control1=8
Temp=5
Hum=7
Link=8
Volt=9
[Controller]
Control2=10
Temp=5
Hum=7
Link=8
Volt=9
I would like to read the values of the controllers only and print them to the screen like
Controller_8: 5,7,8,9
I do not want to use libconfig or glib because I have problem with undefined functions. I did the installation, I have the headers but I do not know why it does not work. So I want another solution. My first thought is with the usage of strchr to find the lines which I want (to ignore [DD] table in my case) and with the usage of strtok to get only the values of temp,hum,link,volt
char buffer1[100];
FILE *f = fopen("/home/pi/Desktop/Config.cfg","r");
while(fgets(buffer1, sizeof(buffer1), f))
{
printf("%s",buffer1);
char *pos1 = strchr(buffer1,'Controller');
if (pos1)
{
item = strtok (buffer1,"Control");
printf("Results: %s\n", buffer1);
}
}
The above code is not correct. Is just a thought. Is there any better way?
Don't try parsing ini files, use some existing library.
Ini file parsing is included in a number of "frameworks", for instance in Gtk+ or on Windows. If you can't access those, you can still use some standalone library, for instance: http://ndevilla.free.fr/iniparser/
I want to use Libextractor to get keywords/metadata for files.
The basic example for it is -
struct EXTRACTOR_PluginList *plugins
= EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
EXTRACTOR_extract (plugins, argv[1],
NULL, 0,
&EXTRACTOR_meta_data_print, stdout);
EXTRACTOR_plugin_remove_all (plugins);
However, this calls the function EXTRACTOR_meta_data_print which "prints" it to "stdout"
I'm looking at a way to get this information to another function - i.e. pass or store this in memory for further working. The documentation was not clear to me. Any help or experience regarding this?
I've tried to install libextractor and failed to get it working (it always returns a NULL plugin pointer upon call to EXTRACTOR_plugin_add_defaults()), so what I will write next is NOT TESTED:
from : http://www.gnu.org/software/libextractor/manual/libextractor.html#Extracting
Function Pointer: int
(*EXTRACTOR_MetaDataProcessor)(void *cls,
const char *plugin_name,
enum EXTRACTOR_MetaType type,
enum EXTRACTOR_MetaFormat format,
const char *data_mime_type,
const char *data,
size_t data_len)
and
Type of a function that libextractor calls for each meta data item found.
cls
closure (user-defined)
plugin_name
name of the plugin that produced this value;
special values can be used (i.e. '<zlib>' for
zlib being used in the main libextractor library
and yielding meta data);
type
libextractor-type describing the meta data;
format basic
format information about data
data_mime_type
mime-type of data (not of the original file);
can be NULL (if mime-type is not known);
data
actual meta-data found
data_len
number of bytes in data
Return 0 to continue extracting, 1 to abort.
So you would just have to write your own function called whatever you want, and have this declaration be like:
int whateveryouwant(void *cls,
const char *plugin_name,
enum EXTRACTOR_MetaType type,
enum EXTRACTOR_MetaFormat format,
const char *data_mime_type,
const char *data,
size_t data_len)
{
// Do your stuff here
if(stop)
return 1; // Stops
else
return 0; // Continues
}
and call it via:
EXTRACTOR_extract (plugins, argv[1],
NULL, 0,
&whateveryouwant,
NULL/* here be dragons */);
Like described in http://www.gnu.org/software/libextractor/manual/libextractor.html#Generalities "3.3 Introduction to the libextractor library"
[here be dragons]: That is a parameter left for the user's use (even if it's redundant to say so). As defined in the doc: "For each meta data item found, GNU libextractor will call the ‘proc’ function, passing ‘proc_cls’ as the first argument to ‘proc’."
Where "the proc function" being the function you added (whateveryouwant() here) and proc_cls being an arbitrary pointer (can be anything) for you to pass data to the function. Like a pointer to stdout in the example, in order to print to stdout. That being said, I suspect that the function writes to a FILE* and not inevitably to stdout; so if you open a file for writing, and pass its "file decriptor" as last EXTRACTOR_extract()'s parameter you would probably end with a file filled with the information you can currently read on your screen. That wouldn't be a proper way to access the information, but if you're looking into a quick and dirty way to test some behavior or some feature; that could do it, until you write a proper function.
Good luck with your code!