Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Number support and cleanups #2

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions INSTALL
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
hg clone https://bitbucket.org/zserge/jsmn
cd jsmn
echo "CFLAGS += -fPIC -DJSMN_PARENT_LINKS" > config.mk
make
cd -

git clone https://github.com/yeryomin/libfmt
cd libfmt
make -f Makefile.dev
20 changes: 2 additions & 18 deletions README
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
/*************************************************************************
* Copyright (c) <2013, 2014> SAF TEHNIKA JSC (www.saftehnika.com)
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* For any questions or requests please contact: SW_LIC (at) SAFTEHNIKA.COM
*/

libfmt
======

Expand All @@ -20,7 +11,7 @@ Features

* Easy to use, high level API for jsmn parser
* Key/value JSON manipulations
* Type tests for object, array, string, bool/null or other primitive (number)
* Type tests for object, array, string, bool/null, number or other primitives
* Load data into parser from file or buffer (with normalization, to enable
further JSON manipulations)
* Dump generated/modified JSON into file or buffer, pretty dump support
Expand Down Expand Up @@ -52,22 +43,15 @@ libfmt depends on jsmn so get and compile that at first.
jsmn should be compiled with JSMN_PARENT_LINKS enabled.
Then just `make' if jsmn is in your library path or see Makefile.dev, change
jsmn library path and `make -f Makefile.dev'
See INSTALL also.

In your source code you should include libfmt.h and then compile with -lfmt,
setting -L and/or -I if needed.


On number type support
----------------------

JSON numbers are actually strings anyway so, at least for now, I didn't see any
point in converting strings into numbers inside the library itself.


TODO
----

* Autotools based configuration (search for jsmn library and headers)
* Number support (really?)
* see the code here and there
* etc tbd
1 change: 0 additions & 1 deletion examples/array_next.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ int main( void )
char *x = NULL;
int err = 0;

