summaryrefslogblamecommitdiffstats
path: root/src/json.c
blob: e23d934c3e3b73f505c5a4632bf2aecd6e491665 (plain) (tree)















































































                                                                                                     
#ifndef DC_REALLOC_K
#define DC_REALLOC_K 1.5
#endif
struct dc_json { /* does not care about syntax, only purpose is to detect objects for libcjson */
	char * buf;	/* internal buffer */
	size_t bufcap;	/* internal buffer capacity */
	size_t nest;	/* internal nesting depth of whatevery type: object or array */
	size_t instr;	/* internal if we are currently in a string */
	size_t start;	/* internal starting offset in buffer of first byte of object - { */
	char backup;	/* internal we store byte we overwrote with \0 when we were ready */
	int ready;	/* internal we indicate to the next call that we were ready previous time */
}; /* note that no memory is transfered. in is copied and return mustn't be freed. */
char * dc_json (struct dc_json * j, char * in) { /* detects start/end of a cat objects JSON stream */
	size_t i;	/* input a null terminated string - a chunk of the json stream */
	if (!j->buf)
		(j->buf = malloc((j->bufcap = 1024) * sizeof(char)))[0] = '\0';
	if (j->ready) {
		if (j->ready > 0)
			memmove(j->buf, j->buf+j->ready, strlen(j->buf+j->ready)+1);
		j->buf[0] = j->backup;
	}
	size_t bufstrlen = strlen(j->buf);	/* could optimize and cache it into the struct */
	size_t instrlen = strlen(in);
	i = bufstrlen;
	if (bufstrlen + instrlen > j->bufcap)
		j->buf = realloc(j->buf, (j->bufcap=(bufstrlen+instrlen)*DC_REALLOC_K)*sizeof(char));
	strcpy(j->buf+bufstrlen, in);
	bufstrlen += instrlen;
	while (i < bufstrlen) {
		if (j->instr) {
			if (j->buf[i] == '"') {
				int escaped = 0;
				int index = 0;
				while (j->buf[i-++index] == '\\') {
					if (escaped)
						escaped = 0;
					else
						escaped++;
				}
				if (!escaped) {
					j->instr = 0;
					fprintf(stderr, "dc_json: j->instr = 0\n");
				} else
					fprintf(stderr, "dc_json: escaped\n");
			}
			goto next;
		}
		switch (j->buf[i]) {
			case '{':
			case '[':
				if (!j->nest++)
					j->start = i;
				break;
			case '"':
				j->instr++;
				fprintf(stderr, "dc_json: j->instr++\n");
				break;
			case '}':
			case ']':
				if (!--j->nest) {
					j->backup = j->buf[++i];
					j->ready = i;
					if (!j->backup)
						j->ready = -1;
					j->buf[i] = '\0';
					return j->buf+j->start;
				}
				break;
			default:
				break;
		}
next:
		i++;
	}
	return NULL;
} /* returns pointer to null terminated string when there's an object to be parsed or NULL. */
void dc_json_free (struct dc_json * s) {
	free(s->buf);
	free(s);
}