pjson 1.0.0
A small, owning JSON value for C++11
Loading...
Searching...
No Matches
pjson.h
1//
2// Copyright 2025 ByteDance Ltd. and/or its affiliates. All rights reserved.
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15//===----------------------------------------------------------------------===//
16// pjson — Praveen's JSON: an ultra-simple JSON value type for C++.
17//
18// A single class, ByteDance::pjson, represents any JSON value and offers an
19// ergonomic obj["key"][i] = value building style plus parsing, serialization,
20// lookup, mutation, equality, and JSON-Schema-subset validation. All method
21// bodies live in pjson.cpp; this header only declares the interface.
22//
23// Author: Praveen Babu J D
24// License: Apache 2.0
25//
26#ifndef PRAVEENJSON_H
27#define PRAVEENJSON_H
28
29// Library version. PJSON_VERSION is the string form ("MAJOR.MINOR.PATCH");
30// the numeric parts allow compile-time checks, e.g.
31// #if PJSON_VERSION_MAJOR >= 1
32#define PJSON_VERSION_MAJOR 1
33#define PJSON_VERSION_MINOR 0
34#define PJSON_VERSION_PATCH 0
35#define PJSON_VERSION "1.0.0"
36
37#include <cstddef>
38#include <cstdint>
39#include <iosfwd>
40#include <map>
41#include <memory>
42#include <string>
43#include <type_traits>
44#include <vector>
45
46namespace ByteDance {
47 struct pjsonImpl;
48 //==[Interface]============================================================
49 /// Owning, mutable JSON value with deep-copy semantics.
50 ///
51 /// Child pointers and string views exposed by lookup/access APIs are borrowed
52 /// from the owning tree. They become invalid when the child or an ancestor is
53 /// destroyed, replaced, reset, erased, moved, swapped, cleared, or successfully
54 /// patched. Unless an operation is `noexcept` or explicitly reports failures,
55 /// allocation and standard-library exceptions may escape.
56 class pjson {
57 public:
58 //== Library version =================================================
59 /// Returns the process-lifetime semantic-version string for this library.
60 static const char* getVersion();
61
62 //== Types ===========================================================
63
64 // JSON value kind. Numbers are stored in one of two representations:
65 // whole numbers as a 64-bit signed integer (jsonNumberInt) and
66 // everything else as a double (jsonNumberDouble).
68 jsonNull = 0, // stable zero-valued discriminator for the default state
73 jsonArray, //[ ] array
74 jsonObject, // { ... } map
75 };
76
77 // Runtime allocator for persistent DOM storage. The allocator is
78 // non-owning and must outlive every pjson value that refers to it.
79 // Allocation covers pjson child/root nodes plus the std::string,
80 // array, and object wrapper objects. Storage used internally by those
81 // standard-library objects and transient parser/algorithm scratch space
82 // continues to use the standard allocator.
83 struct Allocator {
84 enum AllocationKind {
91 /// Enables destruction through an Allocator base pointer.
92 virtual ~Allocator();
93 /// Returns non-null aligned storage or throws; returning null is unsupported.
94 virtual void* allocate(size_t aSize, size_t aAlignment, AllocationKind aKind) = 0;
95 /// Releases a non-null allocation using its original size, alignment, and kind.
96 virtual void deallocate(void* aPtr, size_t aSize, size_t aAlignment,
97 AllocationKind aKind) noexcept = 0;
98 };
99
100 // Stateless ownership for allocator-created nodes. Provenance is read
101 // from the node itself, so moving this pointer never transfers or owns
102 // the Allocator object.
103 struct ValueDeleter {
104 /// Destroys aValue's tree through its originating allocator; accepts null.
105 void operator()(pjson* aValue) const noexcept;
106 };
107 typedef std::unique_ptr<pjson, ValueDeleter> unique_ptr;
109 // Bounds how much work a parse may do. Parsing always enforces RFC 8259
110 // conformance and rejects:
111 // - unknown escapes (e.g. "\q")
112 // - lone/unpaired \u surrogates
113 // - upper/mixed-case keywords (NULL, True, FALSE)
114 // - raw control characters inside strings
115 // - malformed UTF-8 bytes
116 struct ParseOptions {
118
119 int maxDepth; // nesting limit; values <= 0 enforce a one-level limit
120 size_t maxNodes; // max JSON values created (0 = unlimited)
121 size_t maxInputBytes; // max input length in bytes (0 = unlimited)
123 /// Selects duplicate rejection, depth 512, one million nodes, and a
124 /// 64 MiB input limit.
126 };
128 // Filled in by the error-reporting parse() overloads. `ok` is true when
129 // parsing succeeded; otherwise `offset` is the zero-based byte position,
130 // `line` is one-based, `column` is a one-based byte column, and
131 // `message` describes the first failure. Reporting parse APIs reset all
132 // fields on entry and leave this success state after a successful parse.
133 struct ParseError {
134 bool ok;
135 size_t offset;
136 size_t line;
137 size_t column;
138 std::string message;
139 /// Constructs a success state at the beginning of an input.
141 };
143 // Structured JSON Pointer (RFC 6901) lookup failure. `tokenIndex` is
144 // zero-based and `token` is the decoded token that could not be
145 // resolved (or the source token when its escape sequence is invalid).
146 // std::string reporting overloads reset all fields on entry. A C-string
147 // overload can report allocation failure before copying the pointer text.
148 struct PointerError {
149 enum Code {
150 Ok,
168 /// Constructs a successful lookup state with no pointer or token details.
170 };
172 // Structured JSON Patch (RFC 6902) / Merge Patch (RFC 7396) failure.
173 // Patch application is atomic: failure leaves the target unchanged.
174 // Reporting patch APIs reset all fields on entry and on success.
175 struct PatchError {
176 enum Code {
177 Ok,
180 MissingOp,
205 std::string token;
206 std::string message;
207 /// Constructs a successful patch state with no operation or token details.
209 };
211 // Bounds transactional patch amplification. Zero selects the documented
212 // built-in ceiling rather than disabling a safety limit. Clone bytes
213 // include node storage plus string and object-key payload bytes.
215 size_t maxOperations; // default/hard ceiling: 10,000
216 size_t maxClonedNodes; // default/hard ceiling: 1,000,000
217 size_t maxClonedBytes; // default/hard ceiling: 64 MiB
218 size_t maxWork; // default/hard ceiling: 1,000,000
219 PatchOptions();
220 };
221
222 // Controls JSON serialization. The default produces the same compact,
223 // ascending-key output as toString()/write() without options. Pretty
224 // output places each array element/object member on its own line. Only
225 // space and tab are valid indentation characters; any other value is
226 // treated as a space so serialization always remains valid JSON.
227 //
228 // Objects are stored in std::map, so source/insertion order is not
229 // available. Key ordering is therefore explicitly ascending or
230 // descending according to std::map's bytewise std::string ordering.
231 struct SerializeOptions {
233
234 bool pretty;
235 size_t indentWidth;
236 char indentCharacter;
237 bool escapeNonAscii;
239 size_t maxOutputBytes; // default 64 MiB; zero explicitly means unlimited
240
241 /// Selects compact output, two-space indentation, and ascending keys.
243 /// Returns the defaults with pretty printing enabled.
245 };
247 // Event sink for non-owning SAX parsing. Return false from any callback
248 // to cancel parsing; public parseSax* APIs return false for cancellation
249 // or thrown exceptions and populate ParseError when one is supplied.
250 //
251 // Callbacks are delivered in source order. Duplicate-key policy still
252 // applies: RejectDuplicateKeys fails on the duplicate key,
253 // KeepFirstDuplicate suppresses later duplicate-value subtrees, and
254 // KeepLastDuplicate accepts duplicates while still reporting both
255 // occurrences because a streaming SAX walk cannot retract prior events.
256 // String and key references are borrowed and remain valid only for the
257 // duration of their callback. The handler itself need only outlive the
258 // parseSax* call. Default callbacks accept the event and do nothing.
259 struct SaxHandler {
260 /// Enables destruction through a SaxHandler base pointer.
261 virtual ~SaxHandler();
262 /// Receives a JSON null value; return false to cancel parsing.
263 virtual bool onNull();
264 /// Receives a JSON boolean value; return false to cancel parsing.
265 virtual bool onBool(bool aValue);
266 /// Receives an integer-valued JSON number; return false to cancel parsing.
267 virtual bool onInt(int64_t aValue);
268 /// Receives a floating-point JSON number; return false to cancel parsing.
269 virtual bool onDouble(double aValue);
270 /// Receives borrowed decoded string bytes; return false to cancel parsing.
271 virtual bool onString(const std::string& aValue);
272 /// Marks the beginning of an array; return false to cancel parsing.
273 virtual bool onStartArray();
274 /// Marks the end of an array; return false to cancel parsing.
275 virtual bool onEndArray();
276 /// Marks the beginning of an object; return false to cancel parsing.
277 virtual bool onStartObject();
278 /// Receives a borrowed decoded object key; return false to cancel parsing.
279 virtual bool onKey(const std::string& aKey);
280 /// Marks the end of an object; return false to cancel parsing.
281 virtual bool onEndObject();
282 };
284 // One schema-validation failure: `path` is a JSON Pointer to the
285 // offending node (e.g. "/address/zip", "" for the document root) and
286 // `message` explains what was wrong.
287 struct SchemaError {
288 std::string path;
289 std::string message;
290 /// Constructs an error with an empty root path and message.
292 /// Constructs an error for aPath with the supplied diagnostic message.
293 SchemaError(const std::string& aPath, const std::string& aMsg);
294 };
295
296 // Bounds schema regular-expression work. By default only a conservative,
297 // non-ambiguous ECMAScript subset is accepted and both pattern/subject
298 // sizes are capped, preventing catastrophic std::regex backtracking.
299 // trustedRegex() restores unrestricted ECMAScript regex behavior for
300 // schemas and input controlled by the application.
302 size_t maxRegexPatternBytes; // 0 = unlimited (default: 256)
303 size_t maxRegexSubjectBytes; // 0 = unlimited (default: 4096)
304 bool allowUnsafeRegex; // default false
305 /// Recursive depth (default 512); zero still selects the hard ceiling of 512.
306 size_t maxValidationDepth;
307 /// Resolved references (default 1024); zero selects the hard ceiling of 1024.
308 size_t maxRefResolutions;
309 /// Validation work units (default 1,000,000); zero selects that hard ceiling.
310 size_t maxValidationWork;
311 /// Reported errors (default 100); zero selects the hard ceiling of 100.
312 size_t maxErrors;
313 bool validateFormats; // validate known string formats (default true)
314 /// Selects bounded safe-regex, traversal, reference, work, error, and format defaults.
316 /// Disables only regex restrictions; all other defaults remain enabled.
318 };
319
320 //== Construction / lifetime =========================================
321 /// Constructs null using the process-lifetime default allocator.
323 /// Constructs null bound to borrowed aAlloc, which must outlive this tree.
324 explicit pjson(Allocator& aAlloc) noexcept;
325 /// Destroys this value and its complete owned subtree.
326 ~pjson();
327 /// Deep-copies aFrom using aFrom's borrowed allocator.
328 pjson(const pjson& aFrom);
329 /// Deep-copies aFrom into borrowed aAlloc.
330 pjson(const pjson& aFrom, Allocator& aAlloc);
331 /// Transfers aFrom's storage and allocator in O(1), leaving aFrom null.
332 pjson(pjson&& aFrom) noexcept;
333 /// Transfers in O(1) when allocators match; otherwise deep-copies then clears aFrom.
335 /// Deep-copies aFrom while preserving this value's allocator.
337 /// Moves aFrom while preserving this allocator; cross-allocator moves may allocate.
339 /// Deep-copies aFrom while preserving this value's allocator.
340 void copyFrom(const pjson& aFrom);
341 /// Destroys the current contents and becomes null.
342 void reset();
343 /// Replaces the value with the empty/default value of a valid jsonType.
345 /// Calls resetTo() only when the type differs, otherwise preserving contents.
347 // Same-allocator swap is O(1). A cross-allocator swap is rejected as a
348 // safe no-op; use canSwap() to test before requesting it.
349 /// Exchanges contents when allocators match; otherwise does nothing.
350 void swap(pjson& aOther) noexcept;
351 /// Returns the borrowed allocator bound to this value.
353 /// Returns whether swap(aOther) can exchange contents.
355
356 //== DOM parsing with the default allocator ==========================
357 // Each parse accepts exactly one JSON value followed only by whitespace.
358 // In-memory parse failures return an empty pointer; diagnostic overloads
359 // reset aError and describe the first failure. A byte span may contain
360 // embedded NUL bytes, but a null aSrc is always an error.
361 /// Parses aStr into an owning tree using the default allocator.
364 /// Parses the aSize-byte span at aSrc using the default allocator.
365 static pjson::unique_ptr parse(const char* aSrc, size_t aSize,
367 /// Parses aStr and reports the first failure in aError.
370 /// Parses the aSize-byte span and reports the first failure in aError.
373
374 // parseStream() buffers the document in chunks while enforcing
375 // maxInputBytes. Stream or temporary-buffer exceptions may propagate.
376 /// Buffers and parses one document from aIn using the default allocator.
379 /// Buffers and parses aIn, reporting ordinary parse/read failures in aError.
382
383 //== DOM parsing with a custom allocator =============================
384 // Allocator-aware DOM parsing routes root/child nodes and string/array/
385 // object wrapper objects through borrowed aAlloc. Standard-container
386 // backing buffers still use their standard allocators, as described by
387 // Allocator above. aAlloc must outlive the returned tree.
388 /// Parses aStr with allocator-backed nodes and wrapper objects.
391 /// Parses a byte span with allocator-backed nodes and wrapper objects.
394 /// Parses aStr with aAlloc and reports the first failure in aError.
397 /// Parses a byte span with aAlloc and reports the first failure in aError.
400 /// Buffers aIn, then parses with allocator-backed nodes and wrappers.
403 /// Buffers and parses aIn with aAlloc, reporting ordinary failures in aError.
406
407 //== SAX parsing =====================================================
408 // SAX parsing retains neither aHandler nor callback arguments. It returns
409 // false for invalid input, cancellation, stream failure, or a handler
410 // exception; callbacks already delivered before failure are not undone.
411 /// Parses aStr and emits its events to aHandler without building a DOM.
412 static bool parseSax(const std::string& aStr, SaxHandler& aHandler,
414 /// Parses the aSize-byte span and emits its events to aHandler.
415 static bool parseSax(const char* aSrc, size_t aSize, SaxHandler& aHandler,
417 /// SAX-parses aStr and reports failure or cancellation in aError.
420 /// SAX-parses a byte span and reports failure or cancellation in aError.
421 static bool parseSax(const char* aSrc, size_t aSize, SaxHandler& aHandler,
423 // True streaming SAX parse: reads the istream incrementally and never
424 // buffers the full document in memory.
425 /// Incrementally parses aIn and emits events to aHandler.
426 static bool parseSaxStream(std::istream& aIn, SaxHandler& aHandler,
428 /// Incrementally SAX-parses aIn and reports failure or cancellation in aError.
431
432 //== Serialization ===================================================
433 // Non-finite stored doubles serialize as JSON null. Invalid UTF-8 in a
434 // string value or object key is a serialization failure: toString() throws,
435 // while write() sets failbit (and may propagate stream exceptions).
436 // toString() may also throw for allocation or length failure.
437 /// Returns compact JSON using the default serialization options.
438 std::string toString() const;
439 /// Returns JSON serialized according to aOpts.
441 /// Writes compact JSON to aOut using the default serialization options.
442 void write(std::ostream& aOut) const;
443 /// Writes JSON configured by aOpts to aOut.
444 void write(std::ostream& aOut, const SerializeOptions& aOpts) const;
445
446 //== Type inspection =================================================
447 /// Returns this node's stored JSON representation.
449 /// Returns whether this node is null.
450 bool isNull() const;
451 /// Returns whether this node stores a string.
453 /// Returns whether this node stores either numeric representation.
455 /// Returns whether this node stores an integer representation.
456 bool isInt() const;
457 /// Returns whether this node stores a floating-point representation.
458 bool isDouble() const;
459 /// Returns whether this node stores a boolean.
460 bool isBool() const;
461 /// Returns whether this node stores an array.
463 /// Returns whether this node stores an object.
465
466 // Minimal C++11-compatible, non-owning view of a JSON string. A view
467 // aliases bytes owned by this pjson node and is valid only while that
468 // node remains alive and unchanged. Assignment, reset, swap, move,
469 // destruction, erasing the node, or replacing/resetting an ancestor
470 // invalidates it. Strings may contain embedded NUL bytes; use size()
471 // rather than strlen().
473 public:
474 /// Constructs an empty view with data() == nullptr.
476 /// Returns the borrowed first byte; a default view returns null.
477 const char* data() const noexcept;
478 /// Returns the number of bytes in the view, including embedded NUL bytes.
479 size_t size() const noexcept;
480 /// Returns whether size() is zero.
481 bool empty() const noexcept;
482
483 private:
485 /// Constructs the internal borrowed view used by tryGet().
486 StringView(const char* aData, size_t aSize) noexcept;
488 const char* _data;
489 size_t _size;
490 };
492 // Strict typed access to this node. On a type mismatch, returns false
493 // and leaves aResult unchanged. Integers may widen to double; no other
494 // coercions are performed. StringView avoids a string copy.
495 /// Extracts an integer only when this node stores jsonNumberInt.
497 /// Extracts a numeric value, widening a stored integer when necessary.
498 bool tryGet(double& aResult) const noexcept;
499 /// Extracts a boolean only when this node stores jsonBoolean.
500 bool tryGet(bool& aResult) const noexcept;
501 /// Copies a string only when this node stores jsonString.
502 bool tryGet(std::string& aResult) const;
503 /// Borrows a string view only when this node stores jsonString.
505
506 //== Container queries ===============================================
507 /// Returns the element/member count for containers, or zero for scalars.
508 size_t size() const;
509 /// Returns whether size() is zero; consequently all scalar values are empty.
510 bool empty() const;
511 /// Empties a container without changing its type, or resets a scalar to null.
512 void clear();
513
514 /// Returns copied object keys in std::map order, or an empty vector otherwise.
515 std::vector<std::string> keys() const;
517 //== Non-mutating lookup =============================================
518 /// Returns whether this object contains aKey.
519 bool hasKey(const std::string& aKey) const;
520 /// Returns whether this object contains non-null aKey; null returns false.
521 bool hasKey(const char* aKey) const;
522 /// Returns whether this array contains aIndex; negative indexes count from the end.
523 bool hasIndex(int aIndex) const noexcept;
525 // Returns a pointer to the child stored under aKey, or nullptr when
526 // this is not a map or the key is absent. Unlike operator[], this
527 // never creates or mutates anything.
528 /// Returns the borrowed child at aKey, or null when absent or not an object.
529 pjson* find(const std::string& aKey);
530 /// Returns the borrowed child at non-null aKey, or null on failure.
532 /// Returns the read-only borrowed child at aKey, or null on failure.
533 const pjson* find(const std::string& aKey) const;
534 /// Returns the read-only borrowed child at non-null aKey, or null on failure.
536
537 // Non-vivifying array lookup. Negative indexes count from the end
538 // (-1 is the last element); indexes outside the array return nullptr.
539 // These overloads never change this node or its size.
540 /// Returns the borrowed array child at aIndex, or null on failure.
542 /// Returns the read-only borrowed array child at aIndex, or null on failure.
544
545 // RFC 6901 lookup. The empty pointer addresses this value; every
546 // non-empty pointer must begin with '/'. Lookups are iterative and
547 // never create missing nodes. The '-' token is not a lookup index.
548 /// Escapes one decoded reference token for inclusion in a JSON Pointer.
549 static std::string escapePointerToken(const std::string& aToken);
550 /// Resolves aPointer and returns the borrowed target, or null on failure.
551 pjson* findPointer(const std::string& aPointer);
552 /// Resolves aPointer and returns the read-only borrowed target, or null.
554 /// Resolves aPointer and reports lookup failure in aError.
556 /// Resolves aPointer read-only and reports lookup failure in aError.
558 /// Resolves a non-null pointer string; null returns failure.
560 /// Resolves a non-null pointer string read-only; null returns failure.
562 /// Resolves a non-null pointer string and reports failure in aError.
564 /// Resolves a non-null pointer string read-only and reports failure in aError.
566
567 // Strict typed child access layered on find() and node-level tryGet().
568 // Missing/null keys, invalid indexes, and type mismatches leave aResult
569 // unchanged. Negative indexes count from the end.
570 /// Extracts the integer child at aKey without mutating this object.
571 bool tryGet(const std::string& aKey, int64_t& aResult) const;
572 /// Extracts the numeric child at aKey as a double.
573 bool tryGet(const std::string& aKey, double& aResult) const;
574 /// Extracts the boolean child at aKey.
575 bool tryGet(const std::string& aKey, bool& aResult) const;
576 /// Copies the string child at aKey.
577 bool tryGet(const std::string& aKey, std::string& aResult) const;
578 /// Borrows a view of the string child at aKey.
579 bool tryGet(const std::string& aKey, StringView& aResult) const;
580
581 /// Extracts the integer child at non-null aKey.
582 bool tryGet(const char* aKey, int64_t& aResult) const;
583 /// Extracts the numeric child at non-null aKey as a double.
584 bool tryGet(const char* aKey, double& aResult) const;
585 /// Extracts the boolean child at non-null aKey.
586 bool tryGet(const char* aKey, bool& aResult) const;
587 /// Copies the string child at non-null aKey.
588 bool tryGet(const char* aKey, std::string& aResult) const;
589 /// Borrows a view of the string child at non-null aKey.
590 bool tryGet(const char* aKey, StringView& aResult) const;
592 /// Extracts the integer array child at aIndex.
594 /// Extracts the numeric array child at aIndex as a double.
595 bool tryGet(int aIndex, double& aResult) const noexcept;
596 /// Extracts the boolean array child at aIndex.
597 bool tryGet(int aIndex, bool& aResult) const noexcept;
598 /// Copies the string array child at aIndex.
599 bool tryGet(int aIndex, std::string& aResult) const;
600 /// Borrows a view of the string array child at aIndex.
603 //== Building / mutable access =======================================
604 // operator[] is a direct builder API. A key access changes a non-object
605 // into an object and creates a missing null child. An index access changes
606 // a non-array into an array; negative indexes count from the end and clamp
607 // before the beginning to zero, while indexes past the end grow the array
608 // with null children. A single access that would create more than one
609 // million children throws std::length_error before mutation. Use
610 // find()/tryGet() for reads.
611 /// Returns or creates the child at aString.
612 pjson& operator[](const std::string& aString);
613 /// Returns or creates the child at aSkey; throws std::invalid_argument for null.
614 pjson& operator[](const char* aSkey);
615 /// Returns or creates the child at index under the auto-growth rules above.
616 pjson& operator[](int index);
617
618 // Assign a scalar value, replacing whatever this node was. Numbers are
619 // stored as int64_t (integers) or double (floating point).
620 /// Replaces this value with a copy of aString.
621 pjson& operator=(const std::string& aString);
622 /// Replaces this value with aCString; throws std::invalid_argument for null.
623 pjson& operator=(const char* aCString);
624 /// Replaces this value with aBool.
625 pjson& operator=(const bool aBool);
626 /// Replaces this value with aInt.
628 /// Replaces this value with aDouble; non-finite values serialize as null.
629 pjson& operator=(const double aDouble);
630
631 // Vector assignment atomically replaces this node with an array of copied
632 // children allocated through this node's allocator.
633 /// Replaces this value with a copied string array.
634 pjson& operator=(const std::vector<std::string>& aValueArray);
635 /// Replaces this value with a copied boolean array.
636 pjson& operator=(const std::vector<bool>& aValueArray);
637 /// Replaces this value with a copied integer array.
638 pjson& operator=(const std::vector<int64_t>& aValueArray);
639 /// Replaces this value with a copied double array.
640 pjson& operator=(const std::vector<double>& aValueArray);
642 // Scalar append adds one copied child. If this node is not already an
643 // array, its previous value is discarded rather than retained.
644 /// Appends a copy of aValue as a string child.
645 pjson& operator+=(const std::string& aValue);
646 /// Appends aValue as a string child; throws std::invalid_argument for null.
647 pjson& operator+=(const char* aValue);
648 /// Appends aValue as a boolean child.
649 pjson& operator+=(const bool aValue);
650 /// Appends aValue as an integer child.
652 /// Appends aValue as a double child.
653 pjson& operator+=(const double aValue);
654
655 // Vector append copies every element. A non-array's prior value is
656 // discarded; even an empty vector promotes a non-array to an empty array.
657 /// Appends every string in aValueArray.
658 pjson& operator+=(const std::vector<std::string>& aValueArray);
659 /// Appends every boolean in aValueArray.
660 pjson& operator+=(const std::vector<bool>& aValueArray);
661 /// Appends every integer in aValueArray.
662 pjson& operator+=(const std::vector<int64_t>& aValueArray);
663 /// Appends every double in aValueArray.
664 pjson& operator+=(const std::vector<double>& aValueArray);
666 // Remove and free the child under a map key / at an array index.
667 // Array indexes are zero-based and erasure shifts later elements left.
668 /// Erases aKey and returns whether an object member was removed.
669 bool erase(const std::string& aKey);
670 /// Erases non-null aKey; null or a non-object returns false.
671 bool erase(const char* aKey);
672 /// Erases aIndex and returns whether an array element was removed.
673 bool erase(size_t aIndex);
675 // Applies all RFC 6902 operations to a scratch document and commits
676 // only if every operation succeeds. RFC 7396 Merge Patch is likewise
677 // atomic and uses an iterative traversal for deeply nested objects.
678 // These bool-returning boundaries convert allocation and internal
679 // exceptions into PatchError instead of allowing them to escape. Patch
680 // input is borrowed and unchanged; successful commit invalidates prior
681 // views into the target. Overloads without aError discard diagnostics.
682 /// Atomically applies an RFC 6902 patch document.
684 /// Atomically applies RFC 6902 and reports failure details in aError.
687 /// Atomically applies an RFC 7396 Merge Patch document.
690 /// Atomically applies RFC 7396 and reports failure details in aError.
693
694 //== Equality (deep, structural) =====================================
695 // Integer and floating nodes compare equal when numerically equal
696 // (e.g. 1 == 1.0). Arrays compare element-wise in order; objects
697 // compare by key/value regardless of insertion order.
698 /// Returns whether this value and aOther are structurally equal.
700 /// Returns the negation of operator==.
702
703 //== Schema validation ===============================================
704 // Validates this value against a schema that is itself a pjson object,
705 // using the documented JSON Schema subset; this is not a complete draft
706 // implementation. Returns true when the
707 // value conforms. Never throws. The second form appends reported
708 // keyword failures rather than stopping at the first. Errors inside
709 // non-selected anyOf/oneOf/not branches are intentionally suppressed,
710 // and a resource-budget failure can stop further validation.
711 //
712 // Supported keywords:
713 // type, enum, const,
714 // $ref (local JSON Pointer fragments),
715 // properties, patternProperties, propertyNames, required,
716 // dependentRequired, dependencies, additionalProperties,
717 // minProperties, maxProperties,
718 // items, minItems, maxItems, uniqueItems,
719 // minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf,
720 // minLength, maxLength, pattern, format,
721 // allOf, anyOf, oneOf, not.
722 // A boolean schema (true/false) accepts/rejects everything. Unknown
723 // keywords and unsupported keyword shapes are ignored. Both inputs are
724 // borrowed and unchanged; the collecting overload appends to aErrors
725 // without clearing existing entries. Resource aborts may stop collection.
726 /// Returns whether this value satisfies aSchema under aOpts.
729 /// Validates and appends discovered failures to aErrors.
730 bool validate(const pjson& aSchema, std::vector<SchemaError>& aErrors,
732
733 private:
734 //== Internal helpers ================================================
735 // The parser, schema validator, and encoding routines live entirely in
736 // pjson.cpp as the pjsonImpl helper struct, so this header stays small.
737 // pjsonImpl is a friend so it can touch the data union directly; only
738 // the few instance helpers other members call are declared here.
741
742 /// Iteratively deep-copies aFrom's contents using this node's allocator.
743 void copyContentsFrom(const pjson& aFrom);
744
745 //== Data ============================================================
746 typedef std::vector<pjson*> ArrayStorage;
747 typedef std::map<std::string, pjson*> ObjectStorage;
748
749 Allocator* _allocator;
750 bool _allocatorOwnedNode;
751 // Intrusive scratch link used only by allocation-free iterative tree
752 // destruction. It is null during normal object lifetime.
753 pjson* _disposeNext;
754 jsonType _eType = jsonType::jsonNull;
755 union Storage {
756 void* _pValueRaw;
757 ObjectStorage* _pValueMap;
758 ArrayStorage* _pValueArray;
759 int64_t _valueInt;
760 double _valueDouble;
761 bool _valueBool;
762 std::string* _pValueString;
763
764 /// Initializes the raw representation to null.
765 Storage();
766 } _uValue;
767 };
768 //========================================================================
769}; // end namespace ByteDance
770#endif /* !PRAVEENJSON_H */
Minimal C++11-compatible, non-owning view of a JSON string. A view aliases bytes owned by this pjson ...
Definition pjson.h:484
StringView() noexcept
Public API member StringView; see the API overview for its contract. / Returns the borrowed first byt...
Owning, mutable JSON value with deep-copy semantics.
Definition pjson.h:56
jsonType getType() const
Public API member getType; see the API overview for its contract. / Returns whether this node is null...
void resetIfNeeded(jsonType aeType)
Public API member resetIfNeeded; see the API overview for its contract. Same-allocator swap is O(1)....
bool isInt() const
Public API member isInt; see the API overview for its contract. / Returns whether this node stores a ...
pjson & operator=(const pjson &aFrom)
Public API member operator=; see the API overview for its contract. / Moves aFrom while preserving th...
void reset()
Public API member reset; see the API overview for its contract. / Replaces the value with the empty/d...
bool applyMergePatch(const pjson &aPatch, const PatchOptions &aOpts=PatchOptions()) noexcept
Public API member PatchOptions; see the API overview for its contract. / Atomically applies RFC 7396 ...
std::vector< std::string > keys() const
Public API member keys; see the API overview for its contract.
void swap(pjson &aOther) noexcept
Public API member swap; see the API overview for its contract. / Returns the borrowed allocator bound...
~pjson()
Public API member ~pjson; see the API overview for its contract. / Deep-copies aFrom using aFrom's bo...
bool isObject() const
Public API member isObject; see the API overview for its contract.
static bool parseSax(const std::string &aStr, SaxHandler &aHandler, const ParseOptions &aOpts=ParseOptions())
SAX parsing retains neither aHandler nor callback arguments. It returns false for invalid input,...
void write(std::ostream &aOut) const
Public API member write; see the API overview for its contract. / Writes JSON configured by aOpts to ...
std::unique_ptr< pjson, ValueDeleter > unique_ptr
Public API member unique_ptr; see the API overview for its contract.
Definition pjson.h:108
static pjson::unique_ptr parse(const std::string &aStr, const ParseOptions &aOpts=ParseOptions())
Each parse accepts exactly one JSON value followed only by whitespace. In-memory parse failures retur...
void resetTo(jsonType aeType)
Public API member resetTo; see the API overview for its contract. / Calls resetTo() only when the typ...
bool isBool() const
Public API member isBool; see the API overview for its contract. / Returns whether this node stores a...
pjson(pjson &&aFrom, Allocator &aAlloc)
Public API member pjson; see the API overview for its contract. / Deep-copies aFrom while preserving ...
static pjson::unique_ptr parseStream(std::istream &aIn, const ParseOptions &aOpts=ParseOptions())
parseStream() buffers the document in chunks while enforcing maxInputBytes. Stream or temporary-buffe...
bool tryGet(int64_t &aResult) const noexcept
Strict typed access to this node. On a type mismatch, returns false and leaves aResult unchanged....
pjson(Allocator &aAlloc) noexcept
Public API member pjson; see the API overview for its contract. / Destroys this value and its complet...
bool applyPatch(const pjson &aPatch, const PatchOptions &aOpts=PatchOptions()) noexcept
Applies all RFC 6902 operations to a scratch document and commits only if every operation succeeds....
bool isNumber() const
Public API member isNumber; see the API overview for its contract. / Returns whether this node stores...
pjson(pjson &&aFrom) noexcept
Public API member pjson; see the API overview for its contract. / Transfers in O(1) when allocators m...
bool isArray() const
Public API member isArray; see the API overview for its contract. / Returns whether this node stores ...
pjson & operator=(pjson &&aFrom)
Public API member operator=; see the API overview for its contract. / Deep-copies aFrom while preserv...
Allocator & getAllocator() const noexcept
Public API member getAllocator; see the API overview for its contract. / Returns whether swap(aOther)...
pjson * find(const std::string &aKey)
Returns a pointer to the child stored under aKey, or nullptr when this is not a map or the key is abs...
static std::string escapePointerToken(const std::string &aToken)
RFC 6901 lookup. The empty pointer addresses this value; every non-empty pointer must begin with '/'....
pjson * findPointer(const std::string &aPointer)
Public API member findPointer; see the API overview for its contract. / Resolves aPointer and returns...
pjson(const pjson &aFrom)
Public API member pjson; see the API overview for its contract. / Deep-copies aFrom into borrowed aAl...
bool isDouble() const
Public API member isDouble; see the API overview for its contract. / Returns whether this node stores...
pjson(const pjson &aFrom, Allocator &aAlloc)
Public API member pjson; see the API overview for its contract. / Transfers aFrom's storage and alloc...
bool hasIndex(int aIndex) const noexcept
Public API member hasIndex; see the API overview for its contract.
void clear()
Public API member clear; see the API overview for its contract.
static const char * getVersion()
Public API member getVersion; see the API overview for its contract.
bool canSwap(const pjson &aOther) const noexcept
Public API member canSwap; see the API overview for its contract.
bool validate(const pjson &aSchema, const SchemaOptions &aOpts=SchemaOptions()) const noexcept
Validates this value against a schema that is itself a pjson object, using the documented JSON Schema...
bool isNull() const
Public API member isNull; see the API overview for its contract. / Returns whether this node stores a...
std::string toString() const
Non-finite stored doubles serialize as JSON null. Invalid UTF-8 in a string value or object key is a ...
static bool parseSaxStream(std::istream &aIn, SaxHandler &aHandler, const ParseOptions &aOpts=ParseOptions())
Public API member ParseOptions; see the API overview for its contract. / Incrementally SAX-parses aIn...
friend struct pjsonImpl
The parser, schema validator, and encoding routines live entirely in pjson.cpp as the pjsonImpl helpe...
Definition pjson.h:751
void copyFrom(const pjson &aFrom)
Public API member copyFrom; see the API overview for its contract. / Destroys the current contents an...
bool isString() const
Public API member isString; see the API overview for its contract. / Returns whether this node stores...
bool empty() const
Public API member empty; see the API overview for its contract. / Empties a container without changin...
bool erase(const std::string &aKey)
Remove and free the child under a map key / at an array index. Array indexes are zero-based and erasu...
pjson()
Public API member pjson; see the API overview for its contract. / Constructs null bound to borrowed a...
size_t size() const
Public API member size; see the API overview for its contract. / Returns whether size() is zero; cons...
jsonType
JSON value kind. Numbers are stored in one of two representations: whole numbers as a 64-bit signed i...
Definition pjson.h:67
@ jsonBoolean
JSON value or policy constant.
Definition pjson.h:72
@ jsonNumberDouble
JSON value or policy constant.
Definition pjson.h:71
@ jsonString
JSON value or policy constant.
Definition pjson.h:69
@ jsonNumberInt
JSON value or policy constant.
Definition pjson.h:70
@ jsonArray
[ ] array
Definition pjson.h:73
@ jsonObject
{ ... } map
Definition pjson.h:74
@ jsonNull
stable zero-valued discriminator for the default state
Definition pjson.h:68
bool hasKey(const std::string &aKey) const
Public API member hasKey; see the API overview for its contract. / Returns whether this object contai...
Namespace containing the pjson public API.
Definition pjson.h:46
Runtime allocator for persistent DOM storage. The allocator is non-owning and must outlive every pjso...
Definition pjson.h:83
virtual ~Allocator()
Public API member ~Allocator; see the API overview for its contract. / Returns non-null aligned stora...
AllocationKind
Selects one of the public JSON policies.
Definition pjson.h:85
@ ObjectAllocation
JSON value or policy constant.
Definition pjson.h:89
@ StringAllocation
JSON value or policy constant.
Definition pjson.h:87
@ ArrayAllocation
JSON value or policy constant.
Definition pjson.h:88
@ NodeAllocation
JSON value or policy constant.
Definition pjson.h:86
virtual void deallocate(void *aPtr, size_t aSize, size_t aAlignment, AllocationKind aKind) noexcept=0
Public API member member; see the API overview for its contract.
virtual void * allocate(size_t aSize, size_t aAlignment, AllocationKind aKind)=0
Public API member allocate; see the API overview for its contract. / Releases a non-null allocation u...
Filled in by the error-reporting parse() overloads. ok is true when parsing succeeded; otherwise offs...
Definition pjson.h:139
std::string message
Public API member message; see the API overview for its contract. / Constructs a success state at the...
Definition pjson.h:144
bool ok
Public API member ok; see the API overview for its contract.
Definition pjson.h:140
size_t column
Public API member column; see the API overview for its contract.
Definition pjson.h:143
ParseError()
Public API member ParseError; see the API overview for its contract.
size_t line
Public API member line; see the API overview for its contract.
Definition pjson.h:142
size_t offset
Public API member offset; see the API overview for its contract.
Definition pjson.h:141
Bounds how much work a parse may do. Parsing always enforces RFC 8259 conformance and rejects:
Definition pjson.h:117
size_t maxNodes
max JSON values created (0 = unlimited)
Definition pjson.h:126
DuplicateKeyPolicy
Selects one of the public JSON policies.
Definition pjson.h:119
@ KeepFirstDuplicate
JSON value or policy constant.
Definition pjson.h:121
@ KeepLastDuplicate
JSON value or policy constant.
Definition pjson.h:122
@ RejectDuplicateKeys
JSON value or policy constant.
Definition pjson.h:120
size_t maxInputBytes
max input length in bytes (0 = unlimited)
Definition pjson.h:127
ParseOptions()
Public API member ParseOptions; see the API overview for its contract.
DuplicateKeyPolicy duplicateKeys
Public API member duplicateKeys; see the API overview for its contract. / Selects duplicate rejection...
Definition pjson.h:128
int maxDepth
nesting limit; values <= 0 enforce a one-level limit
Definition pjson.h:125
Structured JSON Patch (RFC 6902) / Merge Patch (RFC 7396) failure. Patch application is atomic: failu...
Definition pjson.h:182
std::string token
Public API member token; see the API overview for its contract.
Definition pjson.h:213
size_t opIndex
Public API member opIndex; see the API overview for its contract.
Definition pjson.h:208
bool ok
Public API member ok; see the API overview for its contract.
Definition pjson.h:206
PatchError()
Public API member PatchError; see the API overview for its contract.
std::string from
Public API member from; see the API overview for its contract.
Definition pjson.h:211
std::string message
Public API member message; see the API overview for its contract. / Constructs a successful patch sta...
Definition pjson.h:214
Code code
Public API member code; see the API overview for its contract.
Definition pjson.h:207
std::string path
Public API member path; see the API overview for its contract.
Definition pjson.h:210
std::string op
Public API member op; see the API overview for its contract.
Definition pjson.h:209
Code
Selects one of the public JSON policies.
Definition pjson.h:184
@ MissingFrom
JSON value or policy constant.
Definition pjson.h:190
@ MoveIntoDescendant
JSON value or policy constant.
Definition pjson.h:199
@ MissingValue
JSON value or policy constant.
Definition pjson.h:191
@ InvalidOp
JSON value or policy constant.
Definition pjson.h:192
@ InvalidArrayIndex
JSON value or policy constant.
Definition pjson.h:196
@ AllocationFailure
JSON value or policy constant.
Definition pjson.h:202
@ ArrayIndexOutOfRange
JSON value or policy constant.
Definition pjson.h:197
@ ResourceLimit
JSON value or policy constant.
Definition pjson.h:201
@ MoveRootNotAllowed
JSON value or policy constant.
Definition pjson.h:198
@ InvalidPath
JSON value or policy constant.
Definition pjson.h:193
@ MissingOp
JSON value or policy constant.
Definition pjson.h:188
@ InternalError
JSON value or policy constant.
Definition pjson.h:203
@ TestFailed
JSON value or policy constant.
Definition pjson.h:200
@ InvalidPatchDocument
JSON value or policy constant.
Definition pjson.h:186
@ OperationNotObject
JSON value or policy constant.
Definition pjson.h:187
@ MissingPath
JSON value or policy constant.
Definition pjson.h:189
@ Ok
JSON value or policy constant.
Definition pjson.h:185
@ TargetMissing
JSON value or policy constant.
Definition pjson.h:195
@ InvalidFrom
JSON value or policy constant.
Definition pjson.h:194
size_t tokenIndex
Public API member tokenIndex; see the API overview for its contract.
Definition pjson.h:212
Bounds transactional patch amplification. Zero selects the documented built-in ceiling rather than di...
Definition pjson.h:222
size_t maxClonedBytes
default/hard ceiling: 64 MiB
Definition pjson.h:225
size_t maxOperations
default/hard ceiling: 10,000
Definition pjson.h:223
size_t maxClonedNodes
default/hard ceiling: 1,000,000
Definition pjson.h:224
size_t maxWork
default/hard ceiling: 1,000,000
Definition pjson.h:226
PatchOptions()
Public API member PatchOptions; see the API overview for its contract.
Structured JSON Pointer (RFC 6901) lookup failure. tokenIndex is zero-based and token is the decoded ...
Definition pjson.h:154
size_t tokenIndex
Public API member tokenIndex; see the API overview for its contract.
Definition pjson.h:172
Code
Selects one of the public JSON policies.
Definition pjson.h:156
@ InvalidSyntax
JSON value or policy constant.
Definition pjson.h:158
@ ArrayIndexOutOfRange
JSON value or policy constant.
Definition pjson.h:163
@ InternalError
JSON value or policy constant.
Definition pjson.h:166
@ AllocationFailure
JSON value or policy constant.
Definition pjson.h:165
@ InvalidEscape
JSON value or policy constant.
Definition pjson.h:159
@ MissingTarget
JSON value or policy constant.
Definition pjson.h:160
@ AppendTokenNotAllowed
JSON value or policy constant.
Definition pjson.h:164
@ InvalidArrayIndex
JSON value or policy constant.
Definition pjson.h:162
@ ExpectedContainer
JSON value or policy constant.
Definition pjson.h:161
@ Ok
JSON value or policy constant.
Definition pjson.h:157
std::string token
Public API member token; see the API overview for its contract.
Definition pjson.h:173
bool ok
Public API member ok; see the API overview for its contract.
Definition pjson.h:169
std::string message
Public API member message; see the API overview for its contract. / Constructs a successful lookup st...
Definition pjson.h:174
std::string pointer
Public API member pointer; see the API overview for its contract.
Definition pjson.h:171
Code code
Public API member code; see the API overview for its contract.
Definition pjson.h:170
PointerError()
Public API member PointerError; see the API overview for its contract.
Event sink for non-owning SAX parsing. Return false from any callback to cancel parsing; public parse...
Definition pjson.h:271
virtual bool onDouble(double aValue)
Public API member onDouble; see the API overview for its contract. / Receives borrowed decoded string...
virtual bool onStartArray()
Public API member onStartArray; see the API overview for its contract. / Marks the end of an array; r...
virtual ~SaxHandler()
Public API member ~SaxHandler; see the API overview for its contract. / Receives a JSON null value; r...
virtual bool onInt(int64_t aValue)
Public API member onInt; see the API overview for its contract. / Receives a floating-point JSON numb...
virtual bool onStartObject()
Public API member onStartObject; see the API overview for its contract. / Receives a borrowed decoded...
virtual bool onString(const std::string &aValue)
Public API member onString; see the API overview for its contract. / Marks the beginning of an array;...
virtual bool onEndArray()
Public API member onEndArray; see the API overview for its contract. / Marks the beginning of an obje...
virtual bool onEndObject()
Public API member onEndObject; see the API overview for its contract.
virtual bool onKey(const std::string &aKey)
Public API member onKey; see the API overview for its contract. / Marks the end of an object; return ...
virtual bool onBool(bool aValue)
Public API member onBool; see the API overview for its contract. / Receives an integer-valued JSON nu...
virtual bool onNull()
Public API member onNull; see the API overview for its contract. / Receives a JSON boolean value; ret...
One schema-validation failure: path is a JSON Pointer to the offending node (e.g. "/address/zip",...
Definition pjson.h:299
SchemaError()
Public API member SchemaError; see the API overview for its contract. / Constructs an error for aPath...
SchemaError(const std::string &aPath, const std::string &aMsg)
Public API member SchemaError; see the API overview for its contract.
std::string path
Public API member path; see the API overview for its contract.
Definition pjson.h:300
std::string message
Public API member message; see the API overview for its contract. / Constructs an error with an empty...
Definition pjson.h:301
Bounds schema regular-expression work. By default only a conservative, non-ambiguous ECMAScript subse...
Definition pjson.h:313
static SchemaOptions trustedRegex()
Public API member trustedRegex; see the API overview for its contract.
bool allowUnsafeRegex
default false / Recursive depth (default 512); zero still selects the hard ceiling of 512.
Definition pjson.h:316
size_t maxValidationWork
Public API member maxValidationWork; see the API overview for its contract. / Reported errors (defaul...
Definition pjson.h:322
SchemaOptions()
Public API member SchemaOptions; see the API overview for its contract. / Disables only regex restric...
size_t maxErrors
Public API member maxErrors; see the API overview for its contract.
Definition pjson.h:324
bool validateFormats
validate known string formats (default true) / Selects bounded safe-regex, traversal,...
Definition pjson.h:325
size_t maxRegexSubjectBytes
0 = unlimited (default: 4096)
Definition pjson.h:315
size_t maxValidationDepth
Public API member maxValidationDepth; see the API overview for its contract. / Resolved references (d...
Definition pjson.h:318
size_t maxRegexPatternBytes
0 = unlimited (default: 256)
Definition pjson.h:314
size_t maxRefResolutions
Public API member maxRefResolutions; see the API overview for its contract. / Validation work units (...
Definition pjson.h:320
Controls JSON serialization. The default produces the same compact, ascending-key output as toString(...
Definition pjson.h:239
KeyOrder
Selects one of the public JSON policies.
Definition pjson.h:241
@ AscendingKeys
JSON value or policy constant.
Definition pjson.h:242
@ DescendingKeys
JSON value or policy constant.
Definition pjson.h:243
size_t maxOutputBytes
default 64 MiB; zero explicitly means unlimited
Definition pjson.h:251
char indentCharacter
Public API member indentCharacter; see the API overview for its contract.
Definition pjson.h:248
static SerializeOptions prettyPrinted()
Public API member prettyPrinted; see the API overview for its contract.
size_t indentWidth
Public API member indentWidth; see the API overview for its contract.
Definition pjson.h:247
bool escapeNonAscii
Public API member escapeNonAscii; see the API overview for its contract.
Definition pjson.h:249
KeyOrder keyOrder
Public API member keyOrder; see the API overview for its contract.
Definition pjson.h:250
bool pretty
Public API member pretty; see the API overview for its contract.
Definition pjson.h:246
SerializeOptions()
Public API member SerializeOptions; see the API overview for its contract. / Returns the defaults wit...
Stateless ownership for allocator-created nodes. Provenance is read from the node itself,...
Definition pjson.h:104
void operator()(pjson *aValue) const noexcept
Public API member operator; see the API overview for its contract.