| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | #ifdef SQLITE_STATIC_RANDOMJSON |
| | # include "sqlite3.h" |
| | #else |
| | # include "sqlite3ext.h" |
| | SQLITE_EXTENSION_INIT1 |
| | #endif |
| | #include <assert.h> |
| | #include <string.h> |
| | #include <stdlib.h> |
| |
|
| | |
| | typedef struct Prng { |
| | unsigned int x, y; |
| | } Prng; |
| |
|
| | |
| | static void prngSeed(Prng *p, unsigned int iSeed){ |
| | p->x = iSeed | 1; |
| | p->y = iSeed; |
| | } |
| |
|
| | |
| | static unsigned int prngInt(Prng *p){ |
| | p->x = (p->x>>1) ^ ((1+~(p->x&1)) & 0xd0000001); |
| | p->y = p->y*1103515245 + 12345; |
| | return p->x ^ p->y; |
| | } |
| |
|
| | static char *azJsonAtoms[] = { |
| | |
| | "0", "0", |
| | "1", "1", |
| | "-1", "-1", |
| | "2", "+2", |
| | "3DDDD", "3DDDD", |
| | "2.5DD", "2.5DD", |
| | "0.75", ".75", |
| | "-4.0e2", "-4.e2", |
| | "5.0e-3", "+5e-3", |
| | "6.DDe+0DD", "6.DDe+0DD", |
| | "0", "0x0", |
| | "512", "0x200", |
| | "256", "+0x100", |
| | "-2748", "-0xabc", |
| | "true", "true", |
| | "false", "false", |
| | "null", "null", |
| | "9.0e999", "Infinity", |
| | "-9.0e999", "-Infinity", |
| | "9.0e999", "+Infinity", |
| | "null", "NaN", |
| | "-0.0005DD", "-0.0005DD", |
| | "4.35e-3", "+4.35e-3", |
| | "\"gem\\\"hay\"", "\"gem\\\"hay\"", |
| | "\"icy'joy\"", "'icy\\'joy\'", |
| | "\"keylog\"", "\"key\\\nlog\"", |
| | "\"mix\\\\\\tnet\"", "\"mix\\\\\\tnet\"", |
| | "\"oat\\r\\n\"", "\"oat\\r\\n\"", |
| | "\"\\fpan\\b\"", "\"\\fpan\\b\"", |
| | "{}", "{}", |
| | "[]", "[]", |
| | "[]", "[/*empty*/]", |
| | "{}", "{//empty\n}", |
| | "\"ask\"", "\"ask\"", |
| | "\"bag\"", "\"bag\"", |
| | "\"can\"", "\"can\"", |
| | "\"day\"", "\"day\"", |
| | "\"end\"", "'end'", |
| | "\"fly\"", "\"fly\"", |
| | "\"\\u00XX\\u00XX\"", "\"\\xXX\\xXX\"", |
| | "\"y\\uXXXXz\"", "\"y\\uXXXXz\"", |
| | "\"\"", "\"\"", |
| | }; |
| | static char *azJsonTemplate[] = { |
| | |
| | "{\"a\":%,\"b\":%,\"cDD\":%}", "{a:%,b:%,cDD:%}", |
| | "{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"e\":%}", "{a:%,b:%,c:%,d:%,e:%}", |
| | "{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"\":%}", "{a:%,b:%,c:%,d:%,'':%}", |
| | "{\"d\":%}", "{d:%}", |
| | "{\"eeee\":%, \"ffff\":%}", "{eeee:% /*and*/, ffff:%}", |
| | "{\"$g\":%,\"_h_\":%,\"a b c d\":%}", "{$g:%,_h_:%,\"a b c d\":%}", |
| | "{\"x\":%,\n \"y\":%}", "{\"x\":%,\n \"y\":%}", |
| | "{\"\\u00XX\":%,\"\\uXXXX\":%}", "{\"\\xXX\":%,\"\\uXXXX\":%}", |
| | "{\"Z\":%}", "{Z:%,}", |
| | "[%]", "[%,]", |
| | "[%,%]", "[%,%]", |
| | "[%,%,%]", "[%,%,%,]", |
| | "[%,%,%,%]", "[%,%,%,%]", |
| | "[%,%,%,%,%]", "[%,%,%,%,%]", |
| | }; |
| |
|
| | #define count(X) (sizeof(X)/sizeof(X[0])) |
| |
|
| | #define STRSZ 10000 |
| |
|
| | static void jsonExpand( |
| | const char *zSrc, |
| | char *zDest, |
| | Prng *p, |
| | int eType, |
| | unsigned int r |
| | ){ |
| | unsigned int i, j, k; |
| | char *z; |
| | char *zX; |
| | size_t n; |
| | char zBuf[200]; |
| |
|
| | j = 0; |
| | if( zSrc==0 ) zSrc = "%"; |
| | if( strlen(zSrc)>=STRSZ/10 ) r = 0; |
| | for(i=0; zSrc[i]; i++){ |
| | if( zSrc[i]!='%' ){ |
| | if( j<STRSZ ) zDest[j++] = zSrc[i]; |
| | continue; |
| | } |
| | if( r==0 || (r<1000 && (prngInt(p)%1000)<=r) ){ |
| | |
| | k = prngInt(p)%(count(azJsonAtoms)/2); |
| | k = k*2 + eType; |
| | z = azJsonAtoms[k]; |
| | }else{ |
| | |
| | k = prngInt(p)%(count(azJsonTemplate)/2); |
| | k = k*2 + eType; |
| | z = azJsonTemplate[k]; |
| | } |
| | n = strlen(z); |
| | if( (zX = strstr(z,"XX"))!=0 ){ |
| | unsigned int y = prngInt(p); |
| | if( (y&0xff)==((y>>8)&0xff) ) y += 0x100; |
| | while( (y&0xff)==((y>>16)&0xff) || ((y>>8)&0xff)==((y>>16)&0xff) ){ |
| | y += 0x10000; |
| | } |
| | memcpy(zBuf, z, n+1); |
| | z = zBuf; |
| | zX = strstr(z,"XX"); |
| | while( zX!=0 ){ |
| | zX[0] = "0123456789abcdef"[y%16]; y /= 16; |
| | zX[1] = "0123456789abcdef"[y%16]; y /= 16; |
| | zX = strstr(zX, "XX"); |
| | } |
| | }else if( (zX = strstr(z,"DD"))!=0 ){ |
| | unsigned int y = prngInt(p); |
| | memcpy(zBuf, z, n+1); |
| | z = zBuf; |
| | zX = strstr(z,"DD"); |
| | while( zX!=0 ){ |
| | zX[0] = "0123456789"[y%10]; y /= 10; |
| | zX[1] = "0123456789"[y%10]; y /= 10; |
| | zX = strstr(zX, "DD"); |
| | } |
| | } |
| | assert( strstr(z, "XX")==0 ); |
| | assert( strstr(z, "DD")==0 ); |
| | if( j+n<STRSZ ){ |
| | memcpy(&zDest[j], z, n); |
| | j += (int)n; |
| | } |
| | } |
| | zDest[STRSZ-1] = 0; |
| | if( j<STRSZ ) zDest[j] = 0; |
| | } |
| |
|
| | static void randJsonFunc( |
| | sqlite3_context *context, |
| | int argc, |
| | sqlite3_value **argv |
| | ){ |
| | unsigned int iSeed; |
| | int eType = *(int*)sqlite3_user_data(context); |
| | Prng prng; |
| | char z1[STRSZ+1], z2[STRSZ+1]; |
| |
|
| | iSeed = (unsigned int)sqlite3_value_int(argv[0]); |
| | prngSeed(&prng, iSeed); |
| | jsonExpand(0, z2, &prng, eType, 1000); |
| | jsonExpand(z2, z1, &prng, eType, 1000); |
| | jsonExpand(z1, z2, &prng, eType, 100); |
| | jsonExpand(z2, z1, &prng, eType, 0); |
| | sqlite3_result_text(context, z1, -1, SQLITE_TRANSIENT); |
| | } |
| |
|
| | #ifdef _WIN32 |
| | __declspec(dllexport) |
| | #endif |
| | int sqlite3_randomjson_init( |
| | sqlite3 *db, |
| | char **pzErrMsg, |
| | const sqlite3_api_routines *pApi |
| | ){ |
| | static int cOne = 1; |
| | static int cZero = 0; |
| | int rc = SQLITE_OK; |
| | #ifdef SQLITE_STATIC_RANDOMJSON |
| | (void)pApi; |
| | #else |
| | SQLITE_EXTENSION_INIT2(pApi); |
| | #endif |
| | (void)pzErrMsg; |
| | rc = sqlite3_create_function(db, "random_json", 1, |
| | SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, |
| | &cZero, randJsonFunc, 0, 0); |
| | if( rc==SQLITE_OK ){ |
| | rc = sqlite3_create_function(db, "random_json5", 1, |
| | SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, |
| | &cOne, randJsonFunc, 0, 0); |
| | } |
| | return rc; |
| | } |
| |
|