0

Have this String (str):

ip=127.0.0.1&server=localhost&uri=/&vers=0.56&total_processed=21&total_blocked=20&config=learning&cscore0=$XSS&score0=16&zone0=ARGS&id0=1302&var_name0=a&zone1=ARGS&id1=1303&var_name1=a

Want to produce JSON out of it in pure C, like key:value ie ip: 127.0.0.1 etc

Tried this code:

  struct key_value
  {
    char key[128];
    char value[128];
  };

  int number_of_keys = 50;
  struct key_value *kv = malloc(sizeof(struct key_value) * number_of_keys);
  if (kv == NULL) {
      perror("Malloc");
      exit(EXIT_FAILURE);
  }
  char delim[] = "&";



  char *ptr = strtok((char *)((ngx_str_t *)ostr->elts)[0].data, delim);
  int j=0;
    while(ptr != NULL)
    {
        sscanf(ptr,"%[^=]=%[^\n]",kv[j].key,kv[j].value);
        ptr = strtok(NULL, delim);
        j=j+1;

    }



  ngx_log_error(NGX_LOG_ERR, r->connection->log,
          0, "{ %s:%s }", kv[0].key, kv[0].value);

But forgot how can I make a function to access/format it with unknown elements count??? Above I added only 2 %s ... but it can be more

Any improvements on speed, reliability for the code above?

Thanks,

dev
  • 1,119
  • 1
  • 11
  • 34
  • 1
    Why would you `strtok` it at all? Just `while(sscanf(...) == 2)` – KamilCuk Dec 08 '19 at 23:22
  • 1
    do you need storing the result in a struct/array before outputing it ? – dvhh Dec 08 '19 at 23:54
  • Find a library that does it? – Shawn Dec 09 '19 at 00:00
  • Processing general JSON with `sscanf()` or similar is going to be an exercise in frustration. Get a JSON library — there are many to choose from listed at the [JSON](https://json.org/) web site. – Jonathan Leffler Dec 09 '19 at 00:20
  • @JonathanLeffler the problem seem to be parsing a formatted input string to output it in JSON (which could bring its own headaches as well I admit) – dvhh Dec 09 '19 at 01:17
  • 1
    @dvhh — oh, yes; maybe [Using `scanf()` in a loop](https://stackoverflow.com/questions/3975236/how-to-use-sscanf-in-loops) is more relevant (though generating correct JSON isn't entirely trivial either, though it is much simpler than parsing JSON). – Jonathan Leffler Dec 09 '19 at 01:33

1 Answers1

1

strcspn can be used to iterate through a string and divide into sub-strings.
It will give the count of characters to the next delimiter or to the terminating zero.
Use strncpy to copy the characters to another array.
Set the terminating zero.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ( void) {
    char line[] = "ip=127.0.0.1&server=localhost&uri=/&vers=0.56&total_processed=21"
    "&total_blocked=20&config=learning&cscore0=$XSS&score0=16&zone0=ARGS&id0=1302"
    "&var_name0=a&zone1=ARGS&id1=1303&var_name1=a";
    char key[128] = "";
    char value[128] = "";
    char *item = line;//set pointer to start of line
    size_t span = 0;

    while ( *item) {
        span = strcspn ( item, "=");//count characters to next =
        if ( span >= sizeof key) {
            fprintf ( stderr, "key sub-string too long\n");
            exit ( EXIT_FAILURE);
        }
        strncpy ( key, item, span);//copy those characters to key
        key[span] = 0;//zero terminate
        printf ( "%-30s", key);
        fflush ( stdout);//no newline in printf so force output
        item += span;//advance pointer by count of characters
        item += !!*item;//!!*item add one if not terminating zero, count does not include =
        span = strcspn ( item, "&");
        if ( span >= sizeof value) {
            fprintf ( stderr, "value sub-string too long\n");
            exit ( EXIT_FAILURE);
        }
        strncpy ( value, item, span);
        value[span] = 0;
        printf ( "%s\n", value);
        item += span;
        item += !!*item;
    }

    return 0;
}
user3121023
  • 8,181
  • 5
  • 18
  • 16