10 Commits
v0.6 ... v0.6.3

Author SHA1 Message Date
rexy712
2d94783ee7 Fix remaining integer inconsistencies 2019-07-27 11:38:59 -07:00
rexy712
f9a36a5c37 Fix inconsistent integer types for rjp_value_int 2019-07-27 11:31:29 -07:00
Rexy712
d3c99152fc Added string copy constructor 2019-06-26 18:07:19 -07:00
Rexy712
dc0c003785 Working on enabling chunked reading 2019-06-10 17:51:45 -07:00
rexy712
4577836f8e much better rjp_search_members 2019-04-06 07:08:46 -07:00
rexy712
50c7a055ec Updated version 2019-03-30 05:22:11 -07:00
rexy712
6771d00c6e Updated copyright notice 2019-03-30 05:20:53 -07:00
rexy712
71661cd9ad Made rjp_search_members take a 'const char* const*' for search terms 2019-03-30 04:37:06 -07:00
rexy712
46b7b56852 Fix rjp_string containing incorrect length 2019-02-21 10:49:21 -08:00
rexy712
fd7d9988b8 Fixed search return value being in an inconsistent state 2019-02-13 15:12:14 -08:00
11 changed files with 365 additions and 256 deletions

View File

@@ -4,8 +4,8 @@ include(GNUInstallDirs)
cmake_minimum_required(VERSION 3.0.2)
project(rjp)
set(rjp_VERSION_MAJOR 0)
set(rjp_VERSION_MINOR 5)
set(rjp_VERSION_REVISION 0)
set(rjp_VERSION_MINOR 6)
set(rjp_VERSION_REVISION 2)
set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include)
configure_file(
"${INCLUDE_PATH}/config.h.in"

3
TODO Normal file
View File

@@ -0,0 +1,3 @@
Change string handling to work with chunked reading
Change numeral handling to work with chunked reading
handle scientific notation

View File

@@ -1,6 +1,6 @@
/**
rjp
Copyright (C) 2018 rexy712
Copyright (C) 2018-2019 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/**
rjp
Copyright (C) 2018 rexy712
Copyright (C) 2018-2019 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,6 +25,15 @@
extern "C"{
#endif
#ifndef RJP_int
#include <stdint.h>
#define RJP_int int64_t
#endif
#ifndef RJP_float
#include <stdint.h>
#define RJP_float double
#endif
//type of data
typedef enum RJP_type{
json_object = 0,
@@ -64,8 +73,8 @@ typedef struct RJP_array{
//hold any json data type
typedef struct RJP_value{
union{
long integer;
double dfloat;
RJP_int integer;
RJP_float dfloat;
char boolean;
struct RJP_object object;
struct RJP_string string;
@@ -84,6 +93,7 @@ typedef struct RJP_search_res{
//Convert C string consisting of json data into RJP's format
RJP_value* rjp_parse(const char* str);
RJP_value* rjp_parse_chunked(const char* str, RJP_value* prev_chunk);
//Initialize a root RJP_value to NULL
RJP_value* rjp_init_json(void);
@@ -115,10 +125,11 @@ RJP_value* rjp_add_element(RJP_value* dest, RJP_value value);
void rjp_set_value(RJP_value* dest, RJP_value value);
//initialize a RJP_value to the requested type and value
RJP_value rjp_integer(long i);
RJP_value rjp_integer(RJP_int i);
RJP_value rjp_boolean(char b);
RJP_value rjp_dfloat(double d);
RJP_value rjp_dfloat(RJP_float d);
RJP_value rjp_string(char* c, size_t len);
RJP_value rjp_string_copy(const char* c);
RJP_value rjp_null(void);
RJP_value rjp_object(void);
RJP_value rjp_array(void);
@@ -137,10 +148,10 @@ size_t rjp_member_name_length(RJP_value* member);
RJP_search_res rjp_search_member(const RJP_value* object, const char* search, size_t skip);
//Search for first occurance of multiple keys. Returns first occurance of each.
//Assumes dest is large enough to hold maximum num items.
size_t rjp_search_members(const RJP_value* object, size_t num, const char** searches, RJP_search_res* dest, size_t skip);
size_t rjp_search_members(const RJP_value* object, size_t num, const char* const* searches, RJP_search_res* dest, size_t skip);
//Search for multiple occurances of multiple keys. Returns pointer to list of matches.
//Returned pointer must be freed using rjp_free
RJP_search_res* rjp_search_members_multi(const RJP_value* object, size_t num, const char** searches, size_t* rsize, size_t skip);
RJP_search_res* rjp_search_members_multi(const RJP_value* object, size_t num, const char* const* searches, size_t* rsize, size_t skip);
//Access first element of a json array
RJP_value* rjp_get_element(const RJP_value* array);
//Access next element of a json array given the previous element
@@ -155,8 +166,8 @@ RJP_value* rjp_value_parent(RJP_value* element);
RJP_type rjp_value_type(RJP_value* value);
//value accessors
double rjp_value_dfloat(RJP_value* value);
int rjp_value_integer(RJP_value* value);
RJP_float rjp_value_dfloat(RJP_value* value);
RJP_int rjp_value_integer(RJP_value* value);
char rjp_value_boolean(RJP_value* value);
char* rjp_value_string(RJP_value* value);
size_t rjp_value_string_length(RJP_value* value);

View File

@@ -1,6 +1,6 @@
/**
rjp
Copyright (C) 2018 rexy712
Copyright (C) 2018-2019 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/**
rjp
Copyright (C) 2018 rexy712
Copyright (C) 2018-2019 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
#include <stddef.h> //size_t
int _rjp__is_whitespace(char c);
char* _rjp__parse_string(RJP_value* root, const char* str, int* len, int* row, int* column);
char* _rjp__parse_string(RJP_value* root, const char* str, int* inclen, int* len, int* row, int* column);
size_t _rjp__array_strlen(RJP_value* arr);
size_t _rjp__object_strlen(RJP_value* root);
size_t _rjp__value_strlen(RJP_value* root);

View File

@@ -1,6 +1,6 @@
/**
rjp
Copyright (C) 2018 rexy712
Copyright (C) 2018-2019 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,14 +24,17 @@
#include "memory.h"
#include <stdlib.h> //strtod, strtol
#include <stdio.h> //fprintf, stderr
#include <string.h> //memset
//types of searches in the text
typedef enum json_search_target{
json_key,
json_colon,
json_comma,
json_value,
json_none
json_target_key,
json_target_colon,
json_target_comma,
json_target_value,
json_target_string,
json_target_numeral,
json_target_none
}json_search_target;
static RJP_value* _rjp__add_value(RJP_value* curr, RJP_value new_val){
@@ -49,233 +52,324 @@ static RJP_value* _rjp__add_value(RJP_value* curr, RJP_value new_val){
curr->object.last->value = new_val;
return &curr->object.last->value;
}
#define syntax_error(msg, row, column)\
do{DIAG_PRINT(stderr, "Syntax error! %s (%i:%i)\n", msg, row, column);rjp_free_value(root);return NULL;}while(0)
#define MAX_DEPTH 16
RJP_value* rjp_parse(const char* str){
RJP_value* root = 0;
RJP_value* curr = 0;
int row = 1, column = 0;
int in_line_comment = 0;
int in_block_comment = 0;
//keep track of where we are in a given subobject
int state_stack[MAX_DEPTH] = {0},*top = state_stack;
typedef struct RJP_string_state{
int escaped;
int in_utf_sequence;
char* buffer; //store partial string here only when chunked reading and chunk ends mid string
}RJP_string_state;
typedef struct RJP_numeral_state{
int numlen;
char* buffer; //store partial number string here only when chunked reading and chunk ends mid number
}RJP_numeral_state;
typedef struct RJP_parse_state{
RJP_value* root;
RJP_value* curr;
union{
RJP_string_state str_state;
RJP_numeral_state num_state;
};
int row, column;
int in_line_comment;
int in_block_comment;
int target_stack[MAX_DEPTH];
int* target;
}RJP_parse_state;
void _rjp__init_parse_state(RJP_parse_state* state){
state->root = NULL;
state->curr = NULL;
state->row = state->column = 0;
state->in_line_comment = 0;
state->in_block_comment = 0;
memset(state->target_stack, 0, MAX_DEPTH*sizeof(int));
state->target = state->target_stack;
}
static void syntax_error(const char* msg, RJP_parse_state* state){
DIAG_PRINT(stderr, "Syntax error! %s (%i:%i)\n", msg, state->row, state->column);
rjp_free_value(state->root);
}
//Return number of characters handled while processing comment
int _rjp__handle_comment(const char* str, RJP_parse_state* state){
char c = *str;
if(state->in_line_comment){
if(c == '\n')
state->in_line_comment = 0;
return 1;
}else if(state->in_block_comment){
if(c == '*' && *(str+1) == '/'){
state->in_block_comment = 0;
return 2;
}
return 1;
}else if(c == '/' && *(str+1) == '/'){
state->in_block_comment = 1;
return 2;
}else if(c == '/' && *(str+1) == '/'){
state->in_line_comment = 1;
return 2;
}
return 0;
}
int _rjp__handle_key(const char* str, RJP_parse_state* state){
char c = *str;
//start of key
if(c == '"'){
if(state->curr == NULL){
syntax_error("Key found outside of object definition!", state);
return -1;
}
int keylen;
int inclen;
char* new_string = _rjp__parse_string(state->root, str+1, &inclen, &keylen, &state->row, &state->column);
if(!new_string){
if(!keylen)
syntax_error("Cannot have empty key name!", state);
return -1;
}
_rjp__add_member_no_alloc(&(state->curr->object), new_string, keylen);
*state->target = json_target_colon;
return inclen+2;
//end of this object (object is empty)
}else if(c == '}'){
state->curr = state->curr->parent;
if(state->target != state->target_stack)
--state->target;
return 1;
//unrecognized character
}else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character, expected '\"'!", state);
return -1;
}
return 1;
}
int _rjp__handle_colon(const char* str, RJP_parse_state* state){
char c = *str;
//colon after a key
if(c == ':'){
*state->target = json_target_value;
//unrecognized character
}else if(!_rjp__is_whitespace(c)){
syntax_error( "Unexpected character, expected ':'!", state);
return -1;
}
return 1;
}
int _rjp__handle_comma(const char* str, RJP_parse_state* state){
char c = *str;
//comma separating keys in an object or values in an array
if(c == ','){
*state->target = (state->curr->type == json_array ? json_target_value : json_target_key);
//end of object
}else if(c == '}'){
if(state->curr->type == json_array){
syntax_error("Unexpected end of object within array!", state);
return -1;
}
state->curr = state->curr->parent;
if(state->target != state->target_stack)
--state->target;
//end of array
}else if(c == ']' && state->curr->type == json_array){
state->curr = state->curr->parent;
//unrecognized character
}else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character, expected ','!", state);
return -1;
}
return 1;
}
int _rjp__handle_value(const char* str, RJP_parse_state* state){
//object
char c = *str;
if(c == '{'){
if(!state->root){
state->root = _rjp__add_value(NULL, rjp_object());
state->curr = state->root;
*state->target = json_target_key;
}else{
state->curr = _rjp__add_value(state->curr, rjp_object());
*state->target = json_target_comma;
++state->target;
*state->target = json_target_key;
}
return 1;
}
else if(c == '['){
if(!state->root){
state->root = _rjp__add_value(NULL, rjp_array());
state->curr = state->root;
}else{
state->curr = _rjp__add_value(state->curr, rjp_array());
}
return 1;
}
else if(c == ']' && state->curr->type == json_array){ //empty array
*state->target = json_target_comma;
state->curr = state->curr->parent;
return 1;
}
//strings
else if(c == '"'){
int vallen, inclen;
char* new_string = _rjp__parse_string(state->root, str+1, &inclen, &vallen, &state->row, &state->column);
if(!new_string){
if(vallen == 0){
new_string = rjp_calloc(1, 1);
}else{
return -1;
}
}
_rjp__add_value(state->curr, rjp_string(new_string, vallen));
*state->target = json_target_comma;
return inclen+2;
}
//numbers
else if((c >= '0' && c <= '9') || c == '-'){
if(!state->curr)
*state->target = json_target_none;
else
*state->target = json_target_comma;
int numlen;
int floating = 0; //is an int or a double
for(numlen = 1;*(str+numlen) >= '0' && *(str+numlen) <= '9';++numlen);
if(*(str+numlen) == '.'){ //if we have a decimal, make it a double and continue parsing as a number
int i = ++numlen;
for(;*(str+numlen) >= '0' && *(str+numlen) <= '9';++numlen);
if(i == numlen){ //no number after decimal
syntax_error("Missing numerals after decimal place!", state);
return -1;
}
floating = 1;
}
if(*(str+numlen) == '\0' && state->curr){ //hit EOF early
syntax_error("Unexpected EOF before end of object!", state);
return -1;
}
if(c == '-' && numlen == 1){ //only have a '-' with no numbers
syntax_error("Missing numerals after '-' sign!", state);
return -1;
}
if(floating){
if(!state->root){
state->root = state->curr = _rjp__add_value(NULL, rjp_dfloat(strtod(str, NULL)));
}else{
_rjp__add_value(state->curr, rjp_dfloat(strtod(str, NULL)));
}
}else{
if(!state->root){
state->root = state->curr = _rjp__add_value(NULL, rjp_integer(strtoll(str, NULL, 10)));
}else{
_rjp__add_value(state->curr, rjp_integer(strtoll(str, NULL, 10)));
}
}
state->column += numlen;
return numlen;
}
//booleans and null
else if(!strncmp(str, "true", 4)){
if(!state->curr){
*state->target = json_target_none;
state->root = state->curr = _rjp__add_value(state->curr, rjp_boolean(1));
}else{
*state->target = json_target_comma;
_rjp__add_value(state->curr, rjp_boolean(1));
}
state->column += 3;
return 4;
}else if(!strncmp(str, "false", 5)){
if(!state->curr){
*state->target = json_target_none;
state->root = state->curr = _rjp__add_value(state->curr, rjp_boolean(0));
}else{
*state->target = json_target_comma;
_rjp__add_value(state->curr, rjp_boolean(0));
}
state->column += 4;
return 5;
}else if(!strncmp(str, "null", 4)){
if(!state->curr){
*state->target = json_target_none;
state->root = state->curr = _rjp__add_value(state->curr, rjp_null());
}else{
*state->target = json_target_comma;
_rjp__add_value(state->curr, rjp_null());
}
state->column += 3;
return 4;
}
//unrecognized character
else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character!", state);
return -1;
}
return 1;
}
RJP_value* rjp_parse(const char* str){
RJP_parse_state state;
_rjp__init_parse_state(&state);
//initially search for the root object
*top = json_value;
*state.target = json_target_value;
for(;*str != '\0';++str){
int inc = 0;
for(;*str != '\0';str += inc){
char c = *str;
//keep track of position in input file
if(c == '\n'){
++row;
column = 0;
++state.row;
state.column = 0;
}else{
++column;
++state.column;
}
//Handle comments
if(in_line_comment){
if(c == '\n')
in_line_comment = 0;
}
else if(in_block_comment){
if(c == '*' && *(str+1) == '/'){
in_block_comment = 0;
++str;
}
}
else if(c == '/' && *(str+1) == '/'){
in_line_comment = 1;
++str;
}
else if(c == '/' && *(str+1) == '*'){
in_block_comment = 1;
++str;
if((inc = _rjp__handle_comment(str, &state))){
continue;
}
else if(*top == json_key){
//start of key
if(c == '"'){
if(curr == NULL)
syntax_error("Key found outside of object definition!", row, column);
int keylen;
char* new_string = _rjp__parse_string(root, ++str, &keylen, &row, &column);
if(!new_string){
if(!keylen)
syntax_error("Cannot have empty key name!", row, column);
return NULL;
}
_rjp__add_member_no_alloc(&curr->object, new_string, keylen);
str += keylen;
*top = json_colon;
//end of this object (object is empty)
}else if(c == '}'){
curr = curr->parent;
if(top != state_stack)
--top;
//unrecognized character
}else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character, expected '\"'!", row, column);
switch(*state.target){
case json_target_key:
inc = _rjp__handle_key(str, &state);
break;
case json_target_colon:
inc = _rjp__handle_colon(str, &state);
break;
case json_target_comma:
inc = _rjp__handle_comma(str, &state);
break;
case json_target_value:
inc = _rjp__handle_value(str, &state);
break;
case json_target_none:
if(!_rjp__is_whitespace(*str)){
syntax_error("Unexpected character!", &state);
return NULL;
}
}
else if(*top == json_colon){
//colon after a key
if(c == ':'){
*top = json_value;
//unrecognized character
}else if(!_rjp__is_whitespace(c)){
syntax_error( "Unexpected character, expected ':'!", row, column);
}
}
else if(*top == json_comma){
//comma separating keys in an object or values in an array
if(c == ','){
*top = (curr->type == json_array ? json_value : json_key);
//end of object
}else if(c == '}'){
if(curr->type == json_array){
syntax_error("Unexpected end of object within array!", row, column);
}
curr = curr->parent;
if(top != state_stack)
--top;
//end of array
}else if(c == ']' && curr->type == json_array){
curr = curr->parent;
//unrecognized character
}else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character, expected ','!", row, column);
}
}
else if(*top == json_value){
//object
if(c == '{'){
if(!root){
root = _rjp__add_value(NULL, rjp_object());
curr = root;
*top = json_key;
}else{
curr = _rjp__add_value(curr, rjp_object());
*top = json_comma;
++top;
*top = json_key;
}
}
else if(c == '['){
if(!root){
root = _rjp__add_value(NULL, rjp_array());
curr = root;
}else{
curr = _rjp__add_value(curr, rjp_array());
}
}
else if(c == ']' && curr->type == json_array){ //empty array
*top = json_comma;
curr = curr->parent;
}
//strings
else if(c == '"'){
int vallen;
++str;
char* new_string = _rjp__parse_string(root, str, &vallen, &row, &column);
if(!new_string){
if(vallen == 0){
new_string = rjp_calloc(1, 1);
}else{
return NULL;
}
}
_rjp__add_value(curr, rjp_string(new_string, vallen));
str += vallen;
*top = json_comma;
}
//numbers
else if((c >= '0' && c <= '9') || c == '-'){
if(!curr)
*top = json_none;
else
*top = json_comma;
int numlen;
int floating = 0; //is an int or a double
for(numlen = 1;*(str+numlen) >= '0' && *(str+numlen) <= '9';++numlen);
if(*(str+numlen) == '.'){ //if we have a decimal, make it a double and continue parsing as a number
int i = ++numlen;
for(;*(str+numlen) >= '0' && *(str+numlen) <= '9';++numlen);
if(i == numlen){ //no number after decimal
syntax_error("Missing numerals after decimal place!", row, column);
}
floating = 1;
}
if(*(str+numlen) == '\0' && curr){ //hit EOF early
syntax_error("Unexpected EOF before end of object!", row, column);
}
if(c == '-' && numlen == 1){ //only have a '-' with no numbers
syntax_error("Missing numerals ofter '-' sign!", row, column);
}
if(floating){
if(!root){
root = curr = _rjp__add_value(NULL, rjp_dfloat(strtod(str, NULL)));
}else{
_rjp__add_value(curr, rjp_dfloat(strtod(str, NULL)));
}
}else{
if(!root){
root = curr = _rjp__add_value(NULL, rjp_integer(strtol(str, NULL, 10)));
}else{
_rjp__add_value(curr, rjp_integer(strtol(str, NULL, 10)));
}
}
str += (numlen-1);
column += numlen;
}
//booleans and null
else if(!strncmp(str, "true", 4)){
if(!curr){
*top = json_none;
root = curr = _rjp__add_value(curr, rjp_boolean(1));
}else{
*top = json_comma;
_rjp__add_value(curr, rjp_boolean(1));
}
str += 3;column += 3;
}else if(!strncmp(str, "false", 5)){
if(!curr){
*top = json_none;
root = curr = _rjp__add_value(curr, rjp_boolean(0));
}else{
*top = json_comma;
_rjp__add_value(curr, rjp_boolean(0));
}
str += 4;column += 4;
}else if(!strncmp(str, "null", 4)){
if(!curr){
*top = json_none;
root = curr = _rjp__add_value(curr, rjp_null());
}else{
*top = json_comma;
_rjp__add_value(curr, rjp_null());
}
str += 3;column += 3;
}
//unrecognized character
else if(!_rjp__is_whitespace(c)){
syntax_error("Unexpected character!", row, column);
}
}else if(*top == json_none && !_rjp__is_whitespace(c)){
syntax_error("Unexpected character!", row, column);
}
inc = 1;
break;
default:
inc = 1;
break;
};
}
return root;
return state.root;
}
RJP_value* rjp_parse_chunked(const char* str, RJP_value* prev_chunk){
if(!prev_chunk){
return rjp_parse(str);
}
return NULL;
}
#undef syntax_error

View File

@@ -1,6 +1,6 @@
/**
rjp
Copyright (C) 2018 rexy712
Copyright (C) 2018-2019 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/**
rjp
Copyright (C) 2018 rexy712
Copyright (C) 2018-2019 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -37,7 +37,7 @@ static size_t _rjp__write_value(char* dest, RJP_value* val){
size_t ret;
switch(val->type){
case json_integer:
ret = sprintf(dest, "%li", val->integer);
ret = sprintf(dest, "%lli", val->integer);
break;
case json_dfloat:
ret = sprintf(dest, "%lf", val->dfloat);

View File

@@ -1,6 +1,6 @@
/**
rjp
Copyright (C) 2018 rexy712
Copyright (C) 2018-2019 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -85,7 +85,7 @@ void rjp_set_value(RJP_value* dest, RJP_value value){
*dest = value;
dest->parent = p;
}
RJP_value rjp_integer(long i){
RJP_value rjp_integer(RJP_int i){
return (RJP_value){.integer = i, .type = json_integer};
}
RJP_value rjp_boolean(char b){
@@ -97,6 +97,12 @@ RJP_value rjp_dfloat(double d){
RJP_value rjp_string(char* c, size_t len){
return (RJP_value){.string = {.value = c, .length = len}, .type = json_string};
}
RJP_value rjp_string_copy(const char* c){
size_t esclen = rjp_escape_strlen(c);
char* tmp = rjp_alloc(esclen+1);
rjp_escape_strcpy(tmp, c);
return (RJP_value){.string = {.value = tmp, .length = esclen}, .type = json_string};
}
RJP_value rjp_null(void){
return (RJP_value){.integer = 0, .type = json_null};
}
@@ -138,10 +144,9 @@ RJP_search_res rjp_search_member(const RJP_value* object, const char* search, si
return (RJP_search_res){0};
}
size_t rjp_search_members(const RJP_value* object, size_t num, const char** searches, RJP_search_res* dest, size_t skip){
const char** tmp = rjp_alloc(num*sizeof(char*));
size_t rjp_search_members(const RJP_value* object, size_t num, const char* const* searches, RJP_search_res* dest, size_t skip){
for(size_t i = 0;i < num;++i){
tmp[i] = searches[i];
dest[i] = (RJP_search_res){0};
}
RJP_value* member = rjp_get_member(object);
size_t objindex = 0;
@@ -150,25 +155,20 @@ size_t rjp_search_members(const RJP_value* object, size_t num, const char** sear
for(;member;member = rjp_next_member(member),++objindex){
for(size_t i = 0;i < num;++i){
if(searches[i] == NULL)
if(dest[i].value != NULL)
continue;
if(!strcmp(((RJP_object_member*)member)->name.value, searches[i])){
dest[i].value = member;
dest[i].searchindex = i;
dest[i].objindex = objindex;
searches[i] = NULL;
++matches;
break;
}
}
}
for(size_t i = 0;i < num;++i){
searches[i] = tmp[i];
}
rjp_free(tmp);
return matches;
}
RJP_search_res* rjp_search_members_multi(const RJP_value* object, size_t num, const char** searches, size_t* rsize, size_t skip){
RJP_search_res* rjp_search_members_multi(const RJP_value* object, size_t num, const char* const* searches, size_t* rsize, size_t skip){
RJP_search_res* ret = rjp_alloc(num*sizeof(RJP_search_res));
size_t ret_size = num;
size_t j = 0;
@@ -217,10 +217,10 @@ RJP_value* rjp_value_parent(RJP_value* value){
RJP_type rjp_value_type(RJP_value* value){
return value->type;
}
double rjp_value_dfloat(RJP_value* value){
RJP_float rjp_value_dfloat(RJP_value* value){
return value->dfloat;
}
int rjp_value_integer(RJP_value* value){
RJP_int rjp_value_integer(RJP_value* value){
return value->integer;
}
char rjp_value_boolean(RJP_value* value){

View File

@@ -1,6 +1,6 @@
/**
rjp
Copyright (C) 2018 rexy712
Copyright (C) 2018-2019 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -148,7 +148,7 @@ static uint32_t u8_to_codepoint(char* u){
}
//Convert escape sequences in strings
char* _rjp__parse_string(RJP_value* root, const char* str, int* len, int* row, int* column){
char* _rjp__parse_string(RJP_value* root, const char* str, int* inclen, int* len, int* row, int* column){
char* new_string;
++(*column); //account for starting quotation mark
int oldpos = 0;
@@ -173,7 +173,8 @@ char* _rjp__parse_string(RJP_value* root, const char* str, int* len, int* row, i
*column = 0;
}
}
*len = oldpos;
*inclen = oldpos;
*len = newpos;
if(newpos == 0){
return NULL;
}
@@ -300,7 +301,7 @@ size_t _rjp__array_strlen(RJP_value* arr){
for(;element_list;element_list = element_list->next){
switch(element_list->value.type){
case json_integer:
count += snprintf(NULL, 0, "%li", element_list->value.integer);
count += snprintf(NULL, 0, "%lli", element_list->value.integer);
break;
case json_dfloat:
count += snprintf(NULL, 0, "%lf", element_list->value.dfloat);
@@ -349,7 +350,7 @@ size_t _rjp__object_strlen(RJP_value* root){
size_t _rjp__value_strlen(RJP_value* root){
switch(root->type){
case json_integer:
return snprintf(NULL, 0, "%li", root->integer);
return snprintf(NULL, 0, "%lli", root->integer);
case json_dfloat:
return snprintf(NULL, 0, "%lf", root->dfloat);
case json_boolean: