FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
sqlcipher/src/json.c at sqlite-release · sqlcipher/sqlcipher · GitHub
sqlcipher/src/json.c at sqlite-release · sqlcipher/sqlcipher · GitHub
Skip to content
Navigation Menu
Sign in
Appearance settings
AI CODE CREATION
GitHub Copilot
Write better code with AI
GitHub Copilot app
Direct agents from issue to merge
MCP Registry
Integrate external tools
DEVELOPER WORKFLOWS
Actions
Automate any workflow
Codespaces
Instant dev environments
Issues
Plan and track work
Code Review
Manage code changes
Code Quality
Enforce quality at merge
APPLICATION SECURITY
GitHub Advanced Security
Find and fix vulnerabilities
Code security
Secure your code as you build
Secret protection
Stop leaks before they start
EXPLORE
Why GitHub
Documentation
Blog
Changelog
Marketplace
View all features
BY COMPANY SIZE
Enterprises
Small and medium teams
Startups
Nonprofits
BY USE CASE
App Modernization
DevSecOps
DevOps
CI/CD
View all use cases
BY INDUSTRY
Healthcare
Financial services
Manufacturing
Government
View all industries
View all solutions
EXPLORE BY TOPIC
AI
Software Development
DevOps
Security
View all topics
EXPLORE BY TYPE
Customer stories
Events & webinars
Ebooks & reports
Business insights
GitHub Skills
SUPPORT & SERVICES
Documentation
Customer support
Community forum
Trust center
Partners
View all resources
COMMUNITY
GitHub Sponsors
Fund open source developers
PROGRAMS
Security Lab
Maintainer Community
Accelerator
GitHub Stars
Archive Program
REPOSITORIES
Topics
Trending
Collections
ENTERPRISE SOLUTIONS
Enterprise platform
AI-powered developer platform
AVAILABLE ADD-ONS
GitHub Advanced Security
Enterprise-grade security features
Copilot for Business
Enterprise-grade AI features
Premium Support
Enterprise-grade 24/7 support
Pricing
Sign in
Sign up
Appearance settings
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
Uh oh!
There was an error while loading.
Please reload this page
.
sqlcipher
/
sqlcipher
Public
Notifications
You must be signed in to change notification settings
Fork
1.4k
Star
7.3k
Code
Issues
17
Pull requests
1
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
sqlcipher
/
src
/
json.c
Copy path
More file actions
More file actions
Latest commit
History
History
History
5737 lines (5537 loc) · 175 KB
Breadcrumbs
sqlcipher
/
src
/
json.c
Copy path
File metadata and controls
5737 lines (5537 loc) · 175 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
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
494
495
496
497
498
499
500
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
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
** 2015-08-12
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** SQLite JSON functions.
**
** This file began as an extension in ext/misc/json1.c in 2015. That
** extension proved so useful that it has now been moved into the core.
**
** The original design stored all JSON as pure text, canonical RFC-8259.
** Support for JSON-5 extensions was added with version 3.42.0 (2023-05-16).
** All generated JSON text still conforms strictly to RFC-8259, but text
** with JSON-5 extensions is accepted as input.
**
** Beginning with version 3.45.0 (circa 2024-01-01), these routines also
** accept BLOB values that have JSON encoded using a binary representation
** called "JSONB". The name JSONB comes from PostgreSQL, however the on-disk
** format for SQLite-JSONB is completely different and incompatible with
** PostgreSQL-JSONB.
**
** Decoding and interpreting JSONB is still O(N) where N is the size of
** the input, the same as text JSON. However, the constant of proportionality
** for JSONB is much smaller due to faster parsing. The size of each
** element in JSONB is encoded in its header, so there is no need to search
** for delimiters using persnickety syntax rules. JSONB seems to be about
** 3x faster than text JSON as a result. JSONB is also tends to be slightly
** smaller than text JSON, by 5% or 10%, but there are corner cases where
** JSONB can be slightly larger. So you are not far mistaken to say that
** a JSONB blob is the same size as the equivalent RFC-8259 text.
**
**
** THE JSONB ENCODING:
**
** Every JSON element is encoded in JSONB as a header and a payload.
** The header is between 1 and 9 bytes in size. The payload is zero
** or more bytes.
**
** The lower 4 bits of the first byte of the header determines the
** element type:
**
** 0: NULL
** 1: TRUE
** 2: FALSE
** 3: INT -- RFC-8259 integer literal
** 4: INT5 -- JSON5 integer literal
** 5: FLOAT -- RFC-8259 floating point literal
** 6: FLOAT5 -- JSON5 floating point literal
** 7: TEXT -- Text literal acceptable to both SQL and JSON
** 8: TEXTJ -- Text containing RFC-8259 escapes
** 9: TEXT5 -- Text containing JSON5 and/or RFC-8259 escapes
** 10: TEXTRAW -- Text containing unescaped syntax characters
** 11: ARRAY
** 12: OBJECT
**
** The other three possible values (13-15) are reserved for future
** enhancements.
**
** The upper 4 bits of the first byte determine the size of the header
** and sometimes also the size of the payload. If X is the first byte
** of the element and if X>>4 is between 0 and 11, then the payload
** will be that many bytes in size and the header is exactly one byte
** in size. Other four values for X>>4 (12-15) indicate that the header
** is more than one byte in size and that the payload size is determined
** by the remainder of the header, interpreted as a unsigned big-endian
** integer.
**
** Value of X>>4 Size integer Total header size
** ------------- -------------------- -----------------
** 12 1 byte (0-255) 2
** 13 2 byte (0-65535) 3
** 14 4 byte (0-4294967295) 5
** 15 8 byte (0-1.8e19) 9
**
** The payload size need not be expressed in its minimal form. For example,
** if the payload size is 10, the size can be expressed in any of 5 different
** ways: (1) (X>>4)==10, (2) (X>>4)==12 following by one 0x0a byte,
** (3) (X>>4)==13 followed by 0x00 and 0x0a, (4) (X>>4)==14 followed by
** 0x00 0x00 0x00 0x0a, or (5) (X>>4)==15 followed by 7 bytes of 0x00 and
** a single byte of 0x0a. The shorter forms are preferred, of course, but
** sometimes when generating JSONB, the payload size is not known in advance
** and it is convenient to reserve sufficient header space to cover the
** largest possible payload size and then come back later and patch up
** the size when it becomes known, resulting in a non-minimal encoding.
**
** The value (X>>4)==15 is not actually used in the current implementation
** (as SQLite is currently unable to handle BLOBs larger than about 2GB)
** but is included in the design to allow for future enhancements.
**
** The payload follows the header. NULL, TRUE, and FALSE have no payload and
** their payload size must always be zero. The payload for INT, INT5,
** FLOAT, FLOAT5, TEXT, TEXTJ, TEXT5, and TEXTROW is text. Note that the
** "..." or '...' delimiters are omitted from the various text encodings.
** The payload for ARRAY and OBJECT is a list of additional elements that
** are the content for the array or object. The payload for an OBJECT
** must be an even number of elements. The first element of each pair is
** the label and must be of type TEXT, TEXTJ, TEXT5, or TEXTRAW.
**
** A valid JSONB blob consists of a single element, as described above.
** Usually this will be an ARRAY or OBJECT element which has many more
** elements as its content. But the overall blob is just a single element.
**
** Input validation for JSONB blobs simply checks that the element type
** code is between 0 and 12 and that the total size of the element
** (header plus payload) is the same as the size of the BLOB. If those
** checks are true, the BLOB is assumed to be JSONB and processing continues.
** Errors are only raised if some other miscoding is discovered during
** processing.
**
** Additional information can be found in the doc/jsonb.md file of the
** canonical SQLite source tree.
*/
#ifndef
SQLITE_OMIT_JSON
#include
"sqliteInt.h"
/* JSONB element types
*/
#define
JSONB_NULL
0
/* "null" */
#define
JSONB_TRUE
1
/* "true" */
#define
JSONB_FALSE
2
/* "false" */
#define
JSONB_INT
3
/* integer acceptable to JSON and SQL */
#define
JSONB_INT5
4
/* integer in 0x000 notation */
#define
JSONB_FLOAT
5
/* float acceptable to JSON and SQL */
#define
JSONB_FLOAT5
6
/* float with JSON5 extensions */
#define
JSONB_TEXT
7
/* Text compatible with both JSON and SQL */
#define
JSONB_TEXTJ
8
/* Text with JSON escapes */
#define
JSONB_TEXT5
9
/* Text with JSON-5 escape */
#define
JSONB_TEXTRAW
10
/* SQL text that needs escaping for JSON */
#define
JSONB_ARRAY
11
/* An array */
#define
JSONB_OBJECT
12
/* An object */
/* Human-readable names for the JSONB values. The index for each
** string must correspond to the JSONB_* integer above.
*/
static
const
char
*
const
jsonbType
[]
=
{
"null"
,
"true"
,
"false"
,
"integer"
,
"integer"
,
"real"
,
"real"
,
"text"
,
"text"
,
"text"
,
"text"
,
"array"
,
"object"
,
""
,
""
,
""
,
""
};
/*
** Growing our own isspace() routine this way is twice as fast as
** the library isspace() function, resulting in a 7% overall performance
** increase for the text-JSON parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
*/
static
const
char
jsonIsSpace
[]
=
{
#ifdef
SQLITE_ASCII
/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
0
,
0
,
1
,
0
,
0
,
/* 0 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 1 */
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 2 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 3 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 4 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 5 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 6 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 7 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 8 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 9 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* a */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* b */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* c */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* d */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* e */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* f */
#endif
#ifdef
SQLITE_EBCDIC
/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
/* 0 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 1 */
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 2 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 3 */
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 4 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 5 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 6 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 7 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 8 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 9 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* a */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* b */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* c */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* d */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* e */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* f */
#endif
};
#define
jsonIsspace
(
x
) (jsonIsSpace[(unsigned char)x])
/*
** The set of all space characters recognized by jsonIsspace().
** Useful as the second argument to strspn().
*/
#ifdef
SQLITE_ASCII
static
const
char
jsonSpaces
[]
=
"\011\012\015\040"
;
#endif
#ifdef
SQLITE_EBCDIC
static
const
char
jsonSpaces
[]
=
"\005\045\015\100"
;
#endif
/*
** Characters that are special to JSON. Control characters,
** '"' and '\\' and '\''. Actually, '\'' is not special to
** canonical JSON, but it is special in JSON-5, so we include
** it in the set of special characters.
*/
static
const
char
jsonIsOk
[
256
]
=
{
#ifdef
SQLITE_ASCII
/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 0 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 1 */
1
,
1
,
0
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 2 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 3 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 4 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
1
,
1
,
/* 5 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 6 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 7 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 8 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 9 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* a */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* b */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* c */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* d */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* e */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
/* f */
#endif
#ifdef
SQLITE_EBCDIC
/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 0 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 1 */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 2 */
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
/* 3 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 4 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 5 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 6 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
0
,
1
,
0
,
/* 7 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 8 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* 9 */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* a */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* b */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* c */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* d */
0
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
/* e */
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
/* f */
#endif
};
/* Objects */
typedef
struct
JsonCache
JsonCache
;
typedef
struct
JsonString
JsonString
;
typedef
struct
JsonParse
JsonParse
;
/*
** Magic number used for the JSON parse cache in sqlite3_get_auxdata()
*/
#define
JSON_CACHE_ID
(-429938)
/* Cache entry */
#define
JSON_CACHE_SIZE
4
/* Max number of cache entries */
/*
** jsonUnescapeOneChar() returns this invalid code point if it encounters
** a syntax error.
*/
#define
JSON_INVALID_CHAR
0x99999
/* A cache mapping JSON text into JSONB blobs.
**
** Each cache entry is a JsonParse object with the following restrictions:
**
** * The bReadOnly flag must be set
**
** * The aBlob[] array must be owned by the JsonParse object. In other
** words, nBlobAlloc must be non-zero.
**
** * eEdit and delta must be zero.
**
** * zJson must be an RCStr. In other words bJsonIsRCStr must be true.
*/
struct
JsonCache
{
sqlite3
*
db
;
/* Database connection */
int
nUsed
;
/* Number of active entries in the cache */
JsonParse
*
a
[
JSON_CACHE_SIZE
];
/* One line for each cache entry */
};
/* An instance of this object represents a JSON string
** under construction. Really, this is a generic string accumulator
** that can be and is used to create strings other than JSON.
**
** If the generated string is longer than will fit into the zSpace[] buffer,
** then it will be an RCStr string. This aids with caching of large
** JSON strings.
*/
struct
JsonString
{
sqlite3_context
*
pCtx
;
/* Function context - put error messages here */
char
*
zBuf
;
/* Append JSON content here */
u64
nAlloc
;
/* Bytes of storage available in zBuf[] */
u64
nUsed
;
/* Bytes of zBuf[] currently used */
u8
bStatic
;
/* True if zBuf is static space */
u8
eErr
;
/* True if an error has been encountered */
char
zSpace
[
100
];
/* Initial static space */
};
/* Allowed values for JsonString.eErr */
#define
JSTRING_OOM
0x01
/* Out of memory */
#define
JSTRING_MALFORMED
0x02
/* Malformed JSONB */
#define
JSTRING_TOODEEP
0x04
/* JSON nested too deep */
#define
JSTRING_ERR
0x08
/* Error already sent to sqlite3_result */
/* The "subtype" set for text JSON values passed through using
** sqlite3_result_subtype() and sqlite3_value_subtype().
*/
#define
JSON_SUBTYPE
74
/* Ascii for "J" */
/*
** Bit values for the flags passed into various SQL function implementations
** via the sqlite3_user_data() value.
*/
#define
JSON_JSON
0x01
/* Result is always JSON */
#define
JSON_SQL
0x02
/* Result is always SQL */
#define
JSON_ABPATH
0x03
/* Allow abbreviated JSON path specs */
#define
JSON_ISSET
0x04
/* json_set(), not json_insert() */
#define
JSON_AINS
0x08
/* json_array_insert(), not json_insert() */
#define
JSON_BLOB
0x10
/* Use the BLOB output format */
#define
JSON_INSERT_TYPE
(
X
) (((X)&0xC)>>2)
/* A parsed JSON value. Lifecycle:
**
** 1. JSON comes in and is parsed into a JSONB value in aBlob. The
** original text is stored in zJson. This step is skipped if the
** input is JSONB instead of text JSON.
**
** 2. The aBlob[] array is searched using the JSON path notation, if needed.
**
** 3. Zero or more changes are made to aBlob[] (via json_remove() or
** json_replace() or json_patch() or similar).
**
** 4. New JSON text is generated from the aBlob[] for output. This step
** is skipped if the function is one of the jsonb_* functions that
** returns JSONB instead of text JSON.
*/
struct
JsonParse
{
u8
*
aBlob
;
/* JSONB representation of JSON value */
u32
nBlob
;
/* Bytes of aBlob[] actually used */
u32
nBlobAlloc
;
/* Bytes allocated to aBlob[]. 0 if aBlob is external */
char
*
zJson
;
/* Json text used for parsing */
sqlite3
*
db
;
/* The database connection to which this object belongs */
int
nJson
;
/* Length of the zJson string in bytes */
u32
nJPRef
;
/* Number of references to this object */
u32
iErr
;
/* Error location in zJson[] */
u16
iDepth
;
/* Nesting depth */
u8
nErr
;
/* Number of errors seen */
u8
oom
;
/* Set to true if out of memory */
u8
bJsonIsRCStr
;
/* True if zJson is an RCStr */
u8
hasNonstd
;
/* True if input uses non-standard features like JSON5 */
u8
bReadOnly
;
/* Do not modify. */
/* Search and edit information. See jsonLookupStep() */
u8
eEdit
;
/* Edit operation to apply */
int
delta
;
/* Size change due to the edit */
u32
nIns
;
/* Number of bytes to insert */
u32
iLabel
;
/* Location of label if search landed on an object value */
u8
*
aIns
;
/* Content to be inserted */
};
/* Allowed values for JsonParse.eEdit */
#define
JEDIT_DEL
1
/* Delete if exists */
#define
JEDIT_REPL
2
/* Overwrite if exists */
#define
JEDIT_INS
3
/* Insert if not exists */
#define
JEDIT_SET
4
/* Insert or overwrite */
#define
JEDIT_AINS
5
/* array_insert() */
/*
** Maximum nesting depth of JSON for this implementation.
**
** This limit is needed to avoid a stack overflow in the recursive
** descent parser. A depth of 1000 is far deeper than any sane JSON
** should go. Historical note: This limit was 2000 prior to version 3.42.0
*/
#ifndef
SQLITE_JSON_MAX_DEPTH
# define
JSON_MAX_DEPTH
1000
#else
# define
JSON_MAX_DEPTH
SQLITE_JSON_MAX_DEPTH
#endif
/*
** Allowed values for the flgs argument to jsonParseFuncArg();
*/
#define
JSON_EDITABLE
0x01
/* Generate a writable JsonParse object */
#define
JSON_KEEPERROR
0x02
/* Return non-NULL even if there is an error */
/**************************************************************************
** Forward references
**************************************************************************/
static
void
jsonReturnStringAsBlob
(
JsonString
*
);
static
int
jsonArgIsJsonb
(
sqlite3_value
*
pJson
,
JsonParse
*
p
);
static
u32
jsonTranslateBlobToText
(
JsonParse
*
,
u32
,
JsonString
*
);
static
void
jsonReturnParse
(
sqlite3_context
*
,
JsonParse
*
);
static
JsonParse
*
jsonParseFuncArg
(
sqlite3_context
*
,
sqlite3_value
*
,
u32
);
static
void
jsonParseFree
(
JsonParse
*
);
static
u32
jsonbPayloadSize
(
const
JsonParse
*
,
u32
,
u32
*
);
static
u32
jsonUnescapeOneChar
(
const
char
*
,
u32
,
u32
*
);
/**************************************************************************
** Utility routines for dealing with JsonCache objects
**************************************************************************/
/*
** Free a JsonCache object.
*/
static
void
jsonCacheDelete
(
JsonCache
*
p
){
int
i
;
for
(
i
=
0
;
i
<
p
->
nUsed
;
i
++
){
jsonParseFree
(
p
->
a
[
i
]);
}
sqlite3DbFree
(
p
->
db
,
p
);
}
static
void
jsonCacheDeleteGeneric
(
void
*
p
){
jsonCacheDelete
((
JsonCache
*
)
p
);
}
/*
** Insert a new entry into the cache. If the cache is full, expel
** the least recently used entry. Return SQLITE_OK on success or a
** result code otherwise.
**
** Cache entries are stored in age order, oldest first.
*/
static
int
jsonCacheInsert
(
sqlite3_context
*
ctx
,
/* The SQL statement context holding the cache */
JsonParse
*
pParse
/* The parse object to be added to the cache */
){
JsonCache
*
p
;
assert
(
pParse
->
zJson
!=
0
);
assert
(
pParse
->
bJsonIsRCStr
);
assert
(
pParse
->
delta
==
0
);
p
=
sqlite3_get_auxdata
(
ctx
,
JSON_CACHE_ID
);
if
(
p
==
0
){
sqlite3
*
db
=
sqlite3_context_db_handle
(
ctx
);
p
=
sqlite3DbMallocZero
(
db
,
sizeof
(
*
p
));
if
(
p
==
0
)
return
SQLITE_NOMEM
;
p
->
db
=
db
;
sqlite3_set_auxdata
(
ctx
,
JSON_CACHE_ID
,
p
,
jsonCacheDeleteGeneric
);
p
=
sqlite3_get_auxdata
(
ctx
,
JSON_CACHE_ID
);
if
(
p
==
0
)
return
SQLITE_NOMEM
;
}
if
(
p
->
nUsed
>=
JSON_CACHE_SIZE
){
jsonParseFree
(
p
->
a
[
0
]);
memmove
(
p
->
a
,
&
p
->
a
[
1
], (
JSON_CACHE_SIZE
-
1
)
*
sizeof
(
p
->
a
[
0
]));
p
->
nUsed
=
JSON_CACHE_SIZE
-
1
;
}
assert
(
pParse
->
nBlobAlloc
>
0
);
pParse
->
eEdit
=
0
;
pParse
->
nJPRef
++
;
pParse
->
bReadOnly
=
1
;
p
->
a
[
p
->
nUsed
]
=
pParse
;
p
->
nUsed
++
;
return
SQLITE_OK
;
}
/*
** Search for a cached translation the json text supplied by pArg. Return
** the JsonParse object if found. Return NULL if not found.
**
** When a match if found, the matching entry is moved to become the
** most-recently used entry if it isn't so already.
**
** The JsonParse object returned still belongs to the Cache and might
** be deleted at any moment. If the caller wants the JsonParse to
** linger, it needs to increment the nPJRef reference counter.
*/
static
JsonParse
*
jsonCacheSearch
(
sqlite3_context
*
ctx
,
/* The SQL statement context holding the cache */
sqlite3_value
*
pArg
/* Function argument containing SQL text */
){
JsonCache
*
p
;
int
i
;
const
char
*
zJson
;
int
nJson
;
if
(
sqlite3_value_type
(
pArg
)
!=
SQLITE_TEXT
){
return
0
;
}
zJson
=
(
const
char
*
)
sqlite3_value_text
(
pArg
);
if
(
zJson
==
0
)
return
0
;
nJson
=
sqlite3_value_bytes
(
pArg
);
p
=
sqlite3_get_auxdata
(
ctx
,
JSON_CACHE_ID
);
if
(
p
==
0
){
return
0
;
}
for
(
i
=
0
;
i
<
p
->
nUsed
;
i
++
){
if
(
p
->
a
[
i
]
->
zJson
==
zJson
)
break
;
}
if
(
i
>=
p
->
nUsed
){
for
(
i
=
0
;
i
<
p
->
nUsed
;
i
++
){
if
(
p
->
a
[
i
]
->
nJson
!=
nJson
)
continue
;
if
(
memcmp
(
p
->
a
[
i
]
->
zJson
,
zJson
,
nJson
)
==
0
)
break
;
}
}
if
(
i
<
p
->
nUsed
){
if
(
i
<
p
->
nUsed
-
1
){
/* Make the matching entry the most recently used entry */
JsonParse
*
tmp
=
p
->
a
[
i
];
memmove
(
&
p
->
a
[
i
],
&
p
->
a
[
i
+
1
], (
p
->
nUsed
-
i
-
1
)
*
sizeof
(
tmp
));
p
->
a
[
p
->
nUsed
-
1
]
=
tmp
;
i
=
p
->
nUsed
-
1
;
}
assert
(
p
->
a
[
i
]
->
delta
==
0
);
return
p
->
a
[
i
];
}
else
{
return
0
;
}
}
/**************************************************************************
** Utility routines for dealing with JsonString objects
**************************************************************************/
/* Turn uninitialized bulk memory into a valid JsonString object
** holding a zero-length string.
*/
static
void
jsonStringZero
(
JsonString
*
p
){
p
->
zBuf
=
p
->
zSpace
;
p
->
nAlloc
=
sizeof
(
p
->
zSpace
);
p
->
nUsed
=
0
;
p
->
bStatic
=
1
;
}
/* Initialize the JsonString object
*/
static
void
jsonStringInit
(
JsonString
*
p
,
sqlite3_context
*
pCtx
){
p
->
pCtx
=
pCtx
;
p
->
eErr
=
0
;
jsonStringZero
(
p
);
}
/* Free all allocated memory and reset the JsonString object back to its
** initial state.
*/
static
void
jsonStringReset
(
JsonString
*
p
){
if
( !
p
->
bStatic
)
sqlite3RCStrUnref
(
p
->
zBuf
);
jsonStringZero
(
p
);
}
/* Report an out-of-memory (OOM) condition
*/
static
void
jsonStringOom
(
JsonString
*
p
){
p
->
eErr
|=
JSTRING_OOM
;
if
(
p
->
pCtx
)
sqlite3_result_error_nomem
(
p
->
pCtx
);
jsonStringReset
(
p
);
}
/* Report JSON nested too deep
*/
static
void
jsonStringTooDeep
(
JsonString
*
p
){
p
->
eErr
|=
JSTRING_TOODEEP
;
assert
(
p
->
pCtx
!=
0
);
sqlite3_result_error
(
p
->
pCtx
,
"JSON nested too deep"
,
-1
);
jsonStringReset
(
p
);
}
/* Enlarge pJson->zBuf so that it can hold at least N more bytes.
** Return zero on success. Return non-zero on an OOM error
*/
static
int
jsonStringGrow
(
JsonString
*
p
,
u32
N
){
u64
nTotal
=
N
<
p
->
nAlloc
?
p
->
nAlloc
*
2
:
p
->
nAlloc
+
N
+
10
;
char
*
zNew
;
if
(
p
->
bStatic
){
if
(
p
->
eErr
)
return
1
;
zNew
=
sqlite3RCStrNew
(
nTotal
);
if
(
zNew
==
0
){
jsonStringOom
(
p
);
return
SQLITE_NOMEM
;
}
memcpy
(
zNew
,
p
->
zBuf
, (
size_t
)
p
->
nUsed
);
p
->
zBuf
=
zNew
;
p
->
bStatic
=
0
;
}
else
{
p
->
zBuf
=
sqlite3RCStrResize
(
p
->
zBuf
,
nTotal
);
if
(
p
->
zBuf
==
0
){
p
->
eErr
|=
JSTRING_OOM
;
jsonStringZero
(
p
);
return
SQLITE_NOMEM
;
}
}
p
->
nAlloc
=
nTotal
;
return
SQLITE_OK
;
}
/* Append N bytes from zIn onto the end of the JsonString string.
*/
static
SQLITE_NOINLINE
void
jsonStringExpandAndAppend
(
JsonString
*
p
,
const
char
*
zIn
,
u32
N
){
assert
(
N
>
0
);
if
(
jsonStringGrow
(
p
,
N
) )
return
;
memcpy
(
p
->
zBuf
+
p
->
nUsed
,
zIn
,
N
);
p
->
nUsed
+=
N
;
}
static
void
jsonAppendRaw
(
JsonString
*
p
,
const
char
*
zIn
,
u32
N
){
if
(
N
==
0
)
return
;
if
(
N
+
p
->
nUsed
>=
p
->
nAlloc
){
jsonStringExpandAndAppend
(
p
,
zIn
,
N
);
}
else
{
memcpy
(
p
->
zBuf
+
p
->
nUsed
,
zIn
,
N
);
p
->
nUsed
+=
N
;
}
}
static
void
jsonAppendRawNZ
(
JsonString
*
p
,
const
char
*
zIn
,
u32
N
){
assert
(
N
>
0
);
if
(
N
+
p
->
nUsed
>=
p
->
nAlloc
){
jsonStringExpandAndAppend
(
p
,
zIn
,
N
);
}
else
{
memcpy
(
p
->
zBuf
+
p
->
nUsed
,
zIn
,
N
);
p
->
nUsed
+=
N
;
}
}
/* Append formatted text (not to exceed N bytes) to the JsonString.
*/
static
void
jsonPrintf
(
int
N
,
JsonString
*
p
,
const
char
*
zFormat
, ...){
va_list
ap
;
if
( (
p
->
nUsed
+
N
>=
p
->
nAlloc
)
&&
jsonStringGrow
(
p
,
N
) )
return
;
va_start
(
ap
,
zFormat
);
sqlite3_vsnprintf
(
N
,
p
->
zBuf
+
p
->
nUsed
,
zFormat
,
ap
);
va_end
(
ap
);
p
->
nUsed
+=
(
int
)
strlen
(
p
->
zBuf
+
p
->
nUsed
);
}
/* Append a single character
*/
static
SQLITE_NOINLINE
void
jsonAppendCharExpand
(
JsonString
*
p
,
char
c
){
if
(
jsonStringGrow
(
p
,
1
) )
return
;
p
->
zBuf
[
p
->
nUsed
++
]
=
c
;
}
static
void
jsonAppendChar
(
JsonString
*
p
,
char
c
){
if
(
p
->
nUsed
>=
p
->
nAlloc
){
jsonAppendCharExpand
(
p
,
c
);
}
else
{
p
->
zBuf
[
p
->
nUsed
++
]
=
c
;
}
}
/* Remove a single character from the end of the string
*/
static
void
jsonStringTrimOneChar
(
JsonString
*
p
){
if
(
p
->
eErr
==
0
){
assert
(
p
->
nUsed
>
0
);
p
->
nUsed
--
;
}
}
/* Make sure there is a zero terminator on p->zBuf[]
**
** Return true on success. Return false if an OOM prevents this
** from happening.
*/
static
int
jsonStringTerminate
(
JsonString
*
p
){
jsonAppendChar
(
p
,
0
);
jsonStringTrimOneChar
(
p
);
return
p
->
eErr
==
0
;
}
/* Append a comma separator to the output buffer, if the previous
** character is not '[' or '{'.
*/
static
void
jsonAppendSeparator
(
JsonString
*
p
){
char
c
;
if
(
p
->
nUsed
==
0
)
return
;
c
=
p
->
zBuf
[
p
->
nUsed
-
1
];
if
(
c
==
'['
||
c
==
'{'
)
return
;
jsonAppendChar
(
p
,
','
);
}
/* c is a control character. Append the canonical JSON representation
** of that control character to p.
**
** This routine assumes that the output buffer has already been enlarged
** sufficiently to hold the worst-case encoding plus a nul terminator.
*/
static
void
jsonAppendControlChar
(
JsonString
*
p
,
u8
c
){
static
const
char
aSpecial
[]
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
'b'
,
't'
,
'n'
,
0
,
'f'
,
'r'
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
assert
(
sizeof
(
aSpecial
)
==
32
);
assert
(
aSpecial
[
'\b'
]
==
'b'
);
assert
(
aSpecial
[
'\f'
]
==
'f'
);
assert
(
aSpecial
[
'\n'
]
==
'n'
);
assert
(
aSpecial
[
'\r'
]
==
'r'
);
assert
(
aSpecial
[
'\t'
]
==
't'
);
assert
(
c
>=
0
&&
c
<
sizeof
(
aSpecial
) );
assert
(
p
->
nUsed
+
7
<=
p
->
nAlloc
);
if
(
aSpecial
[
c
] ){
p
->
zBuf
[
p
->
nUsed
]
=
'\\'
;
p
->
zBuf
[
p
->
nUsed
+
1
]
=
aSpecial
[
c
];
p
->
nUsed
+=
2
;
}
else
{
p
->
zBuf
[
p
->
nUsed
]
=
'\\'
;
p
->
zBuf
[
p
->
nUsed
+
1
]
=
'u'
;
p
->
zBuf
[
p
->
nUsed
+
2
]
=
'0'
;
p
->
zBuf
[
p
->
nUsed
+
3
]
=
'0'
;
p
->
zBuf
[
p
->
nUsed
+
4
]
=
"0123456789abcdef"
[
c
>>
4
];
p
->
zBuf
[
p
->
nUsed
+
5
]
=
"0123456789abcdef"
[
c
&
0xf
];
p
->
nUsed
+=
6
;
}
}
/* Append the N-byte string in zIn to the end of the JsonString string
** under construction. Enclose the string in double-quotes ("...") and
** escape any double-quotes or backslash characters contained within the
** string.
**
** This routine is a high-runner. There is a measurable performance
** increase associated with unwinding the jsonIsOk[] loop.
*/
static
void
jsonAppendString
(
JsonString
*
p
,
const
char
*
zIn
,
u32
N
){
u32
k
;
u8
c
;
const
u8
*
z
=
(
const
u8
*
)
zIn
;
if
(
z
==
0
)
return
;
if
( (
N
+
p
->
nUsed
+
2
>=
p
->
nAlloc
)
&&
jsonStringGrow
(
p
,
N
+
2
)
!=
0
)
return
;
p
->
zBuf
[
p
->
nUsed
++
]
=
'"'
;
while
(
1
/*exit-by-break*/
){
k
=
0
;
/* The following while() is the 4-way unwound equivalent of
**
** while( k<N && jsonIsOk[z[k]] ){ k++; }
*/
while
(
1
/* Exit by break */
){
if
(
k
+
3
>=
N
){
while
(
k
<
N
&&
jsonIsOk
[
z
[
k
]] ){
k
++
; }
break
;
}
if
( !
jsonIsOk
[
z
[
k
]] ){
break
;
}
if
( !
jsonIsOk
[
z
[
k
+
1
]] ){
k
+=
1
;
break
;
}
if
( !
jsonIsOk
[
z
[
k
+
2
]] ){
k
+=
2
;
break
;
}
if
( !
jsonIsOk
[
z
[
k
+
3
]] ){
k
+=
3
;
break
;
}
else
{
k
+=
4
;
}
}
if
(
k
>=
N
){
if
(
k
>
0
){
memcpy
(
&
p
->
zBuf
[
p
->
nUsed
],
z
,
k
);
p
->
nUsed
+=
k
;
}
break
;
}
if
(
k
>
0
){
memcpy
(
&
p
->
zBuf
[
p
->
nUsed
],
z
,
k
);
p
->
nUsed
+=
k
;
z
+=
k
;
N
-=
k
;
}
c
=
z
[
0
];
if
(
c
==
'"'
||
c
==
'\\'
){
if
( (
p
->
nUsed
+
N
+
3
>
p
->
nAlloc
)
&&
jsonStringGrow
(
p
,
N
+
3
)
!=
0
)
return
;
p
->
zBuf
[
p
->
nUsed
++
]
=
'\\'
;
p
->
zBuf
[
p
->
nUsed
++
]
=
c
;
}
else
if
(
c
==
'\''
){
p
->
zBuf
[
p
->
nUsed
++
]
=
c
;
}
else
{
if
( (
p
->
nUsed
+
N
+
7
>
p
->
nAlloc
)
&&
jsonStringGrow
(
p
,
N
+
7
)
!=
0
)
return
;
jsonAppendControlChar
(
p
,
c
);
}
z
++
;
N
--
;
}
p
->
zBuf
[
p
->
nUsed
++
]
=
'"'
;
assert
(
p
->
nUsed
<
p
->
nAlloc
);
}
/*
** Append an sqlite3_value (such as a function parameter) to the JSON
** string under construction in p.
*/
static
void
jsonAppendSqlValue
(
JsonString
*
p
,
/* Append to this JSON string */
sqlite3_value
*
pValue
/* Value to append */
){
switch
(
sqlite3_value_type
(
pValue
) ){
case
SQLITE_NULL
: {
jsonAppendRawNZ
(
p
,
"null"
,
4
);
break
;
}
case
SQLITE_FLOAT
: {
jsonPrintf
(
100
,
p
,
"%!0.17g"
,
sqlite3_value_double
(
pValue
));
break
;
}
case
SQLITE_INTEGER
: {
const
char
*
z
=
(
const
char
*
)
sqlite3_value_text
(
pValue
);
u32
n
=
(
u32
)
sqlite3_value_bytes
(
pValue
);
jsonAppendRaw
(
p
,
z
,
n
);
break
;
}
case
SQLITE_TEXT
: {
const
char
*
z
=
(
const
char
*
)
sqlite3_value_text
(
pValue
);
u32
n
=
(
u32
)
sqlite3_value_bytes
(
pValue
);
if
(
sqlite3_value_subtype
(
pValue
)
==
JSON_SUBTYPE
){
jsonAppendRaw
(
p
,
z
,
n
);
}
else
{
jsonAppendString
(
p
,
z
,
n
);
}
break
;
}
default
: {
JsonParse
px
;
memset
(
&
px
,
0
,
sizeof
(
px
));
if
(
jsonArgIsJsonb
(
pValue
,
&
px
) ){
jsonTranslateBlobToText
(
&
px
,
0
,
p
);
}
else
if
(
p
->
eErr
==
0
){
sqlite3_result_error
(
p
->
pCtx
,
"JSON cannot hold BLOB values"
,
-1
);
p
->
eErr
=
JSTRING_ERR
;
jsonStringReset
(
p
);
}
break
;
}
}
}
/* Make the text in p (which is probably a generated JSON text string)
** the result of the SQL function.
**
** The JsonString is reset.
**
** If pParse and ctx are both non-NULL, then the SQL string in p is
** loaded into the zJson field of the pParse object as a RCStr and the
** pParse is added to the cache.
*/
static
void
jsonReturnString
(
JsonString
*
p
,
/* String to return */
JsonParse
*
pParse
,
/* JSONB source or NULL */
sqlite3_context
*
ctx
/* Where to cache */
){
assert
( (
pParse
!=
0
)
==
(
ctx
!=
0
) );
assert
(
ctx
==
0
||
ctx
==
p
->
pCtx
);
jsonStringTerminate
(
p
);
if
(
p
->
eErr
==
0
){
int
flags
=
SQLITE_PTR_TO_INT
(
sqlite3_user_data
(
p
->
pCtx
));
if
(
flags
&
JSON_BLOB
){
jsonReturnStringAsBlob
(
p
);
}
else
if
(
p
->
bStatic
){
sqlite3_result_text64
(
p
->
pCtx
,
p
->
zBuf
,
p
->
nUsed
,
SQLITE_TRANSIENT
,
SQLITE_UTF8
);
}
else
{
if
(
pParse
&&
pParse
->
bJsonIsRCStr
==
0
&&
pParse
->
nBlobAlloc
>
0
){
int
rc
;
pParse
->
zJson
=
sqlite3RCStrRef
(
p
->
zBuf
);
pParse
->
nJson
=
p
->
nUsed
;
pParse
->
bJsonIsRCStr
=
1
;
rc
=
jsonCacheInsert
(
ctx
,
pParse
);
if
(
rc
==
SQLITE_NOMEM
){
sqlite3_result_error_nomem
(
ctx
);
jsonStringReset
(
p
);
return
;
}
}
sqlite3_result_text64
(
p
->
pCtx
,
sqlite3RCStrRef
(
p
->
zBuf
),
p
->
nUsed
,
sqlite3RCStrUnref
,
SQLITE_UTF8
);
}
}
else
if
(
p
->
eErr
&
JSTRING_OOM
){
sqlite3_result_error_nomem
(
p
->
pCtx
);
}
else
if
(
p
->
eErr
&
JSTRING_TOODEEP
){
/* error already in p->pCtx */
}
else
if
(
p
->
eErr
&
JSTRING_MALFORMED
){
sqlite3_result_error
(
p
->
pCtx
,
"malformed JSON"
,
-1
);
}
jsonStringReset
(
p
);
}
/**************************************************************************
** Utility routines for dealing with JsonParse objects
**************************************************************************/
/*
** Reclaim all memory allocated by a JsonParse object. But do not
** delete the JsonParse object itself.
*/
static
void
jsonParseReset
(
JsonParse
*
pParse
){
assert
(
pParse
->
nJPRef
<=
1
);
if
(
pParse
->
bJsonIsRCStr
){
sqlite3RCStrUnref
(
pParse
->
zJson
);
pParse
->
zJson
=
0
;
pParse
->
nJson
=
0
;
pParse
->
bJsonIsRCStr
=
0
;
}
if
(
pParse
->
nBlobAlloc
){
sqlite3DbFree
(
pParse
->
db
,
pParse
->
aBlob
);
pParse
->
aBlob
=
0
;
pParse
->
nBlob
=
0
;
pParse
->
nBlobAlloc
=
0
;
}
}
/*
** Decrement the reference count on the JsonParse object. When the
** count reaches zero, free the object.
*/
static
void
jsonParseFree
(
JsonParse
*
pParse
){
if
(
pParse
){
if
(
pParse
->
nJPRef
>
1
){
pParse
->
nJPRef
--
;
}
else
{
jsonParseReset
(
pParse
);
sqlite3DbFree
(
pParse
->
db
,
pParse
);
}
}
}
/**************************************************************************
** Utility routines for the JSON text parser
**************************************************************************/
/*
** Translate a single byte of Hex into an integer.
** This routine only gives a correct answer if h really is a valid hexadecimal
** character: 0..9a..fA..F. But unlike sqlite3HexToInt(), it does not
** assert() if the digit is not hex.
*/
static
u8
jsonHexToInt
(
int
h
){
#ifdef
SQLITE_ASCII
h
+=
9
*
(
1
&
(
h
>>
6
));
#endif
#ifdef
SQLITE_EBCDIC
h
+=
9
*
(
1
&
~(
h
>>
4
));
#endif
return
(
u8
)(
h
&
0xf
);
}
/*
** Convert a 4-byte hex string into an integer
*/
static
u32
jsonHexToInt4
(
const
char
*
z
){
u32
v
;
v
=
(
jsonHexToInt
(
z
[
0
])<<
12
)
+
(
jsonHexToInt
(
z
[
1
])<<
8
)
+
(
jsonHexToInt
(
z
[
2
])<<
4
)
+
jsonHexToInt
(
z
[
3
]);
return
v
;
}
/*
** Return true if z[] begins with 2 (or more) hexadecimal digits
*/
static
int
jsonIs2Hex
(
const
char
*
z
){
return
sqlite3Isxdigit
(
z
[
0
])
&&
sqlite3Isxdigit
(
z
[
1
]);
}
/*
** Return true if z[] begins with 4 (or more) hexadecimal digits
*/
static
int
jsonIs4Hex
(
const
char
*
z
){
return
jsonIs2Hex
(
z
)
&&
jsonIs2Hex
(
&
z
[
2
]);
}
/*
** Return the number of bytes of JSON5 whitespace at the beginning of
** the input string z[].
**
** JSON5 whitespace consists of any of the following characters:
**
** Unicode UTF-8 Name
** U+0009 09 horizontal tab
** U+000a 0a line feed
** U+000b 0b vertical tab
** U+000c 0c form feed
** U+000d 0d carriage return
** U+0020 20 space
** U+00a0 c2 a0 non-breaking space
** U+1680 e1 9a 80 ogham space mark
** U+2000 e2 80 80 en quad
** U+2001 e2 80 81 em quad
** U+2002 e2 80 82 en space
View remainder of file in raw view
Footer
© 2026 GitHub, Inc.
Footer navigation
Terms
Privacy
Security
Status
Community
Docs
Contact
You can’t perform that action at this time.
Back
|
FazBrowse Home
|
New Git URL