Fossil

Check-in [78d812e2]
Login

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

Overview
Comment:Merge the %j string formatter enhancement from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | graph-improvements
Files: files | file ages | folders
SHA3-256:78d812e24d983dbe021183c6d6b4cc48a216f7e497bb70a4927f004d3feb6a3c
User & Date: drh 2019-05-17 13:54:39
Context
2019-05-17
19:30
In the graph layout, make sure that the idxTop value is properly relayed across gaps. Closed-Leaf check-in: e0186fdb user: drh tags: graph-improvements
16:45
Proof-of-concept for how to pop up a tooltip when mousing over one of the branch arrows in a timeline graph. check-in: 8e922935 user: drh tags: tooltips
13:54
Merge the %j string formatter enhancement from trunk. check-in: 78d812e2 user: drh tags: graph-improvements
13:53
Add the %j formatting directive to the customized printf() inside of Fossil. The %j format generates a string with appropriate backslash escapes so that the string can be part of a Javascript string literal. check-in: 5e9c1d5e user: drh tags: trunk
12:05
Merge changes from trunk. check-in: 49f8f9e1 user: drh tags: graph-improvements
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/encode.c.

374
375
376
377
378
379
380
381


382
383

384
385
386
387
388
389
390
...
396
397
398
399
400
401
402
403
404
405
406

407
408
409
410
411
412
413
...
423
424
425
426
427
428
429

430
431
432
433
434
435
436
        || (c&0xFFFFF800)==0xD800
        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }
  }
  return c;
}

/*
** Encode a UTF8 string for JSON.  All special characters are escaped.


*/
void blob_append_json_string(Blob *pBlob, const char *zStr){

  const unsigned char *z;
  char *zOut;
  u32 c;
  int n, i, j;
  z = (const unsigned char*)zStr;
  n = 0;
  while( (c = fossil_utf8_read(&z))!=0 ){
................................................................................
      }else{
        n += 6;
      }
    }else{
      n++;
    }
  }
  i = blob_size(pBlob);
  blob_resize(pBlob, i+n);
  zOut = blob_buffer(pBlob);
  z = (const unsigned char*)zStr;

  while( (c = fossil_utf8_read(&z))!=0 ){
    if( c=='\\' ){
      zOut[i++] = '\\';
      zOut[i++] = c;
    }else if( c<' ' || c>=0x7f ){
      zOut[i++] = '\\';
      if( c=='\n' ){
................................................................................
        i += 4;
      }
    }else{
      zOut[i++] = c;
    }
  }
  zOut[i] = 0;

}

/*
** The characters used for HTTP base64 encoding.
*/
static unsigned char zBase[] =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";







|
>
>

<
>







 







|
|
<

>







 







>







374
375
376
377
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392
...
398
399
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414
415
...
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
        || (c&0xFFFFF800)==0xD800
        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }
  }
  return c;
}

/*
** Encode a UTF8 string as a JSON string literal (without the surrounding
** "...") and return a pointer to the encoding.  Space to hold the encoding
** is obtained from fossil_malloc() and must be freed by the caller.
*/

char *encode_json_string_literal(const char *zStr){
  const unsigned char *z;
  char *zOut;
  u32 c;
  int n, i, j;
  z = (const unsigned char*)zStr;
  n = 0;
  while( (c = fossil_utf8_read(&z))!=0 ){
................................................................................
      }else{
        n += 6;
      }
    }else{
      n++;
    }
  }
  zOut = fossil_malloc(n+1);
  if( zOut==0 ) return 0;

  z = (const unsigned char*)zStr;
  i = 0;
  while( (c = fossil_utf8_read(&z))!=0 ){
    if( c=='\\' ){
      zOut[i++] = '\\';
      zOut[i++] = c;
    }else if( c<' ' || c>=0x7f ){
      zOut[i++] = '\\';
      if( c=='\n' ){
................................................................................
        i += 4;
      }
    }else{
      zOut[i++] = c;
    }
  }
  zOut[i] = 0;
  return zOut;
}

/*
** The characters used for HTTP base64 encoding.
*/
static unsigned char zBase[] =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

Changes to src/printf.c.

97
98
99
100
101
102
103

104
105
106
107
108
109
110
...
148
149
150
151
152
153
154

155
156
157
158
159
160
161
...
777
778
779
780
781
782
783









784
785
786
787
788
789
790
#define etHTTPIZE    18 /* Make text safe for HTTP.  "/" encoded as %2f */
#define etURLIZE     19 /* Make text safe for HTTP.  "/" not encoded */
#define etFOSSILIZE  20 /* The fossil header encoding format. */
#define etPATH       21 /* Path type */
#define etWIKISTR    22 /* Timeline comment text rendered from a char*: %W */
#define etSTRINGID   23 /* String with length limit for a UUID prefix: %S */
#define etROOT       24 /* String value of g.zTop: %R */



/*
** An "etByte" is an 8-bit unsigned value.
*/
typedef unsigned char etByte;

................................................................................
  {  'h',  0, 4, etHTMLIZE,    0,  0 },
  {  'R',  0, 0, etROOT,       0,  0 },
  {  't',  0, 4, etHTTPIZE,    0,  0 },  /* "/" -> "%2F" */
  {  'T',  0, 4, etURLIZE,     0,  0 },  /* "/" unchanged */
  {  'w',  0, 4, etSQLESCAPE3, 0,  0 },
  {  'F',  0, 4, etFOSSILIZE,  0,  0 },
  {  'S',  0, 4, etSTRINGID,   0,  0 },

  {  'c',  0, 0, etCHARX,      0,  0 },
  {  'o',  8, 0, etRADIX,      0,  2 },
  {  'u', 10, 0, etRADIX,      0,  0 },
  {  'x', 16, 0, etRADIX,      16, 1 },
  {  'X', 16, 0, etRADIX,      0,  4 },
  {  'f',  0, 1, etFLOAT,      0,  0 },
  {  'e',  0, 1, etEXP,        30, 0 },
