3

I'm struggling to figure out how the jsmn library works. Here is my current code and what it produces. My problem is based only in the derefBy function

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

#include "jsmnutil.h"

char * jsmnTypes[] = {"undefined","object","array","string","primitive"};

const jsmnmarker_t jsmnErrorMarker = {NULL,-1};

jsmnmarker_t
makeMarker(jsmndata_t * data) {
  jsmnmarker_t marker;
  marker.data = data;
  marker.index = 0;
  return marker;
}

int
areEqualMarkers(jsmnmarker_t marker1, jsmnmarker_t marker2) {
  return marker1.data == marker2.data && marker1.index == marker2.index;
}

int
isErrorMarker(jsmnmarker_t marker) {
  return areEqualMarkers(marker,jsmnErrorMarker);
}

jsmnmarker_t
objectDeref(jsmnmarker_t marker, char * key) {
  if (marker.index == -1) return marker;
  int childCnt = TOKEN_SIZE(marker);
  jsmnmarker_t child = marker;
  child.index++;
  while (childCnt > 0) {
    if (TOKEN_PARENT(child) == marker.index) {
      if (strncmp(TOKEN_ADDR(child),key,TOKEN_LENGTH(child)) == 0) {
        child.index++;
        return child;
      }
      childCnt--;
    }
    child.index++;
  }
  return jsmnErrorMarker;
}


jsmnmarker_t
arrayDeref(jsmnmarker_t marker, int index) {
  if (marker.index == -1) return marker;
  int childCnt = TOKEN_SIZE(marker);
  if (index >= childCnt) return jsmnErrorMarker;
  jsmnmarker_t child = marker;
  child.index++;
  while (1) {
    if (TOKEN_PARENT(child) == marker.index) {
      if (index == 0) {
        return child;
      }
      index--;
    }
    child.index++;
  }
  return jsmnErrorMarker;
}

jsmnmarker_t
derefBy(jsmnmarker_t marker, char * fmt, ...) {
  va_list ap;
  char * s;
  int d;
  jsmnmarker_t holder = marker;

  va_start(ap,fmt);
  while (*fmt) {
    switch(*fmt++) {
     case 's':
        s = va_arg(ap,char *);
        printf("string %s\n",s);
        break;
     case 'd':
        d = va_arg(ap,int);
        printf("%d\n",d);
        break;
    }
  }
  va_end(ap);
}

jsmnmarker_t
nextKeyForObject(jsmnmarker_t objMarker, jsmnmarker_t keyMarker) {

}

jsmnmarker_t
valueForKey(jsmnmarker_t keyMarker) {
  keyMarker.index++;
  return keyMarker;
}

char * *
keysForObject(jsmnmarker_t marker) {
  if (marker.index == -1) return NULL;
  if (TOKEN_TYPE(marker) != JSMN_OBJECT) return NULL;
  int childSize = TOKEN_SIZE(marker);
  char * * keys = malloc((childSize + 1) * sizeof(char *));
  jsmnmarker_t child = marker;
  child.index++;
  int cnt = 0;
  while (cnt < childSize) {
    if (TOKEN_PARENT(child) == marker.index) {
      keys[cnt] = tokenText(child);
      cnt++;
    }
    child.index++;
  }
  keys[cnt] = NULL;
  return keys;
}

char *
tokenText(jsmnmarker_t marker) {
  if (marker.index < 0) return NULL;
  return strndup(TOKEN_ADDR(marker),TOKEN_LENGTH(marker));
}

void
printToken(FILE * fh, jsmnmarker_t marker) {
  if (marker.index >= 0 ) {
    fprintf(fh,"%.*s",TOKEN_LENGTH(marker),TOKEN_ADDR(marker));
  }
  else {
    fprintf(fh,"unresolved reference");
  }
}

void
dprintToken(int fd, jsmnmarker_t marker) {
  if (marker.index >= 0 ) {
    dprintf(fd,"%.*s",TOKEN_LENGTH(marker),TOKEN_ADDR(marker));
  }
  else {
    dprintf(fd,"unresolved reference");
  }
}

I know I have to return a jsmn marker, but I'm not quite sure how to create it with just the first or last name. Here is an example code that uses this function.

    char * firstName = tokenText(derefBy(faculty,"ds",i,"firstName"));
    char * lastName = tokenText(derefBy(faculty,"ds",i,"lastName"));
    fprintf(stdout,"Prof. %s %s \n",firstName,lastName);

My confusion is based on the results. It seems completely random that I either get

Faculty Schedules
0
string firstName
0
string lastName
Prof. (null) (null)
0
string classes
Segmentation fault (core dumped)

Or I get this without changing anything

Faculty Schedules
0
string firstName
Segmentation fault (core dumped)

I want it to simply produce

Prof. <firstName> <lastName>
Classes: ...

fmt is a string of 's' and 'd' characters which describes whether the remaining arguments are object keys or array indices. For example, derefBy(marker,"sds",key1, sub1, key2) would dereference marker first by key1 then index sub1 and finally key2

alk
  • 69,737
  • 10
  • 105
  • 255
Brad
  • 31
  • 4
  • There's a wonderful [JSON Benchmark repo](https://github.com/miloyip/nativejson-benchmark), I ran some tests a while back which [you can view online](http://facil.io/api/json_performance.html)... JSMN is a decent choice, but you can do much better, FYI. – Myst Apr 24 '18 at 01:04
  • My personal choice of JSON parser is PARSON.It's super easy to use and it's only 2 files. – Martin Chekurov Apr 26 '18 at 14:20
  • @MartinChekurov - parson is also 4 times faster than jsmn, at least on my machine (last time I tested). – Myst Apr 28 '18 at 03:40
  • 1
    `derefBy()` misses to return anything. – alk Apr 29 '18 at 13:51

0 Answers0