Fixes default log output to console for macOS
[sqlcipher.git] / ext / misc / randomjson.c
blobcacc4feb68f84e3a7f225091a37a6e90e9f23c16
1 /*
2 ** 2023-04-28
3 **
4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
6 **
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 ******************************************************************************
13 ** This SQLite extension implements a the random_json(SEED) and
14 ** random_json5(SEED) functions. Given a numeric SEED value, these
15 ** routines generate pseudo-random JSON or JSON5, respectively. The
16 ** same value is always generated for the same seed.
18 ** These SQL functions are intended for testing. They do not have any
19 ** practical real-world use, that we know of.
21 ** COMPILE:
23 ** gcc --shared -fPIC -o randomjson.so -I. ext/misc/randomjson.c
25 ** USING FROM THE CLI:
27 ** .load ./randomjson
28 ** SELECT random_json(1);
29 ** SELECT random_json5(1);
31 #ifdef SQLITE_STATIC_RANDOMJSON
32 # include "sqlite3.h"
33 #else
34 # include "sqlite3ext.h"
35 SQLITE_EXTENSION_INIT1
36 #endif
37 #include <assert.h>
38 #include <string.h>
39 #include <stdlib.h>
41 /* Pseudo-random number generator */
42 typedef struct Prng {
43 unsigned int x, y;
44 } Prng;
46 /* Reseed the PRNG */
47 static void prngSeed(Prng *p, unsigned int iSeed){
48 p->x = iSeed | 1;
49 p->y = iSeed;
52 /* Extract a random number */
53 static unsigned int prngInt(Prng *p){
54 p->x = (p->x>>1) ^ ((1+~(p->x&1)) & 0xd0000001);
55 p->y = p->y*1103515245 + 12345;
56 return p->x ^ p->y;
59 static char *azJsonAtoms[] = {
60 /* JSON JSON-5 */
61 "0", "0",
62 "1", "1",
63 "-1", "-1",
64 "2", "+2",
65 "3DDDD", "3DDDD",
66 "2.5DD", "2.5DD",
67 "0.75", ".75",
68 "-4.0e2", "-4.e2",
69 "5.0e-3", "+5e-3",
70 "6.DDe+0DD", "6.DDe+0DD",
71 "0", "0x0",
72 "512", "0x200",
73 "256", "+0x100",
74 "-2748", "-0xabc",
75 "true", "true",
76 "false", "false",
77 "null", "null",
78 "9.0e999", "Infinity",
79 "-9.0e999", "-Infinity",
80 "9.0e999", "+Infinity",
81 "null", "NaN",
82 "-0.0005DD", "-0.0005DD",
83 "4.35e-3", "+4.35e-3",
84 "\"gem\\\"hay\"", "\"gem\\\"hay\"",
85 "\"icy'joy\"", "'icy\\'joy\'",
86 "\"keylog\"", "\"key\\\nlog\"",
87 "\"mix\\\\\\tnet\"", "\"mix\\\\\\tnet\"",
88 "\"oat\\r\\n\"", "\"oat\\r\\n\"",
89 "\"\\fpan\\b\"", "\"\\fpan\\b\"",
90 "{}", "{}",
91 "[]", "[]",
92 "[]", "[/*empty*/]",
93 "{}", "{//empty\n}",
94 "\"ask\"", "\"ask\"",
95 "\"bag\"", "\"bag\"",
96 "\"can\"", "\"can\"",
97 "\"day\"", "\"day\"",
98 "\"end\"", "'end'",
99 "\"fly\"", "\"fly\"",
100 "\"\\u00XX\\u00XX\"", "\"\\xXX\\xXX\"",
101 "\"y\\uXXXXz\"", "\"y\\uXXXXz\"",
102 "\"\"", "\"\"",
104 static char *azJsonTemplate[] = {
105 /* JSON JSON-5 */
106 "{\"a\":%,\"b\":%,\"cDD\":%}", "{a:%,b:%,cDD:%}",
107 "{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"e\":%}", "{a:%,b:%,c:%,d:%,e:%}",
108 "{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"\":%}", "{a:%,b:%,c:%,d:%,'':%}",
109 "{\"d\":%}", "{d:%}",
110 "{\"eeee\":%, \"ffff\":%}", "{eeee:% /*and*/, ffff:%}",
111 "{\"$g\":%,\"_h_\":%,\"a b c d\":%}", "{$g:%,_h_:%,\"a b c d\":%}",
112 "{\"x\":%,\n \"y\":%}", "{\"x\":%,\n \"y\":%}",
113 "{\"\\u00XX\":%,\"\\uXXXX\":%}", "{\"\\xXX\":%,\"\\uXXXX\":%}",
114 "{\"Z\":%}", "{Z:%,}",
115 "[%]", "[%,]",
116 "[%,%]", "[%,%]",
117 "[%,%,%]", "[%,%,%,]",
118 "[%,%,%,%]", "[%,%,%,%]",
119 "[%,%,%,%,%]", "[%,%,%,%,%]",
122 #define count(X) (sizeof(X)/sizeof(X[0]))
124 #define STRSZ 10000
126 static void jsonExpand(
127 const char *zSrc,
128 char *zDest,
129 Prng *p,
130 int eType, /* 0 for JSON, 1 for JSON5 */
131 unsigned int r /* Growth probability 0..1000. 0 means no growth */
133 unsigned int i, j, k;
134 char *z;
135 char *zX;
136 size_t n;
137 char zBuf[200];
139 j = 0;
140 if( zSrc==0 ) zSrc = "%";
141 if( strlen(zSrc)>=STRSZ/10 ) r = 0;
142 for(i=0; zSrc[i]; i++){
143 if( zSrc[i]!='%' ){
144 if( j<STRSZ ) zDest[j++] = zSrc[i];
145 continue;
147 if( r==0 || (r<1000 && (prngInt(p)%1000)<=r) ){
148 /* Fill in without values without any new % */
149 k = prngInt(p)%(count(azJsonAtoms)/2);
150 k = k*2 + eType;
151 z = azJsonAtoms[k];
152 }else{
153 /* Add new % terms */
154 k = prngInt(p)%(count(azJsonTemplate)/2);
155 k = k*2 + eType;
156 z = azJsonTemplate[k];
158 n = strlen(z);
159 if( (zX = strstr(z,"XX"))!=0 ){
160 unsigned int y = prngInt(p);
161 if( (y&0xff)==((y>>8)&0xff) ) y += 0x100;
162 while( (y&0xff)==((y>>16)&0xff) || ((y>>8)&0xff)==((y>>16)&0xff) ){
163 y += 0x10000;
165 memcpy(zBuf, z, n+1);
166 z = zBuf;
167 zX = strstr(z,"XX");
168 while( zX!=0 ){
169 zX[0] = "0123456789abcdef"[y%16]; y /= 16;
170 zX[1] = "0123456789abcdef"[y%16]; y /= 16;
171 zX = strstr(zX, "XX");
173 }else if( (zX = strstr(z,"DD"))!=0 ){
174 unsigned int y = prngInt(p);
175 memcpy(zBuf, z, n+1);
176 z = zBuf;
177 zX = strstr(z,"DD");
178 while( zX!=0 ){
179 zX[0] = "0123456789"[y%10]; y /= 10;
180 zX[1] = "0123456789"[y%10]; y /= 10;
181 zX = strstr(zX, "DD");
184 assert( strstr(z, "XX")==0 );
185 assert( strstr(z, "DD")==0 );
186 if( j+n<STRSZ ){
187 memcpy(&zDest[j], z, n);
188 j += (int)n;
191 zDest[STRSZ-1] = 0;
192 if( j<STRSZ ) zDest[j] = 0;
195 static void randJsonFunc(
196 sqlite3_context *context,
197 int argc,
198 sqlite3_value **argv
200 unsigned int iSeed;
201 int eType = *(int*)sqlite3_user_data(context);
202 Prng prng;
203 char z1[STRSZ+1], z2[STRSZ+1];
205 iSeed = (unsigned int)sqlite3_value_int(argv[0]);
206 prngSeed(&prng, iSeed);
207 jsonExpand(0, z2, &prng, eType, 1000);
208 jsonExpand(z2, z1, &prng, eType, 1000);
209 jsonExpand(z1, z2, &prng, eType, 100);
210 jsonExpand(z2, z1, &prng, eType, 0);
211 sqlite3_result_text(context, z1, -1, SQLITE_TRANSIENT);
214 #ifdef _WIN32
215 __declspec(dllexport)
216 #endif
217 int sqlite3_randomjson_init(
218 sqlite3 *db,
219 char **pzErrMsg,
220 const sqlite3_api_routines *pApi
222 static int cOne = 1;
223 static int cZero = 0;
224 int rc = SQLITE_OK;
225 #ifdef SQLITE_STATIC_RANDOMJSON
226 (void)pApi; /* Unused parameter */
227 #else
228 SQLITE_EXTENSION_INIT2(pApi);
229 #endif
230 (void)pzErrMsg; /* Unused parameter */
231 rc = sqlite3_create_function(db, "random_json", 1,
232 SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
233 &cZero, randJsonFunc, 0, 0);
234 if( rc==SQLITE_OK ){
235 rc = sqlite3_create_function(db, "random_json5", 1,
236 SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
237 &cOne, randJsonFunc, 0, 0);
239 return rc;