Fossil

Check-in [cde55bd7]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Pulled in latest cson amalgamation for the cson_type_id addition and started refactoring some O(N) lookups to O(1) based on that addition.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cde55bd7a3dc7c5eeb920ff085de1c72955aed1d
User & Date: stephan 2012-07-05 19:03:18
Context
2012-07-05
19:24
Minor interal json refactoring made possible by recent cson changes. check-in: e40e79b7 user: stephan tags: trunk
19:03
Pulled in latest cson amalgamation for the cson_type_id addition and started refactoring some O(N) lookups to O(1) based on that addition. check-in: cde55bd7 user: stephan tags: trunk
2012-07-03
21:30
minor cleanups made possible by newer cson APIs. check-in: 9be377fe user: stephan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/cson_amalgamation.c.

1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
....
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
....
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484

#if defined(__cplusplus)
extern "C" {
#endif


    
/**
   Type IDs corresponding to JavaScript/JSON types.
*/
enum cson_type_id {
  /**
    The special "undefined" value constant.

    Its value must be 0 for internal reasons.
 */
 CSON_TYPE_UNDEF = 0,
 /**
    The special "null" value constant.
 */
 CSON_TYPE_NULL = 1,
 /**
    The bool value type.
 */
 CSON_TYPE_BOOL = 2,
 /**
    The integer value type, represented in this library
    by cson_int_t.
 */
 CSON_TYPE_INTEGER = 3,
 /**
    The double value type, represented in this library
    by cson_double_t.
 */
 CSON_TYPE_DOUBLE = 4,
 /** The immutable string type. This library stores strings
    as immutable UTF8.
 */
 CSON_TYPE_STRING = 5,
 /** The "Array" type. */
 CSON_TYPE_ARRAY = 6,
 /** The "Object" type. */
 CSON_TYPE_OBJECT = 7
};
typedef enum cson_type_id cson_type_id;

/**
   This type holds the "vtbl" for type-specific operations when
   working with cson_value objects.

   All cson_values of a given logical type share a pointer to a single
   library-internal instance of this class.
................................................................................
/** Returns true if v is not NULL and has the given type ID. */
static char cson_value_is_a( cson_value const * v, cson_type_id is )
{
    return (v && v->api && (v->api->typeID == is)) ? 1 : 0;
}
#endif

#if 0
cson_type_id cson_value_type_id( cson_value const * v )
{
    return (v && v->api) ? v->api->typeID : CSON_TYPE_UNDEF;
}
#endif

char cson_value_is_undef( cson_value const * v )
{
    return ( !v || !v->api || (v->api==&cson_value_api_undef))
        ? 1 : 0;
}
#define ISA(T,TID) char cson_value_is_##T( cson_value const * v ) {       \
................................................................................

- (inp) = is a pointer to the pointer to the start of the input.

- (separator) = the separator character

- (end) = a pointer to NULL. i.e. (*end == NULL)

This function scans *inp for the given separator char or a NULL char.
Successive separators at the start of *inp are skipped. The effect is
that, when this function is called in a loop, all neighboring
separators are ignored. e.g. the string "aa.bb...cc" will tokenize to
the list (aa,bb,cc) if the separator is '.' and to (aa.,...cc) if the
separator is 'b'.

Returns 0 (false) if it finds no token, else non-0 (true).







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<




<







 







|







1420
1421
1422
1423
1424
1425
1426






































1427
1428
1429
1430
1431
1432
1433
....
2274
2275
2276
2277
2278
2279
2280

2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
....
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444

#if defined(__cplusplus)
extern "C" {
#endif


    







































/**
   This type holds the "vtbl" for type-specific operations when
   working with cson_value objects.

   All cson_values of a given logical type share a pointer to a single
   library-internal instance of this class.
................................................................................
/** Returns true if v is not NULL and has the given type ID. */
static char cson_value_is_a( cson_value const * v, cson_type_id is )
{
    return (v && v->api && (v->api->typeID == is)) ? 1 : 0;
}
#endif


cson_type_id cson_value_type_id( cson_value const * v )
{
    return (v && v->api) ? v->api->typeID : CSON_TYPE_UNDEF;
}


char cson_value_is_undef( cson_value const * v )
{
    return ( !v || !v->api || (v->api==&cson_value_api_undef))
        ? 1 : 0;
}
#define ISA(T,TID) char cson_value_is_##T( cson_value const * v ) {       \
................................................................................

- (inp) = is a pointer to the pointer to the start of the input.

- (separator) = the separator character

- (end) = a pointer to NULL. i.e. (*end == NULL)

This function scans *inp for the given separator char or a NUL char.
Successive separators at the start of *inp are skipped. The effect is
that, when this function is called in a loop, all neighboring
separators are ignored. e.g. the string "aa.bb...cc" will tokenize to
the list (aa,bb,cc) if the separator is '.' and to (aa.,...cc) if the
separator is 'b'.

Returns 0 (false) if it finds no token, else non-0 (true).

Changes to src/cson_amalgamation.h.

130
131
132
133
134
135
136

















































137
138
139
140
141
142
143
...
209
210
211
212
213
214
215

216
217
218
219
220
221
222
...
738
739
740
741
742
743
744






745
746
747
748
749
750
751
*/

/** @def CSON_DOUBLE_T_PFMT

printf()-compatible format token for cson_double_t.
*/


















































typedef struct cson_value cson_value;

/** @struct cson_value
   
   The core value type of this API. It is opaque to clients, and
   only the cson public API should be used for setting or
   inspecting their values.
................................................................................
   @see cson_value_new_integer()
   @see cson_value_new_double()
   @see cson_value_new_bool()
   @see cson_value_true()
   @see cson_value_false()
   @see cson_value_null()
   @see cson_value_free()

*/

/** @var cson_rc

   This object defines the error codes used by cson.

   Library routines which return int values almost always return a
................................................................................
/**
   Convenience wrapper around cson_output_FILE() which writes to the given filename, destroying
   any existing contents. Returns cson_rc.IOError if the file cannot be opened.

   @see cson_output_FILE()
*/
int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt );







/** Returns true if v is null, v->api is NULL, or v holds the special undefined value. */
char cson_value_is_undef( cson_value const * v );
/** Returns true if v contains a null value. */
char cson_value_is_null( cson_value const * v );
/** Returns true if v contains a bool value. */
char cson_value_is_bool( cson_value const * v );







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







>
>
>
>
>
>







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
*/

/** @def CSON_DOUBLE_T_PFMT

printf()-compatible format token for cson_double_t.
*/

/**
    Type IDs corresponding to JavaScript/JSON types.

    These are only in the public API to allow O(1) client-side
    dispatching based on cson_value types.
*/
enum cson_type_id {
  /**
    The special "undefined" value constant.

    Its value must be 0 for internal reasons.
 */
 CSON_TYPE_UNDEF = 0,
 /**
    The special "null" value constant.
 */
 CSON_TYPE_NULL = 1,
 /**
    The bool value type.
 */
 CSON_TYPE_BOOL = 2,
 /**
    The integer value type, represented in this library
    by cson_int_t.
 */
 CSON_TYPE_INTEGER = 3,
 /**
    The double value type, represented in this library
    by cson_double_t.
 */
 CSON_TYPE_DOUBLE = 4,
 /** The immutable string type. This library stores strings
    as immutable UTF8.
 */
 CSON_TYPE_STRING = 5,
 /** The "Array" type. */
 CSON_TYPE_ARRAY = 6,
 /** The "Object" type. */
 CSON_TYPE_OBJECT = 7
};
/**
   Convenience typedef.
*/
typedef enum cson_type_id cson_type_id;


/**
   Convenience typedef.
*/
typedef struct cson_value cson_value;

/** @struct cson_value
   
   The core value type of this API. It is opaque to clients, and
   only the cson public API should be used for setting or
   inspecting their values.
................................................................................
   @see cson_value_new_integer()
   @see cson_value_new_double()
   @see cson_value_new_bool()
   @see cson_value_true()
   @see cson_value_false()
   @see cson_value_null()
   @see cson_value_free()
   @see cson_value_type_id()
*/

/** @var cson_rc

   This object defines the error codes used by cson.

   Library routines which return int values almost always return a
................................................................................
/**
   Convenience wrapper around cson_output_FILE() which writes to the given filename, destroying
   any existing contents. Returns cson_rc.IOError if the file cannot be opened.

   @see cson_output_FILE()
*/
int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt );

