static void json_object_fini(void) { struct lh_entry *ent; if(MC_GET_DEBUG()) { if (json_object_table->count) { MC_DEBUG("json_object_fini: %d referenced objects at exit\n", json_object_table->count); lh_foreach(json_object_table, ent) { struct json_object* obj = (struct json_object*)ent->v; MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj); } } }
/* * Not all implementations of sscanf actually work properly. * Check whether the one we're currently using does, and if * it's broken, enable the workaround code. */ static void sscanf_is_broken_test() { int64_t num64; int ret_errno, is_int64_min, ret_errno2, is_int64_max; (void)sscanf(" -01234567890123456789012345", "%" SCNd64, &num64); ret_errno = errno; #ifdef INT64_MIN is_int64_min = (num64 == INT64_MIN); #else is_int64_min = (num64 == INT_MIN); #endif (void)sscanf(" 01234567890123456789012345", "%" SCNd64, &num64); ret_errno2 = errno; #ifdef INT64_MAX is_int64_max = (num64 == INT64_MAX); #else is_int64_max = (num64 == INT_MAX); #endif if (ret_errno != ERANGE || !is_int64_min || ret_errno2 != ERANGE || !is_int64_max) { MC_DEBUG("sscanf_is_broken_test failed, enabling workaround code\n"); sscanf_is_broken = 1; } }
int printbuf_memappend(struct printbuf *p, const char *buf, int size) { char *t; if(p->size - p->bpos <= size) { int new_size = json_max(p->size * 2, p->bpos + size + 8); #ifdef PRINTBUF_DEBUG MC_DEBUG("printbuf_memappend: realloc " "bpos=%d wrsize=%d old_size=%d new_size=%d\n", p->bpos, size, p->size, new_size); #endif /* PRINTBUF_DEBUG */ if(!(t = (char*)realloc(p->buf, new_size))) return -1; p->size = new_size; p->buf = t; } memcpy(p->buf + p->bpos, buf, size); p->bpos += size; p->buf[p->bpos]= '\0'; return size; }
/** * Extend the buffer p so it has a size of at least min_size. * * If the current size is large enough, nothing is changed. * * Note: this does not check the available space! The caller * is responsible for performing those calculations. */ static int printbuf_extend(struct printbuf *p, size_t min_size) { char *t; size_t new_size; if (p->size >= min_size) return 0; new_size = json_max(p->size * 2, min_size + 8); #ifdef PRINTBUF_DEBUG MC_DEBUG("printbuf_memappend: realloc " "bpos=%d min_size=%d old_size=%d new_size=%d\n", p->bpos, min_size, p->size, new_size); #endif /* PRINTBUF_DEBUG */ if(!(t = (char*)realloc(p->buf, new_size))) return -1; p->size = new_size; p->buf = t; return 0; }
static void json_object_init(void) { MC_DEBUG("json_object_init: creating object table\n"); json_object_table = lh_kptr_table_new(128, "json_object_table", NULL); }
int json_parse_int64(const char *buf, int64_t *retval) { int64_t num64; const char *buf_sig_digits; int orig_has_neg; int saved_errno; if (!sscanf_is_broken_testdone) { sscanf_is_broken_test(); sscanf_is_broken_testdone = 1; } // Skip leading spaces while (isspace((int)*buf) && *buf) buf++; errno = 0; // sscanf won't always set errno, so initialize if (sscanf(buf, "%" SCNd64, &num64) != 1) { MC_DEBUG("Failed to parse, sscanf != 1\n"); return 1; } saved_errno = errno; buf_sig_digits = buf; orig_has_neg = 0; if (*buf_sig_digits == '-') { buf_sig_digits++; orig_has_neg = 1; } // Not all sscanf implementations actually work if (sscanf_is_broken && saved_errno != ERANGE) { char buf_cmp[100]; char *buf_cmp_start = buf_cmp; int recheck_has_neg = 0; int buf_cmp_len; // Skip leading zeros, but keep at least one digit while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0') buf_sig_digits++; if (num64 == 0) // assume all sscanf impl's will parse -0 to 0 orig_has_neg = 0; // "-0" is the same as just plain "0" snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64); if (*buf_cmp_start == '-') { recheck_has_neg = 1; buf_cmp_start++; } // No need to skip leading spaces or zeros here. buf_cmp_len = strlen(buf_cmp_start); /** * If the sign is different, or * some of the digits are different, or * there is another digit present in the original string * then we have NOT successfully parsed the value. */ if (orig_has_neg != recheck_has_neg || strncmp(buf_sig_digits, buf_cmp_start, strlen(buf_cmp_start)) != 0 || ((int)strlen(buf_sig_digits) != buf_cmp_len && isdigit((int)buf_sig_digits[buf_cmp_len]) ) ) { saved_errno = ERANGE; } } // Not all sscanf impl's set the value properly when out of range. // Always do this, even for properly functioning implementations, // since it shouldn't slow things down much. if (saved_errno == ERANGE) { if (orig_has_neg) num64 = INT64_MIN; else num64 = INT64_MAX; } *retval = num64; return 0; }
int json_parse_int64(const char *buf, int64_t *retval) { int32_t num64; if (sscanf(buf, "%d", &num64) != 1) { MC_DEBUG("Failed to parse, sscanf != 1\n"); return 1; } const char *buf_skip_space = buf; int orig_has_neg = 0; // Skip leading spaces while (isspace((int)*buf_skip_space) && *buf_skip_space) buf_skip_space++; if (*buf_skip_space == '-') { buf_skip_space++; orig_has_neg = 1; } // Skip leading zeros, but keep at least one digit while (buf_skip_space[0] == '0' && buf_skip_space[1] != '\0') buf_skip_space++; if (buf_skip_space[0] == '0' && buf_skip_space[1] == '\0') orig_has_neg = 0; // "-0" is the same as just plain "0" if (errno != ERANGE) { char buf_cmp[100]; char *buf_cmp_start = buf_cmp; int recheck_has_neg = 0; snprintf(buf_cmp_start, sizeof(buf_cmp), "%d", num64); if (*buf_cmp_start == '-') { recheck_has_neg = 1; buf_cmp_start++; } // No need to skip leading spaces or zeros here. int buf_cmp_len = strlen(buf_cmp_start); /** * If the sign is different, or * some of the digits are different, or * there is another digit present in the original string * then we NOT successfully parsed the value. */ if (orig_has_neg != recheck_has_neg || strncmp(buf_skip_space, buf_cmp_start, strlen(buf_cmp_start)) != 0 || (strlen(buf_skip_space) != buf_cmp_len && isdigit((int)buf_skip_space[buf_cmp_len]) ) ) { errno = ERANGE; } } if (errno == ERANGE) { if (orig_has_neg) num64 = INT32_MIN; else num64 = INT32_MAX; } *retval = num64; return 0; }