Guest User

Untitled

a guest
Sep 4th, 2013
454
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 23.54 KB | None | 0 0
  1. // Originally by Exolent[jNr] (https://forums.alliedmods.net/showthread.php?t=189772)
  2. // Ported from AMXX pawn to SourceMod sourcepawn by Nicholas Hastings
  3. // Decoding fixed by Nikkii (https://forums.alliedmods.net/showpost.php?p=1914836&postcount=10)
  4.  
  5. #if defined _json_included
  6.     #endinput
  7. #endif
  8.  
  9. #define _json_included
  10.  
  11. #define JSON_KEY_SIZE   512
  12. #define JSON_STR_SIZE   512
  13.  
  14. //#define JSON_DEBUG
  15.  
  16. #if defined JSON_DEBUG
  17.     #define JSON_VAR new
  18.     #define JSON_FUNC
  19. #else
  20.     #define JSON_VAR stock
  21.     #define JSON_FUNC stock
  22. #endif
  23.  
  24. JSON_VAR String:__json_key[ JSON_KEY_SIZE ];
  25. JSON_VAR String:__json_key2[ JSON_KEY_SIZE ];
  26. JSON_VAR String:__json_string[ JSON_STR_SIZE ];
  27.  
  28. enum JSON
  29. {
  30.     JSON_INVALID = 0,
  31.    
  32.     JSON_Cell,
  33.     JSON_Float,
  34.     JSON_Unsigned,
  35.     JSON_String,
  36.     JSON_Object
  37. };
  38.  
  39. JSON_FUNC JSON:json_create(bool:is_array=false)
  40. {
  41.     new Handle:object = CreateTrie( );
  42.    
  43.     new Handle:data = CreateTrie( );
  44.     new Handle:keys = CreateArray( JSON_KEY_SIZE );
  45.    
  46.     SetTrieValue( object, "data", data );
  47.     SetTrieValue( object, "keys", keys );
  48.    
  49.     if( is_array )
  50.     {
  51.         SetTrieValue( object, "is_array", true );
  52.     }
  53.    
  54.     return JSON:object;
  55. }
  56.  
  57. JSON_FUNC JSON:json_from_array(const any:array[], size, JSON:types[]={JSON_INVALID}, JSON:force_type=JSON_INVALID)
  58. {
  59.     new JSON:json = json_create( .is_array = true );
  60.    
  61.     if( json == JSON_INVALID )
  62.     {
  63.         return JSON_INVALID;
  64.     }
  65.    
  66.     new String:key[ 12 ];
  67.    
  68.     for( new i = 0; i < size; i++ )
  69.     {
  70.         IntToString( i, key, sizeof( key ) );
  71.        
  72.         json_set_cell( json, key, array[ i ], ( force_type ? force_type : types[ i ] ) );
  73.     }
  74.    
  75.     return json;
  76. }
  77.  
  78. JSON_FUNC JSON:json_from_array2(Handle:array, size=-1, {Handle,JSON}:types, bool:force_type=false)
  79. {
  80.     if( array == INVALID_HANDLE )
  81.     {
  82.         return JSON_INVALID;
  83.     }
  84.    
  85.     if( size < 0 )
  86.     {
  87.         size = GetArraySize( array );
  88.     }
  89.    
  90.     if( !size )
  91.     {
  92.         return JSON_INVALID;
  93.     }
  94.    
  95.     new JSON:json = json_create( .is_array = true );
  96.    
  97.     if( json == JSON_INVALID )
  98.     {
  99.         return JSON_INVALID;
  100.     }
  101.    
  102.     new String:key[ 12 ];
  103.    
  104.     for( new i = 0; i < size; i++ )
  105.     {
  106.         IntToString( i, key, sizeof(key) );
  107.        
  108.         json_set_cell( json, key, GetArrayCell( array, i ), JSON:( force_type ? types : GetArrayCell( types, i ) ) );
  109.     }
  110.    
  111.     return json;
  112. }
  113.  
  114. JSON_FUNC bool:json_set_cell(JSON:object, const String:key[], any:value, JSON:type=JSON_Cell)
  115. {
  116.     if( object == JSON_INVALID )
  117.     {
  118.         return false;
  119.     }
  120.    
  121.     new Handle:data, Handle:keys;
  122.    
  123.     GetTrieValue( Handle:object, "data", data );
  124.     GetTrieValue( Handle:object, "keys", keys );
  125.    
  126.     if( !__json_delete( data, key ) )
  127.     {
  128.         PushArrayString( keys, key );
  129.     }
  130.    
  131.     new Handle:info = CreateTrie( );
  132.    
  133.     SetTrieValue( info, "type", type );
  134.     SetTrieValue( info, "value", value );
  135.    
  136.     SetTrieValue( data, key, info );
  137.    
  138.     return true;
  139. }
  140.  
  141. JSON_FUNC bool:json_set_array(JSON:object, const String:key[], const any:array[], size, JSON:types[]={JSON_INVALID}, JSON:force_type=JSON_INVALID)
  142. {
  143.     if( object == JSON_INVALID )
  144.     {
  145.         return false;
  146.     }
  147.    
  148.     new JSON:child = json_from_array( array, size, types, force_type );
  149.    
  150.     return ( child == JSON_INVALID ) ? false : json_set_cell( object, key, child, JSON_Object );
  151. }
  152.  
  153. JSON_FUNC bool:json_set_array2(JSON:object, const String:key[], Handle:array, size=-1, {Handle,JSON}:types, bool:force_type=false)
  154. {
  155.     if( object == JSON_INVALID )
  156.     {
  157.         return false;
  158.     }
  159.    
  160.     new JSON:child = json_from_array2( array, size, types, force_type );
  161.    
  162.     return ( child == JSON_INVALID ) ? false : json_set_cell( object, key, child, JSON_Object );
  163. }
  164.  
  165. JSON_FUNC bool:json_set_string(JSON:object, const String:key[], const String:string[])
  166. {
  167.     if( object == JSON_INVALID )
  168.     {
  169.         return false;
  170.     }
  171.    
  172.     new Handle:data, Handle:keys;
  173.    
  174.     GetTrieValue( Handle:object, "data", data );
  175.     GetTrieValue( Handle:object, "keys", keys );
  176.    
  177.     if( !__json_delete( data, key ) )
  178.     {
  179.         PushArrayString( keys, key );
  180.     }
  181.    
  182.     new Handle:info = CreateTrie( );
  183.    
  184.     SetTrieValue( info, "type", JSON_String );
  185.     SetTrieString( info, "value", string );
  186.    
  187.     SetTrieValue( data, key, info );
  188.    
  189.     return true;
  190. }
  191.  
  192. JSON_FUNC bool:json_get_cell(JSON:object, const String:key[], &any:value, &JSON:type=JSON_Cell)
  193. {
  194.     if( object == JSON_INVALID )
  195.     {
  196.         return false;
  197.     }
  198.    
  199.     new Handle:data;
  200.     GetTrieValue( Handle:object, "data", data );
  201.    
  202.     new Handle:info;
  203.    
  204.     if( !GetTrieValue( data, key, info ) )
  205.     {
  206.         return false;
  207.     }
  208.    
  209.     GetTrieValue( info, "type", type );
  210.    
  211.     if( type != JSON_Cell && type != JSON_Unsigned && type != JSON_Float && type != JSON_Object )
  212.     {
  213.         return false;
  214.     }
  215.    
  216.     GetTrieValue( info, "value", value );
  217.    
  218.     return true;
  219. }
  220.  
  221. JSON_FUNC bool:json_get_float(JSON:object, const String:key[], &Float:value)
  222. {
  223.     if( object == JSON_INVALID )
  224.     {
  225.         return false;
  226.     }
  227.    
  228.     new Handle:data;
  229.     GetTrieValue( Handle:object, "data", data );
  230.    
  231.     new Handle:info;
  232.    
  233.     if( !GetTrieValue( data, key, info ) )
  234.     {
  235.         return false;
  236.     }
  237.    
  238.     GetTrieValue( info, "type", type );
  239.    
  240.     if( type != JSON_Cell && type != JSON_Unsigned && type != JSON_Float )
  241.     {
  242.         return false;
  243.     }
  244.    
  245.     GetTrieValue( info, "value", value );
  246.    
  247.     return true;
  248. }
  249.  
  250. JSON_FUNC bool:json_get_array(JSON:object, const String:key[], any:output[], outputsize, &readsize, JSON:types[])
  251. {
  252.     if( object == JSON_INVALID )
  253.     {
  254.         return false;
  255.     }
  256.    
  257.     new Handle:data;
  258.     GetTrieValue( Handle:object, "data", data );
  259.    
  260.     new Handle:info;
  261.    
  262.     if( !GetTrieValue( data, key, info ) )
  263.     {
  264.         return false;
  265.     }
  266.    
  267.     new JSON:type;
  268.     GetTrieValue( info, "type", type );
  269.    
  270.     if( type != JSON_Object )
  271.     {
  272.         return false;
  273.     }
  274.    
  275.     new JSON:array;
  276.     GetTrieValue( data, "value", array );
  277.    
  278.     new String:num[12];
  279.     new index;
  280.    
  281.     while( index < outputsize )
  282.     {
  283.         IntToString( index, num, sizeof(num) );
  284.        
  285.         if( !json_get_cell( array, num, output[ index ], types[ index ] ) )
  286.         {
  287.             break;
  288.         }
  289.        
  290.         index++;
  291.     }
  292.  
  293.     readsize = index + 1;
  294.    
  295.     return ( index > 0 );
  296. }
  297.  
  298. JSON_FUNC bool:json_get_array2(JSON:object, const String:key[], &Handle:output, size, &Handle:types)
  299. {
  300.     if( object == JSON_INVALID )
  301.     {
  302.         return false;
  303.     }
  304.    
  305.     new Handle:data;
  306.     GetTrieValue( Handle:object, "data", data );
  307.    
  308.     new Handle:info;
  309.    
  310.     if( !GetTrieValue( data, key, info ) )
  311.     {
  312.         return false;
  313.     }
  314.    
  315.     new JSON:type;
  316.     GetTrieValue( info, "type", type );
  317.    
  318.     if( type != JSON_Object )
  319.     {
  320.         return false;
  321.     }
  322.    
  323.     new JSON:array;
  324.     GetTrieValue( data, "value", array );
  325.    
  326.     new num[ 12 ];
  327.     IntToString( 0, num, sizeof(num) );
  328.    
  329.     new index, value;
  330.    
  331.     while( index < size )
  332.     {
  333.         IntToString( index, num, sizeof(num) );
  334.        
  335.         if( !json_get_cell( array, num, value, type ) )
  336.         {
  337.             break;
  338.         }
  339.        
  340.         ArrayPushCell( output, value );
  341.         ArrayPushCell( types, type );
  342.        
  343.         index++;
  344.     }
  345.    
  346.     return ( index > 0 );
  347. }
  348.  
  349. JSON_FUNC bool:json_get_string(JSON:object, const String:key[], String:output[], len)
  350. {
  351.     if( object == JSON_INVALID )
  352.     {
  353.         return false;
  354.     }
  355.    
  356.     new Handle:data;
  357.     GetTrieValue( Handle:object, "data", data );
  358.    
  359.     new Handle:info;
  360.    
  361.     if( !GetTrieValue( data, key, info ) )
  362.     {
  363.         return false;
  364.     }
  365.    
  366.     new JSON:type;
  367.     GetTrieValue( info, "type", type );
  368.    
  369.     if( type != JSON_String )
  370.     {
  371.         return false;
  372.     }
  373.    
  374.     GetTrieString( info, "value", output, len );
  375.    
  376.     return true;
  377. }
  378.  
  379. JSON_FUNC JSON:json_get_type(JSON:object, const String:key[])
  380. {
  381.     if( object == JSON_INVALID )
  382.     {
  383.         return JSON_INVALID;
  384.     }
  385.    
  386.     new Handle:data;
  387.     GetTrieValue( Handle:object, "data", data );
  388.    
  389.     new Handle:info;
  390.    
  391.     if( !GetTrieValue( data, key, info ) )
  392.     {
  393.         return JSON_INVALID;
  394.     }
  395.    
  396.     new JSON:type;
  397.     GetTrieValue( info, "type", type );
  398.    
  399.     return type;
  400. }
  401.  
  402. JSON_FUNC bool:json_delete(JSON:object, const String:key[])
  403. {
  404.     if( object == JSON_INVALID )
  405.     {
  406.         return false;
  407.     }
  408.    
  409.     new Handle:data, Handle:keys;
  410.    
  411.     GetTrieValue( Handle:object, "data", data );
  412.     GetTrieValue( Handle:object, "keys", keys );
  413.    
  414.     new size = GetArraySize( keys );
  415.    
  416.     return __json_delete( data, key, keys, size );
  417. }
  418.  
  419. JSON_FUNC bool:__json_delete(Handle:data, const String:key[], Handle:keys=INVALID_HANDLE, &size=0)
  420. {
  421.     new Handle:info;
  422.    
  423.     if( GetTrieValue( data, key, info ) )
  424.     {
  425.         RemoveFromTrie( data, key );
  426.        
  427.         if( keys != INVALID_HANDLE && size > 0 )
  428.         {
  429.             for( new i = 0; i < size; i++ )
  430.             {
  431.                 GetArrayString( keys, i, __json_key2, sizeof(__json_key2) );
  432.                
  433.                 if( !strcmp( __json_key2, key ) )
  434.                 {
  435.                     RemoveFromArray( keys, i-- );
  436.                     size--;
  437.                 }
  438.             }
  439.         }
  440.        
  441.         new JSON:type;
  442.         GetTrieValue( info, "type", type );
  443.        
  444.         if( type == JSON_Object )
  445.         {
  446.             new JSON:object;
  447.             GetTrieValue( info, "value", object );
  448.            
  449.             json_destroy( object );
  450.         }
  451.        
  452.         CloseHandle( info );
  453.        
  454.         return true;
  455.     }
  456.    
  457.     return false;
  458. }
  459.  
  460. JSON_FUNC JSON:json_decode(const String:string[], &pos=0, len=0)
  461. {
  462.     if( !len && !( len = strlen( string ) ) )
  463.     {
  464.         return JSON_INVALID;
  465.     }
  466.    
  467.     while( pos < len && isspace( string[ pos ] ) )
  468.     {
  469.         pos++;
  470.     }
  471.    
  472.     while( len > 0 && isspace( string[ len - 1 ] ) )
  473.     {
  474.         len--;
  475.     }
  476.    
  477.     if( !len || pos >= len )
  478.     {
  479.         return JSON_INVALID;
  480.     }
  481.    
  482.     new JSON:json = JSON_INVALID;
  483.    
  484.     switch( string[ pos ] )
  485.     {
  486.         case '{':
  487.         {
  488.             json = json_create( );
  489.            
  490.             new key_start, key_len;
  491.             new bool:escaped;
  492.             new JSON:child;
  493.             new Handle:array;
  494.             new Handle:types;
  495.             new string_start;
  496.             new string_len;
  497.            
  498.             while( ++pos < len && isspace( string[ pos ] ) ) { }
  499.            
  500.             while( json )
  501.             {  
  502.                 if( pos >= len || string[ pos ] != '"' )
  503.                 {
  504.                     json_destroy( json );
  505.                     return JSON_INVALID;
  506.                 }
  507.                
  508.                 key_start = pos + 1;
  509.                 escaped = false;
  510.                
  511.                 while( ++pos <= len )
  512.                 {
  513.                     if( pos == len )
  514.                     {
  515.                         json_destroy( json );
  516.                         return JSON_INVALID;
  517.                     }
  518.                    
  519.                     if( escaped )
  520.                     {
  521.                         escaped = false;
  522.                     }
  523.                     else if( string[ pos ] == '\\' )
  524.                     {
  525.                         escaped = true;
  526.                     }
  527.                     else if( string[ pos ] == '"' )
  528.                     {
  529.                         break;
  530.                     }
  531.                 }
  532.                
  533.                 key_len = pos - key_start + 1;
  534.                
  535.                 if( !key_len )
  536.                 {
  537.                     json_destroy( json );
  538.                     return JSON_INVALID;
  539.                 }
  540.                
  541.                 while( ++pos < len && isspace( string[ pos ] ) ) { }
  542.                
  543.                 if( string[ pos ] != ':' )
  544.                 {
  545.                     json_destroy( json );
  546.                     return JSON_INVALID;
  547.                 }
  548.                
  549.                 while( ++pos < len && isspace( string[ pos ] ) ) { }
  550.                
  551.                 switch( string[ pos ] )
  552.                 {
  553.                     case '{':
  554.                     {
  555.                         // Read JSON
  556.                         child = json_decode( string, pos, len );
  557.                        
  558.                         if( child == JSON_INVALID )
  559.                         {
  560.                             json_destroy( json );
  561.                             return JSON_INVALID;
  562.                         }
  563.                        
  564.                         strcopy( __json_key, min( sizeof( __json_key ), key_len ), string[ key_start ] );
  565.                        
  566.                         json_set_cell( json, __json_key, child, JSON_Object );
  567.                     }
  568.                     case '[':
  569.                     {
  570.                         // Read array
  571.                         array = __json_read_array( string, len, pos, string_len, types );
  572.                        
  573.                         if( array == INVALID_HANDLE )
  574.                         {
  575.                             json_destroy( json );
  576.                             return JSON_INVALID;
  577.                         }
  578.                        
  579.                         strcopy( __json_key, min( sizeof( __json_key ), key_len ), string[ key_start ] );
  580.                        
  581.                         json_set_array2( json, __json_key, array, string_len, types, .force_type = false );
  582.                        
  583.                         CloseHandle( array );
  584.                         CloseHandle( types );
  585.                     }
  586.                     case '"':
  587.                     {
  588.                         // Read string
  589.                         escaped = false;
  590.                        
  591.                         string_len = 0;
  592.                         __json_string[ 0 ] = EOS;
  593.                        
  594.                         while( ++pos <= len )
  595.                         {
  596.                             if( pos == len )
  597.                             {
  598.                                 json_destroy( json );
  599.                                 return JSON_INVALID;
  600.                             }
  601.                            
  602.                             if( escaped )
  603.                             {
  604.                                 escaped = false;
  605.                                
  606.                                 if( string_len < sizeof( __json_string ) )
  607.                                 {
  608.                                     __json_string[ string_len++ ] = string[ pos ];
  609.                                 }
  610.                             }
  611.                             else if( string[ pos ] == '\\' )
  612.                             {
  613.                                 escaped = true;
  614.                             }
  615.                             else if( string[ pos ] == '"' )
  616.                             {
  617.                                 pos++;
  618.                                 break;
  619.                             }
  620.                             else
  621.                             {
  622.                                
  623.                                 if( string_len < sizeof( __json_string ) )
  624.                                 {
  625.                                     __json_string[ string_len++ ] = string[ pos ];
  626.                                 }
  627.                             }
  628.                         }
  629.                        
  630.                         if( !string_len )
  631.                         {
  632.                             json_destroy( json );
  633.                             return JSON_INVALID;
  634.                         }
  635.                        
  636.                         __json_string[ string_len ] = EOS;
  637.                        
  638.                         strcopy( __json_key, min( sizeof( __json_key ), key_len ), string[ key_start ] );
  639.                        
  640.                         json_set_string( json, __json_key, __json_string );
  641.                     }
  642.                     default:
  643.                     {
  644.                         // Read true/false, integer, or float
  645.                         string_start = pos;
  646.                        
  647.                         while(pos < len && !isspace( string[ pos ] ) && !iscontrol( string[ pos ] ) ) {
  648.                             pos++;
  649.                         }
  650.                        
  651.                         string_len = pos - string_start;
  652.                         __json_string[string_len + 1] = '\0';
  653.                        
  654.                         strcopy( __json_string, min( sizeof( __json_string ), string_len == -1 ? string_len : string_len + 1 ), string[ string_start ] );
  655.                        
  656.                         if( !strcmp( __json_string, "true", false ) || !strcmp( __json_string, "false", false ) )
  657.                         {
  658.                             strcopy( __json_key, min( sizeof( __json_key ), key_len ), string[ key_start ] );
  659.                            
  660.                             json_set_cell( json, __json_key, ( __json_string[ 0 ] == 't' || __json_string[ 0 ] == 'T' ) );
  661.                         }
  662.                         else if( is_str_num( __json_string ) )
  663.                         {
  664.                             strcopy( __json_key, min( sizeof( __json_key ), key_len ), string[ key_start ] );
  665.                            
  666.                             json_set_cell( json, __json_key, StringToInt( __json_string ) );
  667.                         }
  668.                         else
  669.                         {
  670.                             string_len = StrContains( __json_string, "." );
  671.                            
  672.                             if( string_len <= 0 || !is_str_num( __json_string[ string_len + 1 ] ) )
  673.                             {
  674.                                 json_destroy( json );
  675.                                 return JSON_INVALID;
  676.                             }
  677.                            
  678.                             __json_string[ string_len ] = EOS;
  679.                            
  680.                             string_start = _:!!( __json_string[ 0 ] == '-' );
  681.                            
  682.                             if( !is_str_num( __json_string[ string_start ] ) )
  683.                             {
  684.                                 json_destroy( json );
  685.                                 return JSON_INVALID;
  686.                             }
  687.                            
  688.                             __json_string[ string_len ] = '.';
  689.                            
  690.                             strcopy( __json_key, min( sizeof( __json_key ), key_len ), string[ key_start ] );
  691.                            
  692.                             json_set_cell( json, __json_key, StringToFloat( __json_string ), JSON_Float );
  693.                         }
  694.                     }
  695.                 }
  696.                
  697.                 while( pos < len && isspace( string[ pos ] ) )
  698.                 {
  699.                     pos++;
  700.                 }
  701.                
  702.                 if( string[ pos ] == '}' )
  703.                 {
  704.                     pos++;
  705.                     break;
  706.                 }
  707.                 else if( string[ pos ] != ',' )
  708.                 {
  709.                     json_destroy( json );
  710.                     return JSON_INVALID;
  711.                 }
  712.                
  713.                 while( ++pos < len && isspace( string[ pos ] ) ) { }
  714.             }
  715.         }
  716.         case '[':
  717.         {
  718.             // Read array
  719.             new size;
  720.             new Handle:types;
  721.            
  722.             new Handle:array = __json_read_array( string, len, pos, size, types );
  723.            
  724.             if( array == INVALID_HANDLE )
  725.             {
  726.                 return JSON_INVALID;
  727.             }
  728.            
  729.             json = json_from_array2( array, size, types );
  730.            
  731.             CloseHandle( array );
  732.             CloseHandle( types );
  733.         }
  734.     }
  735.    
  736.     return json;
  737. }
  738.  
  739. JSON_FUNC Handle:__json_read_array(const String:string[], len, &pos, &size, &Handle:types)
  740. {
  741.     new Handle:output = CreateArray( JSON_STR_SIZE );
  742.     size = 0;
  743.     types = CreateArray( );
  744.    
  745.     new bool:failed;
  746.    
  747.     new JSON:child;
  748.     new Handle:array;
  749.     new array_size;
  750.     new Handle:array_types;
  751.     new bool:escaped;
  752.     new string_start;
  753.     new string_len;
  754.    
  755.     while( ++pos <= len )
  756.     {
  757.         while( pos < len && isspace( string[ pos ] ) )
  758.         {
  759.             pos++;
  760.         }
  761.        
  762.         if( pos == len )
  763.         {
  764.             //PrintToServer("Position reached length in __json_read_array");
  765.             failed = true;
  766.             break;
  767.         }
  768.        
  769.         switch( string[ pos ] )
  770.         {
  771.             case ']':
  772.             {
  773.                 pos++;
  774.                 break;
  775.             }
  776.             case '{':
  777.             {
  778.                 child = json_decode( string, pos, len );
  779.                
  780.                 if( child == JSON_INVALID )
  781.                 {
  782.                     //PrintToServer("Unable to decode child in __json_read_array");
  783.                     failed = true;
  784.                     break;
  785.                 }
  786.                
  787.                 PushArrayCell( output, child );
  788.                 PushArrayCell( types, JSON_Object );
  789.                 size++;
  790.             }
  791.             case '[':
  792.             {
  793.                 array = __json_read_array( string, len, pos, array_size, array_types );
  794.                
  795.                 if( array == INVALID_HANDLE )
  796.                 {
  797.                     //PrintToServer("Unable to read child array in __json_read_array");
  798.                     failed = true;
  799.                     break;
  800.                 }
  801.                
  802.                 PushArrayCell( output, json_from_array2( array, array_size, array_types ) );
  803.                 PushArrayCell( types, JSON_Object );
  804.                 size++;
  805.                
  806.                 CloseHandle( array );
  807.                 CloseHandle( array_types );
  808.             }
  809.             case '"':
  810.             {
  811.                 // Read string
  812.                 escaped = false;
  813.                
  814.                 string_len = 0;
  815.                 __json_string[ 0 ] = EOS;
  816.                
  817.                 while( ++pos <= len )
  818.                 {
  819.                     if( pos == len )
  820.                     {
  821.                         //PrintToServer("Unable to read string (pos==len) in __json_read_array");
  822.                         failed = true;
  823.                         break;
  824.                     }
  825.                    
  826.                     if( escaped )
  827.                     {
  828.                         escaped = false;
  829.                        
  830.                         if( string_len < sizeof( __json_string ) )
  831.                         {
  832.                             __json_string[ string_len++ ] = string[ pos ];
  833.                         }
  834.                     }
  835.                     else if( string[ pos ] == '\\' )
  836.                     {
  837.                         escaped = true;
  838.                     }
  839.                     else if( string[ pos ] == '"' )
  840.                     {
  841.                         pos++;
  842.                         break;
  843.                     }
  844.                     else
  845.                     {
  846.                        
  847.                         if( string_len < sizeof( __json_string ) )
  848.                         {
  849.                             __json_string[ string_len++ ] = string[ pos ];
  850.                         }
  851.                     }
  852.                 }
  853.                
  854.                 if( failed )
  855.                     break;
  856.                
  857.                 if( !string_len )
  858.                 {
  859.                     //PrintToServer("Unable to read string (!string_len) in __json_read_array");
  860.                     failed = true;
  861.                     break;
  862.                 }
  863.                
  864.                 PushArrayString( output, __json_string );
  865.                 PushArrayCell( types, JSON_String );
  866.                 size++;
  867.             }
  868.             default:
  869.             {
  870.                 // Read true/false, integer, or float
  871.                 string_start = pos;
  872.                
  873.                 while( pos < len && !isspace( string[ pos ] ) && !iscontrol( string[ pos ]) ) {
  874.                     pos++;
  875.                 }
  876.                
  877.                 string_len = pos - string_start + 1;
  878.                
  879.                 strcopy( __json_string, min( sizeof( __json_string ), string_len ), string[ string_start ] );
  880.                
  881.                 if( !strcmp( __json_string, "true", false ) || !strcmp( __json_string, "false", false ) )
  882.                 {
  883.                     PushArrayCell( output, ( __json_string[ 0 ] == 't' || __json_string[ 0 ] == 'T' ) );
  884.                     PushArrayCell( types, JSON_Cell );
  885.                     size++;
  886.                 }
  887.                 else if( is_str_num( __json_string ) )
  888.                 {
  889.                     PushArrayCell( output, StringToInt( __json_string ) );
  890.                     PushArrayCell( types, JSON_Cell );
  891.                     size++;
  892.                 }
  893.                 else
  894.                 {
  895.                     string_len = StrContains( __json_string, "." );
  896.                    
  897.                     if( string_len <= 0 || !is_str_num( __json_string[ string_len + 1 ] ) )
  898.                     {
  899.                         //PrintToServer("Unable to read float (string_len <= 0 || !is_str_num) in __json_read_array - %i - '%s' - %i", string_len, __json_string, is_str_num( __json_string ));
  900.                         failed = true;
  901.                         break;
  902.                     }
  903.                    
  904.                     __json_string[ string_len ] = EOS;
  905.                    
  906.                     string_start = _:!!( __json_string[ 0 ] == '-' );
  907.                    
  908.                     if( !is_str_num( __json_string[ string_start ] ) )
  909.                     {
  910.                         //PrintToServer("Unable to read float (!is_str_num) in __json_read_array");
  911.                         failed = true;
  912.                         break;
  913.                     }
  914.                    
  915.                     __json_string[ string_len ] = '.';
  916.                    
  917.                     PushArrayCell( output, StringToFloat( __json_string ) );
  918.                     PushArrayCell( types, JSON_Float );
  919.                     size++;
  920.                 }
  921.             }
  922.         }
  923.        
  924.         while( pos < len && isspace( string[ pos ] ) )
  925.         {
  926.             pos++;
  927.         }
  928.        
  929.         if( string[ pos ] == ']' )
  930.         {
  931.             pos++;
  932.             break;
  933.         }
  934.         else if( string[ pos ] != ',' )
  935.         {
  936.             //PrintToServer("Invalid character in __json_read_array, got '%c' expected ','", string[ pos ]);
  937.             failed = true;
  938.             break;
  939.         }
  940.     }
  941.    
  942.     if( failed )
  943.     {
  944.         while( --size >= 0 )
  945.         {
  946.             if( GetArrayCell( types, size ) == JSON_Object )
  947.             {
  948.                 child = GetArrayCell( output, size );
  949.                
  950.                 json_destroy( child );
  951.             }
  952.         }
  953.        
  954.         CloseHandle( output );
  955.         CloseHandle( types );
  956.        
  957.         output = INVALID_HANDLE;
  958.     }
  959.    
  960.     return output;
  961. }
  962.  
  963. JSON_FUNC json_encode(JSON:object, String:output[], len)
  964. {
  965.     if( object == JSON_INVALID )
  966.     {
  967.         return 0;
  968.     }
  969.    
  970.     new Handle:data, Handle:keys;
  971.    
  972.     GetTrieValue( Handle:object, "data", data );
  973.     GetTrieValue( Handle:object, "keys", keys );
  974.    
  975.     new dummy;
  976.     new bool:is_array = GetTrieValue( Handle:object, "is_array", dummy );
  977.    
  978.     new pos = strcopy( output, len, is_array ? "[" : "{" );
  979.    
  980.     new size = GetArraySize( keys );
  981.    
  982.     new Handle:info;
  983.     new bool:first = true;
  984.     new JSON:type;
  985.     new value;
  986.    
  987.     for( new i = 0; i < size; i++ )
  988.     {
  989.         GetArrayString( keys, i, __json_key, sizeof( __json_key ) );
  990.        
  991.         if( GetTrieValue( data, __json_key, info ) )
  992.         {
  993.             if( first )
  994.             {
  995.                 first = false;
  996.             }
  997.             else
  998.             {
  999.                 pos += strcopy( output[ pos ], len - pos, "," );
  1000.             }
  1001.            
  1002.             if( !is_array )
  1003.             {
  1004.                 pos += strcopy( output[ pos ], len - pos, "\"" );
  1005.                
  1006.                 pos += json_escape( __json_key, output[ pos ], len - pos );
  1007.                
  1008.                 pos += strcopy( output[ pos ], len - pos, "\":" );
  1009.             }
  1010.            
  1011.             GetTrieValue( info, "type", type );
  1012.            
  1013.             switch( type )
  1014.             {
  1015.                 case JSON_Cell:
  1016.                 {
  1017.                     GetTrieValue( info, "value", value );
  1018.                    
  1019.                     pos += FormatEx( output[ pos ], len - pos, "%d", value );
  1020.                 }
  1021.                 case JSON_Unsigned:
  1022.                 {
  1023.                     GetTrieValue( info, "value", value );
  1024.                    
  1025.                     pos += FormatEx( output[ pos ], len - pos, "%u", value );
  1026.                 }
  1027.                 case JSON_Float:
  1028.                 {
  1029.                     GetTrieValue( info, "value", value );
  1030.                    
  1031.                     pos += FormatEx( output[ pos ], len - pos, "%f", value );
  1032.                    
  1033.                     // Remove insignificant digits
  1034.                     while( output[ --pos ] == '0' ) { }
  1035.                    
  1036.                     if( output[ pos ] == '.' )
  1037.                     {
  1038.                         output[ pos ] = EOS;
  1039.                     }
  1040.                     else
  1041.                     {
  1042.                        
  1043.                         output[ ++pos ] = EOS;
  1044.                     }
  1045.                 }
  1046.                 case JSON_String:
  1047.                 {
  1048.                     GetTrieString( info, "value", __json_string, sizeof( __json_string ) );
  1049.                    
  1050.                     pos += strcopy( output[ pos ], len - pos, "\"" );
  1051.                    
  1052.                     pos += json_escape( __json_string, output[ pos ], len - pos );
  1053.                    
  1054.                     pos += strcopy( output[ pos ], len - pos, "\"" );
  1055.                 }
  1056.                 case JSON_Object:
  1057.                 {
  1058.                     GetTrieValue( info, "value", value );
  1059.                    
  1060.                     pos += json_encode( JSON:value, output[ pos ], len - pos );
  1061.                 }
  1062.             }
  1063.         }
  1064.     }
  1065.    
  1066.     pos += strcopy( output[ pos ], len - pos, is_array ? "]" : "}" );
  1067.    
  1068.     return pos;
  1069. }
  1070.  
  1071. JSON_FUNC json_escape(const String:string[], String:output[], len)
  1072. {
  1073.     new pos, c, o;
  1074.    
  1075.     while( ( c = string[ pos++ ] ) > 0 )
  1076.     {
  1077.         if( o == len )
  1078.         {
  1079.             // Out of room for the rest of the string
  1080.             // Fail the escaping since we cannot give back full string
  1081.             o = 0;
  1082.             break;
  1083.         }
  1084.        
  1085.         if( c == '"' || c == '\\' )
  1086.         {
  1087.             if( ( o + 2 ) > len )
  1088.             {
  1089.                 // Cannot finish escaping the string, so fail the function
  1090.                 o = 0;
  1091.                 break;
  1092.             }
  1093.            
  1094.             output[ o++ ] = '\\';
  1095.             output[ o++ ] = c;
  1096.         }
  1097.         else
  1098.         {
  1099.             output[ o++ ] = c;
  1100.         }
  1101.     }
  1102.    
  1103.     output[ o ] = EOS;
  1104.    
  1105.     return o;
  1106. }
  1107.  
  1108. JSON_FUNC bool:json_destroy(&JSON:object)
  1109. {
  1110.     if( object == JSON_INVALID )
  1111.     {
  1112.         return false;
  1113.     }
  1114.    
  1115.     new Handle:data, Handle:keys;
  1116.    
  1117.     GetTrieValue( Handle:object, "data", data );
  1118.     GetTrieValue( Handle:object, "keys", keys );
  1119.    
  1120.     new size = GetArraySize( keys );
  1121.    
  1122.     for( new i = 0; i < size; i++ )
  1123.     {
  1124.         GetArrayString( keys, i, __json_key, sizeof( __json_key ) );
  1125.        
  1126.         __json_delete( data, __json_key );
  1127.     }
  1128.    
  1129.     CloseHandle( data );
  1130.     CloseHandle( keys );
  1131.    
  1132.     CloseHandle( Handle:object );
  1133.    
  1134.     object = JSON_INVALID;
  1135.    
  1136.     return true;
  1137. }
  1138.  
  1139. static JSON_FUNC isspace( c )
  1140. {
  1141.     return c == ' '
  1142.         || c == '\t'
  1143.         || c == '\n'
  1144.         || c == '\r'
  1145.         || c == '\v'
  1146.         || c == '\f'
  1147.     ;
  1148. }
  1149.  
  1150. static JSON_FUNC iscontrol( c )
  1151. {
  1152.     return c == ','
  1153.         || c == '{'
  1154.         || c == '}'
  1155.         || c == '['
  1156.         || c == ']'
  1157.     ;
  1158. }
  1159.  
  1160. static JSON_FUNC min( x, y )
  1161. {
  1162.     return ( x < y ) ? x : y;
  1163. }
  1164.  
  1165. static JSON_FUNC bool:is_str_num( const String:sString[] )
  1166. {
  1167.     new i = 0;
  1168.  
  1169.     if (sString[i] && (sString[i] == '-' || sString[i] == '+'))
  1170.         i = 1;
  1171.    
  1172.     while (sString[i] && IsCharNumeric(sString[i]))
  1173.         ++i;
  1174.    
  1175.     return sString[i] == 0 && i != 0;
  1176. }
Advertisement
Add Comment
Please, Sign In to add comment