/**
   Returns the virtual type of v, or CSON_TYPE_UNDEF if !v.
*/
cson_type_id cson_value_type_id( cson_value const * v );


/** Returns true if v is null, v->api is NULL, or v holds the special undefined value. */
char cson_value_is_undef( cson_value const * v );
/** Returns true if v contains a null value. */
char cson_value_is_null( cson_value const * v );
/** Returns true if v contains a bool value. */
char cson_value_is_bool( cson_value const * v );

Changes to src/json.c.

173
174
175
176
177
178
179
180


181
182
183
184
185
186
187
...
465
466
467
468
469
470
471
472
473
474

475
476

477
478
479
480


481
482

483
484
485

486
487
488
489
490
491
492
493
...
501
502
503
504
505
506
507
508
509
510

511
512

513

514
515
516
517
518
519
520
521
522
523


524
525

526
527

528
529
530
531
532
533
534
535
...
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769

#else
#define BEGIN_TIMER 
#define END_TIMER 0.0
#define HAS_TIMER 0
#endif




char fossil_has_json(){
  return g.json.isJsonMode && (g.isHTTP || g.json.post.o);
}

/*
** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
** (but planned) pages/commands.
................................................................................
**
** If it finds a value and that value is-a JSON number or is a string
** which looks like an integer or is-a JSON bool/null then it is
** converted to an int. If none of those apply then dflt is returned.
*/
int json_getenv_int(char const * pKey, int dflt ){
  cson_value const * v = json_getenv(pKey);
  if(!v){
    return dflt;
  }else if( cson_value_is_number(v) ){

    return (int)cson_value_get_integer(v);
  }else if( cson_value_is_string(v) ){

    char const * sv = cson_string_cstr(cson_value_get_string(v));
    assert( (NULL!=sv) && "This is quite unexpected." );
    return sv ? atoi(sv) : dflt;
  }else if( cson_value_is_bool(v) ){


    return cson_value_get_bool(v) ? 1 : 0;
  }else if( cson_value_is_null(v) ){

    return 0;
  }else{
    /* we should arguably treat JSON null as 0. */

    return dflt;
  }
}