fmt_parser_init( &obj, 0 );
if ( fmt_load_string( b, strlen( b ), &obj ) ) {
printf( "failed to load string: %s\n", b );
fmt_free( &obj );
Expand Down
2 changes: 0 additions & 2 deletions examples/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ int main( int argc, char **argv )
* Every key, string, object, array or their element counts as a token.
* Parser performs better when it's size is smaller.
*/
fmt_parser_init( &p, 1000 );

if (fmt_load_file( file, &p, 0 ) < 0) {
printf("cannot load file\n");
fmt_free( &p );
Expand Down
2 changes: 0 additions & 2 deletions examples/delete.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ int main( int argc, char **argv )
* Every key, string, object, array or their element counts as a token.
* Parser performs better when it's size is smaller.
*/
fmt_parser_init( &p, 1000 );

if (fmt_load_file( file, &p, 0 ) < 0) {
printf("cannot load file\n");
fmt_free( &p );
Expand Down
2 changes: 0 additions & 2 deletions examples/empty_strings.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
int main( int argc, char **argv )
{
fmt_t p=FMT_NULL;
fmt_parser_init( &p, 10 );

char *sss = "{\"key\":\"\",\"key2\":\"\"}";
if (fmt_load_string( sss, strlen(sss), &p ) < 0) {
printf("cannot load string\n");
Expand Down
2 changes: 0 additions & 2 deletions examples/object_update.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
int main( int argc, char **argv )
{
fmt_t p=FMT_NULL;
fmt_parser_init( &p, 1 );

char *obj = NULL;
char *json = "{\"result\":{\"key\":\"value\"}}";

Expand Down
3 changes: 0 additions & 3 deletions examples/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ int main( int argc, char **argv )
* Every key, string, object, array or their element counts as a token.
* Parser performs better when it's size is smaller.
*/
fmt_parser_init( &p, 11 );

if (fmt_load_file( file, &p, 0 ) < 0) {
printf("cannot load file\n");
fmt_free( &p );
Expand Down Expand Up @@ -93,7 +91,6 @@ int main( int argc, char **argv )
// z[strlen(z)-1] = '\0';
// printf("%s\n", z);
fmt_t newp=FMT_NULL;
fmt_parser_init( &newp, 100 );
printf("Trying to load incomplete json\n");
err = fmt_load_string( z, strlen(z)-2, &newp );
printf("err: %i\n", err);
Expand Down
2 changes: 0 additions & 2 deletions examples/parse_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ int main( int argc, char **argv )
/* test if init macro worked */
fmt_free( &p );

fmt_parser_init( &p, 1 );

if ( (err = fmt_load_file( file, &p, 0 )) < 0) {
printf("cannot load file: %i\n", err);
fmt_free( &p );
Expand Down
17 changes: 10 additions & 7 deletions fmt_priv.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,15 @@ int parser_init( fmt_t *obj, uint32_t size )
return LIBFMT_ERR_NONE;
}

int fmt_load_normalized_new(char *iobuf, size_t size)
size_t fmt_load_normalized( char *iobuf, size_t size )
{
int i, shift = 0, inq = 0, escape = 0;
size_t i, shift = 0;
int inq = 0, escape = 0;
char symb;
char *start = iobuf;

if(!iobuf || size < 1)
return LIBFMT_ERR_GENERIC;
if ( !iobuf || size < 1 )
return 0;

for(i = 0; i < size; i++)
{
Expand All @@ -321,7 +323,7 @@ int fmt_load_normalized_new(char *iobuf, size_t size)

if(symb == '\0') {
if(inq)
return LIBFMT_ERR_NULLMET;
return 0;
else
break;
}
Expand All @@ -345,7 +347,7 @@ int fmt_load_normalized_new(char *iobuf, size_t size)
}
*(iobuf - shift) = 0;

return LIBFMT_ERR_NONE;
return (size_t)(start - iobuf - shift - 1);
}

int fmt_new( const char *s, int len, fmt_type_t type, fmt_t *res )
Expand Down Expand Up @@ -384,7 +386,8 @@ int fmt_new( const char *s, int len, fmt_type_t type, fmt_t *res )
case FMT_TYPE_STRING:
res->tok->type = JSMN_STRING;
break;
case FMT_TYPE_NUMBER:
case FMT_TYPE_DOUBLE:
case FMT_TYPE_INTEGER:
case FMT_TYPE_NULL:
case FMT_TYPE_BOOL:
res->tok->type = JSMN_PRIMITIVE;
Expand Down
2 changes: 1 addition & 1 deletion fmt_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ int find_last_subtok( fmt_t *obj, int parent_idx );
* @return LIBFMT_ERR_NONE on success, negative error code otherwise
*/
int parser_init( fmt_t *p, uint32_t size );
int fmt_load_normalized_new(char *iobuf, size_t size);
size_t fmt_load_normalized( char *iobuf, size_t size );

int fmt_new( const char *s, int len, fmt_type_t type, fmt_t *res );
fmt_t *fmt_new_alloc( const char *s, int len, fmt_type_t type );
Expand Down
103 changes: 88 additions & 15 deletions fmt_tests.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*************************************************************************
* Copyright (c) 2014 Roman Yeryomin <[email protected]>
* Copyright (c) <2013, 2014> SAF TEHNIKA JSC (www.saftehnika.com)
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -58,39 +59,111 @@ inline int fmt_is_string( fmt_t *obj )
return fmt_tok_is_string( obj->tok );
}

inline int fmt_is_primitive( fmt_t *obj, fmt_tok_t *tok, const char *val )
inline int fmt_is_primitive( fmt_t *obj, fmt_tok_t *where )
{
if ( !obj || !obj->js || !obj->tok )
return LIBFMT_FALSE;

if ( !val )
if ( !tok_is_type( (where? where : obj->tok), JSMN_PRIMITIVE ) )
return LIBFMT_FALSE;

fmt_tok_t *tmp_tok = obj->tok;
if ( tok )
tmp_tok = tok;
return LIBFMT_TRUE;
}

if ( !tok_is_type( tmp_tok, JSMN_PRIMITIVE ) )
inline int fmt_is_bool( fmt_t *obj, fmt_tok_t *where, int tf )
{
if ( !fmt_is_primitive( obj, where ) )
return LIBFMT_FALSE;

if ( !strncmp( obj->js + tmp_tok->start, val, strlen(val) ) )
if ( !strncmp( obj->js + (where? where : obj->tok)->start,
tf == LIBFMT_TRUE? "true" : "false",
tf == LIBFMT_TRUE? 4 : 5 ) )
return LIBFMT_TRUE;

return LIBFMT_FALSE;

}

inline int fmt_is_bool( fmt_t *obj, fmt_tok_t *tok, int tf )
inline int fmt_is_null( fmt_t *obj, fmt_tok_t *where )
{
if ( tf == LIBFMT_TRUE )
return fmt_is_primitive( obj, tok, "true" );
else
return fmt_is_primitive( obj, tok, "false" );
if ( !fmt_is_primitive( obj, where ) )
return LIBFMT_FALSE;

if ( !strncmp( obj->js + (where? where : obj->tok)->start, "null", 4 ) )
return LIBFMT_TRUE;

return LIBFMT_FALSE;
}

inline int fmt_is_null( fmt_t *obj, fmt_tok_t *tok )
inline int fmt_is_number( fmt_t *obj, fmt_tok_t *where, fmt_num_t *res )
{
return fmt_is_primitive( obj, tok, "null" );
if ( !fmt_is_primitive( obj, where ) )
return LIBFMT_FALSE;

char *p;
double dtmp = 0;
long long itmp = 0;
char *num = NULL;

int type = obj->tok->type;
size_t start = obj->tok->start;
size_t end = obj->tok->end;
size_t len = 0;
size_t i;

if ( where ) {
type = where->type;
start = where->start;
end = where->end;
}
len = end - start;

num = (char *)malloc( len + 1 );
if ( !num )
return LIBFMT_FALSE;

memcpy( num, obj->js + start, len );
num[len] = '\0';

/* jsmn doesn't destinguish number types,
* so we have to try to do it ourselves */
if ( type == FMT_TYPE_UNDEF ) {
type = FMT_TYPE_INTEGER;
for( i = 0; num[i]; i++ ) {
if ( num[i] == '.' ) {
type = FMT_TYPE_DOUBLE;
break;
}
}
}

switch (type) {
case FMT_TYPE_DOUBLE:
dtmp = strtod( num, &p );
if ( res )
res->d = dtmp;
break;
case FMT_TYPE_INTEGER:
itmp = strtoll( num, &p, 10 );
if ( res )
res->i = itmp;
break;
}

if ( *p == '\0' ) {
switch (type) {
case FMT_TYPE_DOUBLE:
(where? where : obj->tok)->type = FMT_TYPE_DOUBLE;
break;
case FMT_TYPE_INTEGER:
(where? where : obj->tok)->type = FMT_TYPE_INTEGER;
break;
}
free( num );
return LIBFMT_TRUE;
}

free( num );
return LIBFMT_FALSE;
}

inline int fmt_tok_valid( fmt_tok_t *tok )
Expand Down
Loading