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,

6
  • 1
    Why would you strtok it at all? Just while(sscanf(...) == 2) Commented Dec 8, 2019 at 23:22
  • 1
    do you need storing the result in a struct/array before outputing it ? Commented Dec 8, 2019 at 23:54
  • Find a library that does it? Commented Dec 9, 2019 at 0: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 web site. Commented Dec 9, 2019 at 0:20
  • 1
    @dvhh — oh, yes; maybe Using scanf() in a loop is more relevant (though generating correct JSON isn't entirely trivial either, though it is much simpler than parsing JSON). Commented Dec 9, 2019 at 1:33

1 Answer 1

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;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.