/*
** Wrapper around json_getenv() which tries to evaluate a payload/env
** value as a boolean. Uses mostly the same logic as
................................................................................
** either 0 or 1, as opposed to "0 or non-zero", so that clients can
** pass a different value as dflt. Thus they can use, e.g. -1 to know
** whether or not this function found a match (it will return -1 in
** that case).
*/
char json_getenv_bool(char const * pKey, char dflt ){
  cson_value const * v = json_getenv(pKey);
  if(!v){
    return dflt;
  }else if( cson_value_is_number(v) ){

    return cson_value_get_integer(v) ? 1 : 0;
  }else if( cson_value_is_string(v) ){

    char const * sv = cson_string_cstr(cson_value_get_string(v));

    if(!*sv || ('0'==*sv)){
      return 0;
    }else{
      return ((('1'<=*sv) && ('9'>=*sv))
              || ('t'==*sv) || ('T'==*sv)
              || ('y'==*sv) || ('Y'==*sv)
              )
        ? 1 : 0;
    }
  }else if( cson_value_is_bool(v) ){


    return cson_value_get_bool(v) ? 1 : 0;
  }else if( cson_value_is_null(v) ){

    return 0;
  }else{

    return dflt;
  }
}

/*
** Returns the string form of a json_getenv() value, but ONLY If that
** value is-a String. Non-strings are not converted to strings for
** this purpose. Returned memory is owned by g.json or fossil and is
................................................................................
    g.json.authToken = json_getenv(FossilJsonKeys.authToken);
    if(g.json.authToken
       && cson_value_is_string(g.json.authToken)
       && !PD(login_cookie_name(),NULL)){
      /* tell fossil to use this login info.

      FIXME?: because the JSON bits don't carry around
      login_cookie_name(), there is a potential login hijacking
      window here. We may need to change the JSON auth token to be
      in the form: login_cookie_name()=...

      Then again, the hardened cookie value helps ensure that
      only a proper key/value match is valid.
      */
      cgi_replace_parameter( login_cookie_name(), cson_value_get_cstr(g.json.authToken) );
    }else if( g.isHTTP ){
      /* try fossil's conventional cookie. */







|
>
>







 







|
|
|
>
|
<
>
|
|
|
<
>
>
|
<
>
|
<
<
>
|







 







|
|
|
>
|
<
>
|
>
|
|
|
|
|
|
|
|
|
<
>
>
|
<
>
|
<
>
|







 







|
|
|







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
467
468
469
470
471
472
473
474
475
476
477
478

479
480
481
482

483
484
485

486
487


488
489
490
491
492
493
494
495
496
...
504
505
506
507
508
509
510
511
512
513
514
515

516
517
518
519
520
521
522
523
524
525
526
527

528
529
530

531
532

533
534
535
536
537
538
539
540
541
...
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775

#else
#define BEGIN_TIMER 
#define END_TIMER 0.0
#define HAS_TIMER 0
#endif

/*
** Returns true (non-0) if fossil appears to be running in JSON mode.
*/
char fossil_has_json(){
  return g.json.isJsonMode && (g.isHTTP || g.json.post.o);
}

/*
** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
** (but planned) pages/commands.
................................................................................
**
** If it finds a value and that value is-a JSON number or is a string
** which looks like an integer or is-a JSON bool/null then it is
** converted to an int. If none of those apply then dflt is returned.
*/
int json_getenv_int(char const * pKey, int dflt ){
  cson_value const * v = json_getenv(pKey);
  const cson_type_id type = v ? cson_value_type_id(v) : CSON_TYPE_UNDEF;
  switch(type){
    case CSON_TYPE_INTEGER:
    case CSON_TYPE_DOUBLE:
      return (int)cson_value_get_integer(v);

    case CSON_TYPE_STRING: {
      char const * sv = cson_string_cstr(cson_value_get_string(v));
      assert( (NULL!=sv) && "This is quite unexpected." );
      return sv ? atoi(sv) : dflt;

    }
    case CSON_TYPE_BOOL:
      return cson_value_get_bool(v) ? 1 : 0;

    case CSON_TYPE_NULL:
      return 0;


    default:
      return dflt;
  }
}


/*
** Wrapper around json_getenv() which tries to evaluate a payload/env
** value as a boolean. Uses mostly the same logic as
................................................................................
** either 0 or 1, as opposed to "0 or non-zero", so that clients can
** pass a different value as dflt. Thus they can use, e.g. -1 to know
** whether or not this function found a match (it will return -1 in
** that case).
*/
char json_getenv_bool(char const * pKey, char dflt ){
  cson_value const * v = json_getenv(pKey);
  const cson_type_id type = v ? cson_value_type_id(v) : CSON_TYPE_UNDEF;
  switch(type){
    case CSON_TYPE_INTEGER:
    case CSON_TYPE_DOUBLE:
      return cson_value_get_integer(v) ? 1 : 0;

    case CSON_TYPE_STRING: {
      char const * sv = cson_string_cstr(cson_value_get_string(v));
      assert( (NULL!=sv) && "This is quite unexpected." );
      if(!*sv || ('0'==*sv)){
        return 0;
      }else{
        return ((('1'<=*sv) && ('9'>=*sv))
                || ('t'==*sv) || ('T'==*sv)
                || ('y'==*sv) || ('Y'==*sv)
                )
          ? 1 : 0;
      }

    }
    case CSON_TYPE_BOOL:
      return cson_value_get_bool(v) ? 1 : 0;

    case CSON_TYPE_NULL:
      return 0;

    default:
      return dflt;
  }
}

/*
** Returns the string form of a json_getenv() value, but ONLY If that
** value is-a String. Non-strings are not converted to strings for
** this purpose. Returned memory is owned by g.json or fossil and is
................................................................................
    g.json.authToken = json_getenv(FossilJsonKeys.authToken);
    if(g.json.authToken
       && cson_value_is_string(g.json.authToken)
       && !PD(login_cookie_name(),NULL)){
      /* tell fossil to use this login info.

      FIXME?: because the JSON bits don't carry around
      login_cookie_name(), there is(?) a potential(?) login hijacking
      window here. We may need to change the JSON auth token to be in
      the form: login_cookie_name()=...

      Then again, the hardened cookie value helps ensure that
      only a proper key/value match is valid.
      */
      cgi_replace_parameter( login_cookie_name(), cson_value_get_cstr(g.json.authToken) );
    }else if( g.isHTTP ){
      /* try fossil's conventional cookie. */