@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
/*
* Copyright ( c ) 2009 , 2010 Petri Lehtinen < petri @ digip . org >
* Copyright ( c ) 2009 - 2011 Petri Lehtinen < petri @ digip . org >
*
* Jansson is free software ; you can redistribute it and / or modify
* it under the terms of the MIT license . See LICENSE for details .
@ -12,7 +12,6 @@
@@ -12,7 +12,6 @@
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <stdarg.h>
# include <assert.h>
# include <jansson.h>
@ -20,6 +19,10 @@
@@ -20,6 +19,10 @@
# include "strbuffer.h"
# include "utf.h"
# define STREAM_STATE_OK 0
# define STREAM_STATE_EOF -1
# define STREAM_STATE_ERROR -2
# define TOKEN_INVALID -1
# define TOKEN_EOF 0
# define TOKEN_STRING 256
@ -29,113 +32,125 @@
@@ -29,113 +32,125 @@
# define TOKEN_FALSE 260
# define TOKEN_NULL 261
/* read one byte from stream, return EOF on end of file */
/* Read one byte from stream, convert to unsigned char, then int, and
return . return EOF on end of file . This corresponds to the
behaviour of fgetc ( ) . */
typedef int ( * get_func ) ( void * data ) ;
/* return non-zero if end of file has been reached */
typedef int ( * eof_func ) ( void * data ) ;
typedef struct {
get_func get ;
eof_func eof ;
void * data ;
int stream_pos ;
char buffer [ 5 ] ;
int buffer_pos ;
int state ;
int line ;
int column , last_column ;
size_t position ;
} stream_t ;
typedef struct {
stream_t stream ;
strbuffer_t saved_text ;
int token ;
int line , column ;
union {
char * string ;
in t integer ;
json_int_ t integer ;
double real ;
} value ;
} lex_t ;
# define stream_to_lex(stream) container_of(stream, lex_t, stream)
/*** error reporting ***/
static void error_init ( json_error_t * error )
{
if ( error )
{
error - > text [ 0 ] = ' \0 ' ;
error - > line = - 1 ;
}
}
/*** error reporting ***/
static void error_set ( json_error_t * error , const lex_t * lex ,
const char * msg , . . . )
{
va_list ap ;
char text [ JSON_ERROR_TEXT_LENGTH ] ;
char msg_text [ JSON_ERROR_TEXT_LENGTH ] ;
int line = - 1 , col = - 1 ;
size_t pos = 0 ;
const char * result = msg_text ;
if ( ! error | | error - > text [ 0 ] ! = ' \0 ' ) {
/* error already set */
if ( ! error )
return ;
}
va_start ( ap , msg ) ;
vsnprintf ( text , JSON_ERROR_TEXT_LENGTH , msg , ap ) ;
vsnprintf ( msg_ text, JSON_ERROR_TEXT_LENGTH , msg , ap ) ;
va_end ( ap ) ;
if ( lex )
{
const char * saved_text = strbuffer_value ( & lex - > saved_text ) ;
error - > line = lex - > line ;
char msg_with_context [ JSON_ERROR_TEXT_LENGTH ] ;
line = lex - > stream . line ;
col = lex - > stream . column ;
pos = lex - > stream . position ;
if ( saved_text & & saved_text [ 0 ] )
{
if ( lex - > saved_text . length < = 20 ) {
snprintf ( error - > text , JSON_ERROR_TEXT_LENGTH ,
" %s near '%s' " , text , saved_text ) ;
snprintf ( msg_with_context , JSON_ERROR_TEXT_LENGTH ,
" %s near '%s' " , msg_text , saved_text ) ;
result = msg_with_context ;
}
else
snprintf ( error - > text , JSON_ERROR_TEXT_LENGTH , " %s " , text ) ;
}
else
{
snprintf ( error - > text , JSON_ERROR_TEXT_LENGTH ,
" %s near end of file " , text ) ;
if ( lex - > stream . state = = STREAM_STATE_ERROR ) {
/* No context for UTF-8 decoding errors */
result = msg_text ;
}
else {
snprintf ( msg_with_context , JSON_ERROR_TEXT_LENGTH ,
" %s near end of file " , msg_text ) ;
result = msg_with_context ;
}
}
else
{
error - > line = - 1 ;
snprintf ( error - > text , JSON_ERROR_TEXT_LENGTH , " %s " , text ) ;
}
jsonp_error_set ( error , line , col , pos , " %s " , result ) ;
}
/*** lexical analyzer ***/
static void
stream_init ( stream_t * stream , get_func get , eof_func eof , void * data )
stream_init ( stream_t * stream , get_func get , void * data )
{
stream - > get = get ;
stream - > eof = eof ;
stream - > data = data ;
stream - > stream_pos = 0 ;
stream - > buffer [ 0 ] = ' \0 ' ;
stream - > buffer_pos = 0 ;
stream - > state = STREAM_STATE_OK ;
stream - > line = 1 ;
stream - > column = 0 ;
stream - > position = 0 ;
}
static char stream_get ( stream_t * stream , json_error_t * error )
static int stream_get ( stream_t * stream , json_error_t * error )
{
char c ;
int c ;
if ( stream - > state ! = STREAM_STATE_OK )
return stream - > state ;
if ( ! stream - > buffer [ stream - > buffer_pos ] )
{
stream - > buffer [ 0 ] = stream - > get ( stream - > data ) ;
stream - > buffer_pos = 0 ;
c = stream - > get ( stream - > data ) ;
if ( c = = EOF ) {
stream - > state = STREAM_STATE_EOF ;
return STREAM_STATE_EOF ;
}
c = stream - > buffer [ 0 ] ;
stream - > buffer [ 0 ] = c ;
stream - > buffer_pos = 0 ;
if ( ( unsigned char ) c > = 0x80 & & c ! = ( char ) EO F)
if ( 0x80 < = c & & c < = 0xF F)
{
/* multi-byte UTF-8 sequence */
int i , count ;
@ -152,30 +167,47 @@ static char stream_get(stream_t *stream, json_error_t *error)
@@ -152,30 +167,47 @@ static char stream_get(stream_t *stream, json_error_t *error)
if ( ! utf8_check_full ( stream - > buffer , count , NULL ) )
goto out ;
stream - > stream_pos + = count ;
stream - > buffer [ count ] = ' \0 ' ;
}
else {
else
stream - > buffer [ 1 ] = ' \0 ' ;
stream - > stream_pos + + ;
}
}
return stream - > buffer [ stream - > buffer_pos + + ] ;
c = stream - > buffer [ stream - > buffer_pos + + ] ;
out :
error_set ( error , NULL , " unable to decode byte 0x%x at position %d " ,
( unsigned char ) c , stream - > stream_pos ) ;
stream - > position + + ;
if ( c = = ' \n ' ) {
stream - > line + + ;
stream - > last_column = stream - > column ;
stream - > column = 0 ;
}
else if ( utf8_check_first ( c ) ) {
/* track the Unicode character column, so increment only if
this is the first character of a UTF - 8 sequence */
stream - > column + + ;
}
stream - > buffer [ 0 ] = EOF ;
stream - > buffer [ 1 ] = ' \0 ' ;
stream - > buffer_pos = 1 ;
return c ;
return EOF ;
out :
stream - > state = STREAM_STATE_ERROR ;
error_set ( error , stream_to_lex ( stream ) , " unable to decode byte 0x%x " , c ) ;
return STREAM_STATE_ERROR ;
}
static void stream_unget ( stream_t * stream , char c )
static void stream_unget ( stream_t * stream , int c )
{
if ( c = = STREAM_STATE_EOF | | c = = STREAM_STATE_ERROR )
return ;
stream - > position - - ;
if ( c = = ' \n ' ) {
stream - > line - - ;
stream - > column = stream - > last_column ;
}
else if ( utf8_check_first ( c ) )
stream - > column - - ;
assert ( stream - > buffer_pos > 0 ) ;
stream - > buffer_pos - - ;
assert ( stream - > buffer [ stream - > buffer_pos ] = = c ) ;
@ -187,29 +219,32 @@ static int lex_get(lex_t *lex, json_error_t *error)
@@ -187,29 +219,32 @@ static int lex_get(lex_t *lex, json_error_t *error)
return stream_get ( & lex - > stream , error ) ;
}
static int lex_eof ( lex_t * lex )
{
return lex - > stream . eof ( lex - > stream . data ) ;
}
static void lex_save ( lex_t * lex , char c )
static void lex_save ( lex_t * lex , int c )
{
strbuffer_append_byte ( & lex - > saved_text , c ) ;
}
static int lex_get_save ( lex_t * lex , json_error_t * error )
{
char c = stream_get ( & lex - > stream , error ) ;
int c = stream_get ( & lex - > stream , error ) ;
if ( c ! = STREAM_STATE_EOF & & c ! = STREAM_STATE_ERROR )
lex_save ( lex , c ) ;
return c ;
}
static void lex_unget_unsave ( lex_t * lex , char c )
static void lex_unget ( lex_t * lex , int c )
{
stream_unget ( & lex - > stream , c ) ;
}
static void lex_unget_unsave ( lex_t * lex , int c )
{
if ( c ! = STREAM_STATE_EOF & & c ! = STREAM_STATE_ERROR ) {
char d ;
stream_unget ( & lex - > stream , c ) ;
d = strbuffer_pop ( & lex - > saved_text ) ;
assert ( c = = d ) ;
}
}
static void lex_save_cached ( lex_t * lex )
@ -218,6 +253,7 @@ static void lex_save_cached(lex_t *lex)
@@ -218,6 +253,7 @@ static void lex_save_cached(lex_t *lex)
{
lex_save ( lex , lex - > stream . buffer [ lex - > stream . buffer_pos ] ) ;
lex - > stream . buffer_pos + + ;
lex - > stream . position + + ;
}
}
@ -247,7 +283,7 @@ static int32_t decode_unicode_escape(const char *str)
@@ -247,7 +283,7 @@ static int32_t decode_unicode_escape(const char *str)
static void lex_scan_string ( lex_t * lex , json_error_t * error )
{
char c ;
int c ;
const char * p ;
char * t ;
int i ;
@ -258,14 +294,15 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
@@ -258,14 +294,15 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
c = lex_get_save ( lex , error ) ;
while ( c ! = ' " ' ) {
if ( c = = ( char ) EOF ) {
lex_unget_unsave ( lex , c ) ;
if ( lex_eof ( lex ) )
if ( c = = STREAM_STATE_ERROR )
goto out ;
else if ( c = = STREAM_STATE_EOF ) {
error_set ( error , lex , " premature end of input " ) ;
goto out ;
}
else if ( ( unsigned char ) c < = 0x1F ) {
else if ( 0 < = c & & c < = 0x1F ) {
/* control character */
lex_unget_unsave ( lex , c ) ;
if ( c = = ' \n ' )
@ -281,7 +318,6 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
@@ -281,7 +318,6 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
c = lex_get_save ( lex , error ) ;
for ( i = 0 ; i < 4 ; i + + ) {
if ( ! isxdigit ( c ) ) {
lex_unget_unsave ( lex , c ) ;
error_set ( error , lex , " invalid escape " ) ;
goto out ;
}
@ -292,7 +328,6 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
@@ -292,7 +328,6 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
c = = ' f ' | | c = = ' n ' | | c = = ' r ' | | c = = ' t ' )
c = lex_get_save ( lex , error ) ;
else {
lex_unget_unsave ( lex , c ) ;
error_set ( error , lex , " invalid escape " ) ;
goto out ;
}
@ -308,7 +343,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
@@ -308,7 +343,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
- two \ uXXXX escapes ( length 12 ) forming an UTF - 16 surrogate pair
are converted to 4 bytes
*/
lex - > value . string = malloc ( lex - > saved_text . length + 1 ) ;
lex - > value . string = jsonp_ malloc( lex - > saved_text . length + 1 ) ;
if ( ! lex - > value . string ) {
/* this is not very nice, since TOKEN_INVALID is returned */
goto out ;
@ -398,10 +433,16 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
@@ -398,10 +433,16 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
return ;
out :
free ( lex - > value . string ) ;
jsonp_ free( lex - > value . string ) ;
}
static int lex_scan_number ( lex_t * lex , char c , json_error_t * error )
# if JSON_INTEGER_IS_LONG_LONG
# define json_strtoint strtoll
# else
# define json_strtoint strtol
# endif
static int lex_scan_number ( lex_t * lex , int c , json_error_t * error )
{
const char * saved_text ;
char * end ;
@ -430,32 +471,35 @@ static int lex_scan_number(lex_t *lex, char c, json_error_t *error)
@@ -430,32 +471,35 @@ static int lex_scan_number(lex_t *lex, char c, json_error_t *error)
}
if ( c ! = ' . ' & & c ! = ' E ' & & c ! = ' e ' ) {
long value ;
json_int_t value ;
lex_unget_unsave ( lex , c ) ;
saved_text = strbuffer_value ( & lex - > saved_text ) ;
value = strtol ( saved_text , & end , 10 ) ;
assert ( end = = saved_text + lex - > saved_text . length ) ;
if ( ( value = = LONG_MAX & & errno = = ERANGE ) | | value > INT_MAX ) {
error_set ( error , lex , " too big integer " ) ;
goto out ;
}
else if ( ( value = = LONG_MIN & & errno = = ERANGE ) | | value < INT_MIN ) {
errno = 0 ;
value = json_strtoint ( saved_text , & end , 10 ) ;
if ( errno = = ERANGE ) {
if ( value < 0 )
error_set ( error , lex , " too big negative integer " ) ;
else
error_set ( error , lex , " too big integer " ) ;
goto out ;
}
assert ( end = = saved_text + lex - > saved_text . length ) ;
lex - > token = TOKEN_INTEGER ;
lex - > value . integer = ( int ) value ;
lex - > value . integer = value ;
return 0 ;
}
if ( c = = ' . ' ) {
c = lex_get ( lex , error ) ;
if ( ! isdigit ( c ) )
if ( ! isdigit ( c ) ) {
lex_unget ( lex , c ) ;
goto out ;
}
lex_save ( lex , c ) ;
c = lex_get_save ( lex , error ) ;
@ -481,6 +525,7 @@ static int lex_scan_number(lex_t *lex, char c, json_error_t *error)
@@ -481,6 +525,7 @@ static int lex_scan_number(lex_t *lex, char c, json_error_t *error)
lex_unget_unsave ( lex , c ) ;
saved_text = strbuffer_value ( & lex - > saved_text ) ;
errno = 0 ;
value = strtod ( saved_text , & end ) ;
assert ( end = = saved_text + lex - > saved_text . length ) ;
@ -499,28 +544,25 @@ out:
@@ -499,28 +544,25 @@ out:
static int lex_scan ( lex_t * lex , json_error_t * error )
{
char c ;
int c ;
strbuffer_clear ( & lex - > saved_text ) ;
if ( lex - > token = = TOKEN_STRING ) {
free ( lex - > value . string ) ;
jsonp_ free( lex - > value . string ) ;
lex - > value . string = NULL ;
}
c = lex_get ( lex , error ) ;
while ( c = = ' ' | | c = = ' \t ' | | c = = ' \n ' | | c = = ' \r ' )
{
if ( c = = ' \n ' )
lex - > line + + ;
c = lex_get ( lex , error ) ;
}
if ( c = = ( char ) EOF ) {
if ( lex_eof ( lex ) )
if ( c = = STREAM_STATE_EOF ) {
lex - > token = TOKEN_EOF ;
else
goto out ;
}
if ( c = = STREAM_STATE_ERROR ) {
lex - > token = TOKEN_INVALID ;
goto out ;
}
@ -581,31 +623,29 @@ static char *lex_steal_string(lex_t *lex)
@@ -581,31 +623,29 @@ static char *lex_steal_string(lex_t *lex)
return result ;
}
static int lex_init ( lex_t * lex , get_func get , eof_func eof , void * data )
static int lex_init ( lex_t * lex , get_func get , void * data )
{
stream_init ( & lex - > stream , get , eof , data ) ;
stream_init ( & lex - > stream , get , data ) ;
if ( strbuffer_init ( & lex - > saved_text ) )
return - 1 ;
lex - > token = TOKEN_INVALID ;
lex - > line = 1 ;
return 0 ;
}
static void lex_close ( lex_t * lex )
{
if ( lex - > token = = TOKEN_STRING )
free ( lex - > value . string ) ;
jsonp_ free( lex - > value . string ) ;
strbuffer_close ( & lex - > saved_text ) ;
}
/*** parser ***/
static json_t * parse_value ( lex_t * lex , json_error_t * error ) ;
static json_t * parse_value ( lex_t * lex , size_t flags , json_error_t * error ) ;
static json_t * parse_object ( lex_t * lex , json_error_t * error )
static json_t * parse_object ( lex_t * lex , size_t flags , json_error_t * error )
{
json_t * object = json_object ( ) ;
if ( ! object )
@ -628,28 +668,36 @@ static json_t *parse_object(lex_t *lex, json_error_t *error)
@@ -628,28 +668,36 @@ static json_t *parse_object(lex_t *lex, json_error_t *error)
if ( ! key )
return NULL ;
if ( flags & JSON_REJECT_DUPLICATES ) {
if ( json_object_get ( object , key ) ) {
jsonp_free ( key ) ;
error_set ( error , lex , " duplicate object key " ) ;
goto error ;
}
}
lex_scan ( lex , error ) ;
if ( lex - > token ! = ' : ' ) {
free ( key ) ;
jsonp_ free( key ) ;
error_set ( error , lex , " ':' expected " ) ;
goto error ;
}
lex_scan ( lex , error ) ;
value = parse_value ( lex , error ) ;
value = parse_value ( lex , flags , error ) ;
if ( ! value ) {
free ( key ) ;
jsonp_ free( key ) ;
goto error ;
}
if ( json_object_set_nocheck ( object , key , value ) ) {
free ( key ) ;
jsonp_ free( key ) ;
json_decref ( value ) ;
goto error ;
}
json_decref ( value ) ;
free ( key ) ;
jsonp_ free( key ) ;
lex_scan ( lex , error ) ;
if ( lex - > token ! = ' , ' )
@ -670,7 +718,7 @@ error:
@@ -670,7 +718,7 @@ error:
return NULL ;
}
static json_t * parse_array ( lex_t * lex , json_error_t * error )
static json_t * parse_array ( lex_t * lex , size_t flags , json_error_t * error )
{
json_t * array = json_array ( ) ;
if ( ! array )
@ -681,7 +729,7 @@ static json_t *parse_array(lex_t *lex, json_error_t *error)
@@ -681,7 +729,7 @@ static json_t *parse_array(lex_t *lex, json_error_t *error)
return array ;
while ( lex - > token ) {
json_t * elem = parse_value ( lex , error ) ;
json_t * elem = parse_value ( lex , flags , error ) ;
if ( ! elem )
goto error ;
@ -710,7 +758,7 @@ error:
@@ -710,7 +758,7 @@ error:
return NULL ;
}
static json_t * parse_value ( lex_t * lex , json_error_t * error )
static json_t * parse_value ( lex_t * lex , size_t flags , json_error_t * error )
{
json_t * json ;
@ -743,11 +791,11 @@ static json_t *parse_value(lex_t *lex, json_error_t *error)
@@ -743,11 +791,11 @@ static json_t *parse_value(lex_t *lex, json_error_t *error)
break ;
case ' { ' :
json = parse_object ( lex , error ) ;
json = parse_object ( lex , flags , error ) ;
break ;
case ' [ ' :
json = parse_array ( lex , error ) ;
json = parse_array ( lex , flags , error ) ;
break ;
case TOKEN_INVALID :
@ -765,9 +813,9 @@ static json_t *parse_value(lex_t *lex, json_error_t *error)
@@ -765,9 +813,9 @@ static json_t *parse_value(lex_t *lex, json_error_t *error)
return json ;
}
static json_t * parse_json ( lex_t * lex , json_error_t * error )
static json_t * parse_json ( lex_t * lex , size_t flags , json_error_t * error )
{
error_init ( error ) ;
json_t * result ;
lex_scan ( lex , error ) ;
if ( lex - > token ! = ' [ ' & & lex - > token ! = ' { ' ) {
@ -775,7 +823,20 @@ static json_t *parse_json(lex_t *lex, json_error_t *error)
@@ -775,7 +823,20 @@ static json_t *parse_json(lex_t *lex, json_error_t *error)
return NULL ;
}
return parse_value ( lex , error ) ;
result = parse_value ( lex , flags , error ) ;
if ( ! result )
return NULL ;
if ( ! ( flags & JSON_DISABLE_EOF_CHECK ) ) {
lex_scan ( lex , error ) ;
if ( lex - > token ! = TOKEN_EOF ) {
error_set ( error , lex , " end of file expected " ) ;
json_decref ( result ) ;
result = NULL ;
}
}
return result ;
}
typedef struct
@ -794,75 +855,95 @@ static int string_get(void *data)
@@ -794,75 +855,95 @@ static int string_get(void *data)
else
{
stream - > pos + + ;
return c ;
return ( unsigned char ) c ;
}
}
static int string_eof ( void * data )
json_t * json_loads ( const char * string , size_t flags , json_error_t * error )
{
string_data_t * stream = ( string_data_t * ) data ;
return ( stream - > data [ stream - > pos ] = = ' \0 ' ) ;
lex_t lex ;
json_t * result ;
string_data_t stream_data ;
stream_data . data = string ;
stream_data . pos = 0 ;
if ( lex_init ( & lex , string_get , ( void * ) & stream_data ) )
return NULL ;
jsonp_error_init ( error , " <string> " ) ;
result = parse_json ( & lex , flags , error ) ;
lex_close ( & lex ) ;
return result ;
}
json_t * json_loads ( const char * string , json_error_t * error )
typedef struct
{
const char * data ;
size_t len ;
size_t pos ;
} buffer_data_t ;
static int buffer_get ( void * data )
{
char c ;
buffer_data_t * stream = data ;
if ( stream - > pos > = stream - > len )
return EOF ;
c = stream - > data [ stream - > pos ] ;
stream - > pos + + ;
return ( unsigned char ) c ;
}
json_t * json_loadb ( const char * buffer , size_t buflen , size_t flags , json_error_t * error )
{
lex_t lex ;
json_t * result ;
buffer_data_t stream_data ;
string_data_t stream_data = {
. data = string ,
. pos = 0
} ;
stream_data . data = buffer ;
stream_data . pos = 0 ;
stream_data . len = buflen ;
if ( lex_init ( & lex , string_get , string_eof , ( void * ) & stream_data ) )
if ( lex_init ( & lex , buffer_get , ( void * ) & stream_data ) )
return NULL ;
result = parse_json ( & lex , error ) ;
if ( ! result )
goto out ;
lex_scan ( & lex , error ) ;
if ( lex . token ! = TOKEN_EOF ) {
error_set ( error , & lex , " end of file expected " ) ;
json_decref ( result ) ;
result = NULL ;
}
jsonp_error_init ( error , " <buffer> " ) ;
result = parse_json ( & lex , flags , error ) ;
out :
lex_close ( & lex ) ;
return result ;
}
json_t * json_loadf ( FILE * input , json_error_t * error )
json_t * json_loadf ( FILE * input , size_t flags , json_error_t * error )
{
lex_t lex ;
const char * source ;
json_t * result ;
if ( lex_init ( & lex , ( get_func ) fgetc , ( eof_func ) feof , input ) )
if ( lex_init ( & lex , ( get_func ) fgetc , input ) )
return NULL ;
result = parse_json ( & lex , error ) ;
if ( ! result )
goto out ;
if ( input = = stdin )
source = " <stdin> " ;
else
source = " <stream> " ;
lex_scan ( & lex , error ) ;
if ( lex . token ! = TOKEN_EOF ) {
error_set ( error , & lex , " end of file expected " ) ;
json_decref ( result ) ;
result = NULL ;
}
jsonp_error_init ( error , source ) ;
result = parse_json ( & lex , flags , error ) ;
out :
lex_close ( & lex ) ;
return result ;
}
json_t * json_load_file ( const char * path , json_error_t * error )
json_t * json_load_file ( const char * path , size_t flags , json_error_t * error )
{
json_t * result ;
FILE * fp ;
error_init ( error ) ;
jsonp_ error_init( error , path ) ;
fp = fopen ( path , " r " ) ;
if ( ! fp )
@ -872,7 +953,7 @@ json_t *json_load_file(const char *path, json_error_t *error)
@@ -872,7 +953,7 @@ json_t *json_load_file(const char *path, json_error_t *error)
return NULL ;
}
result = json_loadf ( fp , error ) ;
result = json_loadf ( fp , flags , error ) ;
fclose ( fp ) ;
return result ;