................................................................................
        break;
      }
      case etFOSSILIZE: {
        int limit = flag_alternateform ? va_arg(ap,int) : -1;
        char *zMem = va_arg(ap,char*);
        if( zMem==0 ) zMem = "";
        zExtra = bufpt = fossilize(zMem, limit);









        length = strlen(bufpt);
        if( precision>=0 && precision<length ) length = precision;
        break;
      }
      case etWIKISTR: {
        int limit = flag_alternateform ? va_arg(ap,int) : -1;
        char *zWiki = va_arg(ap, char*);







>







 







>







 







>
>
>
>
>
>
>
>
>







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
#define etHTTPIZE    18 /* Make text safe for HTTP.  "/" encoded as %2f */
#define etURLIZE     19 /* Make text safe for HTTP.  "/" not encoded */
#define etFOSSILIZE  20 /* The fossil header encoding format. */
#define etPATH       21 /* Path type */
#define etWIKISTR    22 /* Timeline comment text rendered from a char*: %W */
#define etSTRINGID   23 /* String with length limit for a UUID prefix: %S */
#define etROOT       24 /* String value of g.zTop: %R */
#define etJSONSTR    25 /* String encoded as a JSON string literal: %j */


/*
** An "etByte" is an 8-bit unsigned value.
*/
typedef unsigned char etByte;

................................................................................
  {  'h',  0, 4, etHTMLIZE,    0,  0 },
  {  'R',  0, 0, etROOT,       0,  0 },
  {  't',  0, 4, etHTTPIZE,    0,  0 },  /* "/" -> "%2F" */
  {  'T',  0, 4, etURLIZE,     0,  0 },  /* "/" unchanged */
  {  'w',  0, 4, etSQLESCAPE3, 0,  0 },
  {  'F',  0, 4, etFOSSILIZE,  0,  0 },
  {  'S',  0, 4, etSTRINGID,   0,  0 },
  {  'j',  0, 0, etJSONSTR,    0,  0 },
  {  'c',  0, 0, etCHARX,      0,  0 },
  {  'o',  8, 0, etRADIX,      0,  2 },
  {  'u', 10, 0, etRADIX,      0,  0 },
  {  'x', 16, 0, etRADIX,      16, 1 },
  {  'X', 16, 0, etRADIX,      0,  4 },
  {  'f',  0, 1, etFLOAT,      0,  0 },
  {  'e',  0, 1, etEXP,        30, 0 },
................................................................................
        break;
      }
      case etFOSSILIZE: {
        int limit = flag_alternateform ? va_arg(ap,int) : -1;
        char *zMem = va_arg(ap,char*);
        if( zMem==0 ) zMem = "";
        zExtra = bufpt = fossilize(zMem, limit);
        length = strlen(bufpt);
        if( precision>=0 && precision<length ) length = precision;
        break;
      }
      case etJSONSTR: {
        int limit = flag_alternateform ? va_arg(ap,int) : -1;
        char *zMem = va_arg(ap,char*);
        if( zMem==0 ) zMem = "";
        zExtra = bufpt = encode_json_string_literal(zMem);
        length = strlen(bufpt);
        if( precision>=0 && precision<length ) length = precision;
        break;
      }
      case etWIKISTR: {
        int limit = flag_alternateform ? va_arg(ap,int) : -1;
        char *zWiki = va_arg(ap, char*);

Changes to src/unversioned.c.

617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
   while( db_step(&q)==SQLITE_ROW ){
     const char *zName = db_column_text(&q, 0);
     sqlite3_int64 mtime = db_column_int(&q, 1);
     const char *zHash = db_column_text(&q, 2);
     int fullSize = db_column_int(&q, 3);
     const char *zLogin = db_column_text(&q, 4);
     if( zLogin==0 ) zLogin = "";
     blob_appendf(&json, "%s{\"name\":\"", zSep);
     zSep = ",\n ";
     blob_append_json_string(&json, zName);
     blob_appendf(&json, "\",\n  \"mtime\":%lld,\n  \"hash\":\"", mtime);
     blob_append_json_string(&json, zHash);
     blob_appendf(&json, "\",\n  \"size\":%d,\n  \"user\":\"", fullSize);
     blob_append_json_string(&json, zLogin);
     blob_appendf(&json, "\"}");
   }
   db_finalize(&q);
   blob_appendf(&json,"]\n");
   cgi_set_content(&json);
}







|

|
|
|
<
<
|





617
618
619
620
621
622
623
624
625
626
627
628


629
630
631
632
633
634
   while( db_step(&q)==SQLITE_ROW ){
     const char *zName = db_column_text(&q, 0);
     sqlite3_int64 mtime = db_column_int(&q, 1);
     const char *zHash = db_column_text(&q, 2);
     int fullSize = db_column_int(&q, 3);
     const char *zLogin = db_column_text(&q, 4);
     if( zLogin==0 ) zLogin = "";
     blob_appendf(&json, "%s{\"name\":\"%j\",\n", zSep, zName);
     zSep = ",\n ";
     blob_appendf(&json, "  \"mtime\":%lld,\n", mtime);
     blob_appendf(&json, "  \"hash\":\"%j\",\n", zHash);
     blob_appendf(&json, "  \"size\":%d,\n", fullSize);


     blob_appendf(&json, "  \"user\":\"%j\"}", zLogin);
   }
   db_finalize(&q);
   blob_appendf(&json,"]\n");
   cgi_set_content(&json);
}