about summary refs log tree commit diff stats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/Main.cpp25
-rw-r--r--Source/Memory.h25
-rw-r--r--Source/Panel.cpp134
-rw-r--r--Source/Panel.h85
-rw-r--r--Source/Randomizer.cpp74
-rw-r--r--Source/RandomizerCore.cpp16
-rw-r--r--Source/RandomizerCore.h15
-rw-r--r--Source/Source.vcxproj2
-rw-r--r--Source/Source.vcxproj.filters6
-rw-r--r--Source/json.hpp20274
10 files changed, 20597 insertions, 59 deletions
diff --git a/Source/Main.cpp b/Source/Main.cpp index 8336c77..8c4bf8c 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp
@@ -6,13 +6,19 @@
6#include "Randomizer.h" 6#include "Randomizer.h"
7#include "Version.h" 7#include "Version.h"
8#include "Random.h" 8#include "Random.h"
9#include "Panel.h"
9 10
10#define IDC_RANDOMIZE 0x401 11#define IDC_RANDOMIZE 0x401
11#define IDC_TOGGLESPEED 0x402 12#define IDC_TOGGLESPEED 0x402
12#define IDC_SPEEDRUNNER 0x403 13#define IDC_SPEEDRUNNER 0x403
13#define IDC_HARDMODE 0x404 14#define IDC_HARDMODE 0x404
15#define IDC_READ 0x405
16#define IDC_RANDOM 0x406
17#define IDC_WRITE 0x407
14 18
15HWND hwndSeed, hwndRandomize; 19HWND hwndSeed, hwndRandomize;
20int panel = 0x12C9;
21std::shared_ptr<Panel> _panel;
16 22
17LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 23LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
18{ 24{
@@ -57,6 +63,15 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
57 SetWindowText(hwndRandomize, L"Randomized!"); 63 SetWindowText(hwndRandomize, L"Randomized!");
58 break; 64 break;
59 } 65 }
66 case IDC_READ:
67 _panel = std::make_shared<Panel>(panel);
68 break;
69 case IDC_RANDOM:
70 _panel->Random();
71 break;
72 case IDC_WRITE:
73 _panel->Write(panel);
74 break;
60 } 75 }
61 } 76 }
62 return DefWindowProc(hwnd, message, wParam, lParam); 77 return DefWindowProc(hwnd, message, wParam, lParam);
@@ -99,6 +114,16 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd
99 WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 114 WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
100 160, 10, 100, 26, hwnd, (HMENU)IDC_RANDOMIZE, hInstance, NULL); 115 160, 10, 100, 26, hwnd, (HMENU)IDC_RANDOMIZE, hInstance, NULL);
101 116
117 CreateWindow(L"BUTTON", L"READ",
118 WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
119 160, 100, 100, 26, hwnd, (HMENU)IDC_READ, hInstance, NULL);
120 CreateWindow(L"BUTTON", L"RANDOM",
121 WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
122 160, 130, 100, 26, hwnd, (HMENU)IDC_RANDOM, hInstance, NULL);
123 CreateWindow(L"BUTTON", L"WRITE",
124 WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
125 160, 160, 100, 26, hwnd, (HMENU)IDC_WRITE, hInstance, NULL);
126
102 CreateWindow(L"BUTTON", L"", 127 CreateWindow(L"BUTTON", L"",
103 WS_VISIBLE | WS_CHILD | BS_CHECKBOX, 128 WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
104 10, 52, 12, 12, hwnd, (HMENU)IDC_TOGGLESPEED, hInstance, NULL); 129 10, 52, 12, 12, hwnd, (HMENU)IDC_TOGGLESPEED, hInstance, NULL);
diff --git a/Source/Memory.h b/Source/Memory.h index 53fa1e0..310c971 100644 --- a/Source/Memory.h +++ b/Source/Memory.h
@@ -3,6 +3,9 @@
3#include <map> 3#include <map>
4#include <windows.h> 4#include <windows.h>
5 5
6#define GLOBALS 0x5B28C0
7//#define GLOBALS 0x62A080
8
6// https://github.com/erayarslan/WriteProcessMemory-Example 9// https://github.com/erayarslan/WriteProcessMemory-Example
7// http://stackoverflow.com/q/32798185 10// http://stackoverflow.com/q/32798185
8// http://stackoverflow.com/q/36018838 11// http://stackoverflow.com/q/36018838
@@ -16,6 +19,27 @@ public:
16 Memory(const Memory& memory) = delete; 19 Memory(const Memory& memory) = delete;
17 Memory& operator=(const Memory& other) = delete; 20 Memory& operator=(const Memory& other) = delete;
18 21
22
23 template <class T>
24 std::vector<T> ReadArray(int panel, int offset, int size) {
25 return ReadData<T>({GLOBALS, 0x18, panel*8, offset, 0}, size);
26 }
27
28 template <class T>
29 void WriteArray(int panel, int offset, const std::vector<T>& data) {
30 WriteData<T>({GLOBALS, 0x18, panel*8, offset, 0}, data);
31 }
32
33 template <class T>
34 std::vector<T> ReadPanelData(int panel, int offset, size_t size) {
35 return ReadData<T>({GLOBALS, 0x18, panel*8, offset}, size);
36 }
37
38 template <class T>
39 void WritePanelData(int panel, int offset, const std::vector<T>& data) {
40 WriteData<T>({GLOBALS, 0x18, panel*8, offset}, data);
41 }
42
19 template<class T> 43 template<class T>
20 std::vector<T> ReadData(const std::vector<int>& offsets, size_t numItems) { 44 std::vector<T> ReadData(const std::vector<int>& offsets, size_t numItems) {
21 std::vector<T> data; 45 std::vector<T> data;
@@ -41,6 +65,7 @@ public:
41 } 65 }
42 66
43private: 67private:
68
44 void ThrowError(); 69 void ThrowError();
45 70
46 void* ComputeOffset(std::vector<int> offsets); 71 void* ComputeOffset(std::vector<int> offsets);
diff --git a/Source/Panel.cpp b/Source/Panel.cpp new file mode 100644 index 0000000..0f62664 --- /dev/null +++ b/Source/Panel.cpp
@@ -0,0 +1,134 @@
1#include "Panel.h"
2#include "Random.h"
3
4Decoration::Decoration(int shape) {
5 _shape = shape;
6}
7
8int Decoration::GetValue() {
9 return _shape;
10}
11
12Intersection::Intersection(float x, float y, int flags) {
13 _x = x;
14 _y = y;
15 _flags = flags;
16}
17
18int Intersection::GetValue() {
19 return _flags;
20}
21
22Panel::Panel(int id) {
23 _width = _memory.ReadPanelData<int>(id, GRID_SIZE_X, 1)[0];
24 _height = _memory.ReadPanelData<int>(id, GRID_SIZE_Y, 1)[0];
25
26 ReadIntersections(id);
27 ReadDecorations(id);
28}
29
30void Panel::Write(int id) {
31 WriteIntersections(id);
32 WriteDecorations(id);
33
34 _memory.WritePanelData<int>(id, GRID_SIZE_X, {_width});
35 _memory.WritePanelData<int>(id, GRID_SIZE_Y, {_height});
36}
37
38void Panel::Random() {
39 for (auto& row : _decorations) {
40 for (auto& cell : row) {
41 cell._shape &= 0xFFFFFFF0;
42 cell._shape |= Random::RandInt(1, 10);
43 }
44 }
45}
46
47void Panel::ReadDecorations(int id) {
48 int numDecorations = _memory.ReadPanelData<int>(id, NUM_DECORATIONS, 1)[0];
49 std::vector<int> decorations = _memory.ReadArray<int>(id, DECORATIONS, numDecorations);
50 _decorations.resize(_width - 1);
51 for (int x=0; x<_width-1; x++) {
52 _decorations[x].resize(_height - 1);
53 for (int y=0; y<_height-1; y++) {
54 int i = x * (_height - 1) + y;
55 _decorations[x][y] = Decoration(decorations[i]);
56 }
57 }
58}
59
60void Panel::WriteDecorations(int id) {
61 std::vector<int> flattenedDecorations;
62 for (std::vector<Decoration> row : _decorations) {
63 for (Decoration decoration : row) {
64 flattenedDecorations.push_back(decoration.GetValue());
65 }
66 }
67
68 _memory.WritePanelData<int>(id, NUM_DECORATIONS, {static_cast<int>(flattenedDecorations.size())});
69 _memory.WriteArray<int>(id, DECORATIONS, flattenedDecorations);
70}
71
72void Panel::ReadIntersections(int id) {
73 int numIntersections = _memory.ReadPanelData<int>(id, NUM_DOTS, 1)[0];
74 std::vector<float> intersections = _memory.ReadArray<float>(id, DOT_POSITIONS, numIntersections*2);
75 std::vector<int> intersectionFlags = _memory.ReadArray<int>(id, DOT_FLAGS, numIntersections);
76 _intersections.resize(_width);
77 int i=0;
78 for (int y=0; y<_height; y++) {
79 for (int x=0; x<_width; x++) {
80 _intersections[x].resize(_height);
81 _intersections[x][y] = Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i]);
82 i++;
83 }
84 }
85
86 // Iterate the remaining intersections (either endpoints or gaps)
87 for (; i < numIntersections; i++) {
88 if (intersectionFlags[i] & Intersection::Flags::IS_ENDPOINT) {
89 _endpoints.push_back(Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i]));
90 }
91 if (intersectionFlags[i] & Intersection::Flags::IS_GAP) {
92 _gaps.push_back(Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i]));
93 }
94 }
95}
96
97void Panel::WriteIntersections(int id) {
98 std::vector<float> intersections;
99 std::vector<int> intersectionFlags;
100 std::pair<std::vector<int>, std::vector<int>> connections;
101
102 for (int y=0; y<_height; y++) {
103 for (int x=0; x<_width; x++) {
104 Intersection intersection = _intersections[x][y];
105 intersections.push_back(intersection._x);
106 intersections.push_back(intersection._y);
107 intersectionFlags.push_back(intersection._flags);
108 if (y > 0) {
109 connections.first.push_back(y * _width + x);
110 connections.second.push_back((y - 1) * _width + x);
111 }
112 if (x > 0) {
113 connections.first.push_back(y * _width + x);
114 connections.second.push_back(y * _width + (x - 1));
115 }
116 }
117 }
118
119 // Endpoints go here :(
120
121 int a = _memory.ReadPanelData<int>(id, NUM_DOTS, 1)[0];
122 std::vector<float> b = _memory.ReadArray<float>(id, DOT_POSITIONS, a*2);
123 std::vector<int> c = _memory.ReadArray<int>(id, DOT_FLAGS, a);
124 std::pair<std::vector<int>, std::vector<int>> d;
125 d.first = _memory.ReadArray<int>(id, DOT_CONNECTION_A, a);
126 d.second = _memory.ReadArray<int>(id, DOT_CONNECTION_B, a);
127
128 _memory.WritePanelData<int>(id, NUM_DOTS, {_width * _height});
129 _memory.WriteArray<float>(id, DOT_POSITIONS, intersections);
130 _memory.WriteArray<int>(id, DOT_FLAGS, intersectionFlags);
131 _memory.WriteArray<int>(id, DOT_CONNECTION_A, connections.first);
132 _memory.WriteArray<int>(id, DOT_CONNECTION_B, connections.second);
133}
134
diff --git a/Source/Panel.h b/Source/Panel.h new file mode 100644 index 0000000..fa3f750 --- /dev/null +++ b/Source/Panel.h
@@ -0,0 +1,85 @@
1#pragma once
2#include "json.hpp"
3#include "RandomizerCore.h"
4
5class Decoration
6{
7public:
8 enum Shape {
9 Stone = 100,
10 Star = 200,
11 Poly = 400,
12 Eraser = 500,
13 Triangle = 600,
14 };
15
16 Decoration() = default;
17 explicit Decoration(int shape);
18
19 int GetValue();
20
21//private:
22 int _shape;
23};
24
25class Intersection
26{
27public:
28 enum Flags {
29 IS_ENDPOINT = 0x1,
30 IS_STARTPOINT = 0x2,
31 IS_GAP = 0x10000,
32 HAS_DOT = 0x8,
33 DOT_IS_BLUE = 0x100,
34 DOT_IS_ORANGE = 0x200,
35 DOT_IS_INVISIBLE = 0x1000,
36 };
37
38 Intersection() = default;
39 explicit Intersection(float x, float y, int flags);
40
41 int GetValue();
42
43// private:
44 float _x, _y;
45 int _flags;
46};
47
48class Panel
49{
50public:
51 explicit Panel(int id);
52 void Write(int id);
53
54 void Random();
55
56 enum Style {
57 SYMMETRICAL = 0x2,
58 IS_2COLOR = 0x10,
59 HAS_DOTS = 0x4,
60 HAS_STARS = 0x40,
61 HAS_STONES = 0x100,
62 HAS_ERASERS = 0x1000,
63 HAS_SHAPERS = 0x2000,
64 };
65
66private:
67 void ReadIntersections(int id);
68 void WriteIntersections(int id);
69 void ReadDecorations(int id);
70 void WriteDecorations(int id);
71
72 // TODO: Reflection data
73 // TODO: Decoration colors
74
75
76 Memory _memory = Memory("witness64_d3d11.exe");
77
78 int _width, _height;
79
80 std::vector<std::vector<Decoration>> _decorations;
81 std::vector<std::vector<Intersection>> _intersections;
82 std::vector<Intersection> _endpoints;
83 std::vector<Intersection> _gaps;
84 int _style;
85}; \ No newline at end of file
diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp index 9622601..8833078 100644 --- a/Source/Randomizer.cpp +++ b/Source/Randomizer.cpp
@@ -66,19 +66,19 @@ short Randomizer::Randomize(int seed)
66 66
67void Randomizer::AdjustSpeed() { 67void Randomizer::AdjustSpeed() {
68 // Desert Surface Final Control 68 // Desert Surface Final Control
69 _core.WritePanelData<float>(0x09F95, OPEN_RATE, {0.04f}); // 4x 69 _core._memory.WritePanelData<float>(0x09F95, OPEN_RATE, {0.04f}); // 4x
70 // Swamp Sliding Bridge 70 // Swamp Sliding Bridge
71 _core.WritePanelData<float>(0x0061A, OPEN_RATE, {0.1f}); // 4x 71 _core._memory.WritePanelData<float>(0x0061A, OPEN_RATE, {0.1f}); // 4x
72 // Mountain 2 Elevator 72 // Mountain 2 Elevator
73 _core.WritePanelData<float>(0x09EEC, OPEN_RATE, {0.075f}); // 3x 73 _core._memory.WritePanelData<float>(0x09EEC, OPEN_RATE, {0.075f}); // 3x
74} 74}
75 75
76void Randomizer::RandomizeTutorial() { 76void Randomizer::RandomizeTutorial() {
77 // Disable tutorial cursor speed modifications (not working?) 77 // Disable tutorial cursor speed modifications (not working?)
78 _core.WritePanelData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0}); 78 _core._memory.WritePanelData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0});
79 _core.WritePanelData<float>(0x0C373, CURSOR_SPEED_SCALE, {1.0}); 79 _core._memory.WritePanelData<float>(0x0C373, CURSOR_SPEED_SCALE, {1.0});
80 _core.WritePanelData<float>(0x00293, CURSOR_SPEED_SCALE, {1.0}); 80 _core._memory.WritePanelData<float>(0x00293, CURSOR_SPEED_SCALE, {1.0});
81 _core.WritePanelData<float>(0x002C2, CURSOR_SPEED_SCALE, {1.0}); 81 _core._memory.WritePanelData<float>(0x002C2, CURSOR_SPEED_SCALE, {1.0});
82} 82}
83 83
84void Randomizer::RandomizeSymmetry() { 84void Randomizer::RandomizeSymmetry() {
@@ -88,11 +88,11 @@ void Randomizer::RandomizeDesert() {
88 _core.Randomize(desertPanels, SWAP_LINES); 88 _core.Randomize(desertPanels, SWAP_LINES);
89 89
90 // Turn off desert surface 8 90 // Turn off desert surface 8
91 _core.WritePanelData<float>(0x09F94, POWER, {0.0, 0.0}); 91 _core._memory.WritePanelData<float>(0x09F94, POWER, {0.0, 0.0});
92 // Turn off desert flood final 92 // Turn off desert flood final
93 _core.WritePanelData<float>(0x18076, POWER, {0.0, 0.0}); 93 _core._memory.WritePanelData<float>(0x18076, POWER, {0.0, 0.0});
94 // Change desert floating target to desert flood final 94 // Change desert floating target to desert flood final
95 _core.WritePanelData<int>(0x17ECA, TARGET, {0x18077}); 95 _core._memory.WritePanelData<int>(0x17ECA, TARGET, {0x18077});
96} 96}
97 97
98void Randomizer::RandomizeQuarry() { 98void Randomizer::RandomizeQuarry() {
@@ -100,14 +100,14 @@ void Randomizer::RandomizeQuarry() {
100 100
101void Randomizer::RandomizeTreehouse() { 101void Randomizer::RandomizeTreehouse() {
102 // Ensure that whatever pivot panels we have are flagged as "pivotable" 102 // Ensure that whatever pivot panels we have are flagged as "pivotable"
103 int panelFlags = _core.ReadPanelData<int>(0x17DD1, STYLE_FLAGS, 1)[0]; 103 int panelFlags = _core._memory.ReadPanelData<int>(0x17DD1, STYLE_FLAGS, 1)[0];
104 _core.WritePanelData<int>(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); 104 _core._memory.WritePanelData<int>(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000});
105 panelFlags = _core.ReadPanelData<int>(0x17CE3, STYLE_FLAGS, 1)[0]; 105 panelFlags = _core._memory.ReadPanelData<int>(0x17CE3, STYLE_FLAGS, 1)[0];
106 _core.WritePanelData<int>(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000}); 106 _core._memory.WritePanelData<int>(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000});
107 panelFlags = _core.ReadPanelData<int>(0x17DB7, STYLE_FLAGS, 1)[0]; 107 panelFlags = _core._memory.ReadPanelData<int>(0x17DB7, STYLE_FLAGS, 1)[0];
108 _core.WritePanelData<int>(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000}); 108 _core._memory.WritePanelData<int>(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000});
109 panelFlags = _core.ReadPanelData<int>(0x17E52, STYLE_FLAGS, 1)[0]; 109 panelFlags = _core._memory.ReadPanelData<int>(0x17E52, STYLE_FLAGS, 1)[0];
110 _core.WritePanelData<int>(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000}); 110 _core._memory.WritePanelData<int>(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000});
111} 111}
112 112
113void Randomizer::RandomizeKeep() { 113void Randomizer::RandomizeKeep() {
@@ -115,11 +115,11 @@ void Randomizer::RandomizeKeep() {
115 115
116void Randomizer::RandomizeShadows() { 116void Randomizer::RandomizeShadows() {
117 // Distance-gate shadows laser to prevent sniping through the bars 117 // Distance-gate shadows laser to prevent sniping through the bars
118 _core.WritePanelData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); 118 _core._memory.WritePanelData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5});
119 // Change the shadows tutorial cable to only activate avoid 119 // Change the shadows tutorial cable to only activate avoid
120 _core.WritePanelData<int>(0x319A8, CABLE_TARGET_2, {0}); 120 _core._memory.WritePanelData<int>(0x319A8, CABLE_TARGET_2, {0});
121 // Change shadows avoid 8 to power shadows follow 121 // Change shadows avoid 8 to power shadows follow
122 _core.WritePanelData<int>(0x1972F, TARGET, {0x1C34C}); 122 _core._memory.WritePanelData<int>(0x1972F, TARGET, {0x1C34C});
123 123
124 std::vector<int> randomOrder(shadowsPanels.size(), 0); 124 std::vector<int> randomOrder(shadowsPanels.size(), 0);
125 std::iota(randomOrder.begin(), randomOrder.end(), 0); 125 std::iota(randomOrder.begin(), randomOrder.end(), 0);
@@ -128,9 +128,9 @@ void Randomizer::RandomizeShadows() {
128 _core.RandomizeRange(randomOrder, SWAP_NONE, 16, 21); // Follow 128 _core.RandomizeRange(randomOrder, SWAP_NONE, 16, 21); // Follow
129 _core.ReassignTargets(shadowsPanels, randomOrder); 129 _core.ReassignTargets(shadowsPanels, randomOrder);
130 // Turn off original starting panel 130 // Turn off original starting panel
131 _core.WritePanelData<float>(shadowsPanels[0], POWER, {0.0f, 0.0f}); 131 _core._memory.WritePanelData<float>(shadowsPanels[0], POWER, {0.0f, 0.0f});
132 // Turn on new starting panel 132 // Turn on new starting panel
133 _core.WritePanelData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); 133 _core._memory.WritePanelData<float>(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f});
134} 134}
135 135
136void Randomizer::RandomizeTown() { 136void Randomizer::RandomizeTown() {
@@ -167,7 +167,7 @@ void Randomizer::RandomizeJungle() {
167 167
168void Randomizer::RandomizeSwamp() { 168void Randomizer::RandomizeSwamp() {
169 // Distance-gate swamp snipe 1 to prevent RNG swamp snipe 169 // Distance-gate swamp snipe 1 to prevent RNG swamp snipe
170 _core.WritePanelData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); 170 _core._memory.WritePanelData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0});
171} 171}
172 172
173void Randomizer::RandomizeMountain() { 173void Randomizer::RandomizeMountain() {
@@ -178,7 +178,7 @@ void Randomizer::RandomizeMountain() {
178 // Randomize final pillars order 178 // Randomize final pillars order
179 std::vector<int> targets = {pillars[0] + 1}; 179 std::vector<int> targets = {pillars[0] + 1};
180 for (const int pillar : pillars) { 180 for (const int pillar : pillars) {
181 int target = _core.ReadPanelData<int>(pillar, TARGET, 1)[0]; 181 int target = _core._memory.ReadPanelData<int>(pillar, TARGET, 1)[0];
182 targets.push_back(target); 182 targets.push_back(target);
183 } 183 }
184 targets[5] = pillars[5] + 1; 184 targets[5] = pillars[5] + 1;
@@ -189,27 +189,27 @@ void Randomizer::RandomizeMountain() {
189 _core.RandomizeRange(randomOrder, SWAP_NONE, 5, 9); // Right Pillars 1-4 189 _core.RandomizeRange(randomOrder, SWAP_NONE, 5, 9); // Right Pillars 1-4
190 _core.ReassignTargets(pillars, randomOrder, targets); 190 _core.ReassignTargets(pillars, randomOrder, targets);
191 // Turn off original starting panels 191 // Turn off original starting panels
192 _core.WritePanelData<float>(pillars[0], POWER, {0.0f, 0.0f}); 192 _core._memory.WritePanelData<float>(pillars[0], POWER, {0.0f, 0.0f});
193 _core.WritePanelData<float>(pillars[5], POWER, {0.0f, 0.0f}); 193 _core._memory.WritePanelData<float>(pillars[5], POWER, {0.0f, 0.0f});
194 // Turn on new starting panels 194 // Turn on new starting panels
195 _core.WritePanelData<float>(pillars[randomOrder[0]], POWER, {1.0f, 1.0f}); 195 _core._memory.WritePanelData<float>(pillars[randomOrder[0]], POWER, {1.0f, 1.0f});
196 _core.WritePanelData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f}); 196 _core._memory.WritePanelData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f});
197 197
198 // Read the target of keep front laser, and write it to keep back laser. 198 // Read the target of keep front laser, and write it to keep back laser.
199 std::vector<int> keepFrontLaserTarget = _core.ReadPanelData<int>(0x0360E, TARGET, 1); 199 std::vector<int> keepFrontLaserTarget = _core._memory.ReadPanelData<int>(0x0360E, TARGET, 1);
200 _core.WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget); 200 _core._memory.WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget);
201} 201}
202 202
203void Randomizer::RandomizeChallenge() { 203void Randomizer::RandomizeChallenge() {
204 std::vector<int> randomOrder(challengePanels.size(), 0); 204 std::vector<int> randomOrder(challengePanels.size(), 0);
205 std::iota(randomOrder.begin(), randomOrder.end(), 0); 205 std::iota(randomOrder.begin(), randomOrder.end(), 0);
206 _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 9); // Easy maze - Triple 2 206 _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 9); // Easy maze - Triple 2
207 std::vector<int> triple1Target = _core.ReadPanelData<int>(0x00C80, TARGET, 1); 207 std::vector<int> triple1Target = _core._memory.ReadPanelData<int>(0x00C80, TARGET, 1);
208 _core.WritePanelData<int>(0x00CA1, TARGET, triple1Target); 208 _core._memory.WritePanelData<int>(0x00CA1, TARGET, triple1Target);
209 _core.WritePanelData<int>(0x00CB9, TARGET, triple1Target); 209 _core._memory.WritePanelData<int>(0x00CB9, TARGET, triple1Target);
210 std::vector<int> triple2Target = _core.ReadPanelData<int>(0x00C22, TARGET, 1); 210 std::vector<int> triple2Target = _core._memory.ReadPanelData<int>(0x00C22, TARGET, 1);
211 _core.WritePanelData<int>(0x00C59, TARGET, triple2Target); 211 _core._memory.WritePanelData<int>(0x00C59, TARGET, triple2Target);
212 _core.WritePanelData<int>(0x00C68, TARGET, triple2Target); 212 _core._memory.WritePanelData<int>(0x00C68, TARGET, triple2Target);
213 _core.ReassignTargets(challengePanels, randomOrder); 213 _core.ReassignTargets(challengePanels, randomOrder);
214} 214}
215 215
diff --git a/Source/RandomizerCore.cpp b/Source/RandomizerCore.cpp index f14a76f..d4aadef 100644 --- a/Source/RandomizerCore.cpp +++ b/Source/RandomizerCore.cpp
@@ -101,10 +101,10 @@ void RandomizerCore::SwapPanels(int panel1, int panel2, int flags) {
101 } 101 }
102 102
103 for (auto const& [offset, size] : offsets) { 103 for (auto const& [offset, size] : offsets) {
104 std::vector<byte> panel1data = ReadPanelData<byte>(panel1, offset, size); 104 std::vector<byte> panel1data = _memory.ReadPanelData<byte>(panel1, offset, size);
105 std::vector<byte> panel2data = ReadPanelData<byte>(panel2, offset, size); 105 std::vector<byte> panel2data = _memory.ReadPanelData<byte>(panel2, offset, size);
106 WritePanelData<byte>(panel2, offset, panel1data); 106 _memory.WritePanelData<byte>(panel2, offset, panel1data);
107 WritePanelData<byte>(panel1, offset, panel2data); 107 _memory.WritePanelData<byte>(panel1, offset, panel2data);
108 } 108 }
109} 109}
110 110
@@ -114,7 +114,7 @@ void RandomizerCore::ReassignTargets(const std::vector<int>& panels, const std::
114 // The first panel may not have a wire to power it, so we use the panel ID itself. 114 // The first panel may not have a wire to power it, so we use the panel ID itself.
115 targets = {panels[0] + 1}; 115 targets = {panels[0] + 1};
116 for (const int panel : panels) { 116 for (const int panel : panels) {
117 int target = ReadPanelData<int>(panel, TARGET, 1)[0]; 117 int target = _memory.ReadPanelData<int>(panel, TARGET, 1)[0];
118 targets.push_back(target); 118 targets.push_back(target);
119 } 119 }
120 } 120 }
@@ -122,18 +122,18 @@ void RandomizerCore::ReassignTargets(const std::vector<int>& panels, const std::
122 for (size_t i=0; i<order.size() - 1; i++) { 122 for (size_t i=0; i<order.size() - 1; i++) {
123 // Set the target of order[i] to order[i+1], using the "real" target as determined above. 123 // Set the target of order[i] to order[i+1], using the "real" target as determined above.
124 const int panelTarget = targets[order[i+1]]; 124 const int panelTarget = targets[order[i+1]];
125 WritePanelData<int>(panels[order[i]], TARGET, {panelTarget}); 125 _memory.WritePanelData<int>(panels[order[i]], TARGET, {panelTarget});
126 } 126 }
127} 127}
128 128
129void RandomizerCore::ReassignNames(const std::vector<int>& panels, const std::vector<int>& order) { 129void RandomizerCore::ReassignNames(const std::vector<int>& panels, const std::vector<int>& order) {
130 std::vector<int64_t> names; 130 std::vector<int64_t> names;
131 for (const int panel : panels) { 131 for (const int panel : panels) {
132 names.push_back(ReadPanelData<int64_t>(panel, AUDIO_LOG_NAME, 1)[0]); 132 names.push_back(_memory.ReadPanelData<int64_t>(panel, AUDIO_LOG_NAME, 1)[0]);
133 } 133 }
134 134
135 for (int i=0; i<panels.size(); i++) { 135 for (int i=0; i<panels.size(); i++) {
136 WritePanelData<int64_t>(panels[i], AUDIO_LOG_NAME, {names[order[i]]}); 136 _memory.WritePanelData<int64_t>(panels[i], AUDIO_LOG_NAME, {names[order[i]]});
137 } 137 }
138} 138}
139 139
diff --git a/Source/RandomizerCore.h b/Source/RandomizerCore.h index 7ec8e33..27e5724 100644 --- a/Source/RandomizerCore.h +++ b/Source/RandomizerCore.h
@@ -1,9 +1,6 @@
1#pragma once 1#pragma once
2#include "Memory.h" 2#include "Memory.h"
3 3
4// #define GLOBALS 0x5B28C0
5#define GLOBALS 0x62A080
6
7__declspec(selectany) int SWAP_NONE = 0x0; 4__declspec(selectany) int SWAP_NONE = 0x0;
8__declspec(selectany) int SWAP_TARGETS = 0x1; 5__declspec(selectany) int SWAP_TARGETS = 0x1;
9__declspec(selectany) int SWAP_LINES = 0x2; 6__declspec(selectany) int SWAP_LINES = 0x2;
@@ -20,20 +17,10 @@ public:
20 void ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order, std::vector<int> targets = {}); 17 void ReassignTargets(const std::vector<int>& panels, const std::vector<int>& order, std::vector<int> targets = {});
21 void ReassignNames(const std::vector<int>& panels, const std::vector<int>& order); 18 void ReassignNames(const std::vector<int>& panels, const std::vector<int>& order);
22 19
23 template <class T>
24 std::vector<T> ReadPanelData(int panel, int offset, size_t size) {
25 return _memory.ReadData<T>({GLOBALS, 0x18, panel*8, offset}, size);
26 }
27
28 template <class T>
29 void WritePanelData(int panel, int offset, const std::vector<T>& data) {
30 _memory.WriteData<T>({GLOBALS, 0x18, panel*8, offset}, data);
31 }
32
33 short ReadMetadata(); 20 short ReadMetadata();
34 void WriteMetadata(short metadata); 21 void WriteMetadata(short metadata);
35 22
36private: 23// private:
37 Memory _memory = Memory("witness64_d3d11.exe"); 24 Memory _memory = Memory("witness64_d3d11.exe");
38}; 25};
39 26
diff --git a/Source/Source.vcxproj b/Source/Source.vcxproj index 38914a6..020f69b 100644 --- a/Source/Source.vcxproj +++ b/Source/Source.vcxproj
@@ -163,6 +163,7 @@
163 </ItemDefinitionGroup> 163 </ItemDefinitionGroup>
164 <ItemGroup> 164 <ItemGroup>
165 <ClInclude Include="Memory.h" /> 165 <ClInclude Include="Memory.h" />
166 <ClInclude Include="Panel.h" />
166 <ClInclude Include="Panels.h" /> 167 <ClInclude Include="Panels.h" />
167 <ClInclude Include="Random.h" /> 168 <ClInclude Include="Random.h" />
168 <ClInclude Include="Randomizer.h" /> 169 <ClInclude Include="Randomizer.h" />
@@ -172,6 +173,7 @@
172 <ItemGroup> 173 <ItemGroup>
173 <ClCompile Include="Main.cpp" /> 174 <ClCompile Include="Main.cpp" />
174 <ClCompile Include="Memory.cpp" /> 175 <ClCompile Include="Memory.cpp" />
176 <ClCompile Include="Panel.cpp" />
175 <ClCompile Include="Randomizer.cpp" /> 177 <ClCompile Include="Randomizer.cpp" />
176 <ClCompile Include="RandomizerCore.cpp" /> 178 <ClCompile Include="RandomizerCore.cpp" />
177 </ItemGroup> 179 </ItemGroup>
diff --git a/Source/Source.vcxproj.filters b/Source/Source.vcxproj.filters index 2f8f60b..8f94061 100644 --- a/Source/Source.vcxproj.filters +++ b/Source/Source.vcxproj.filters
@@ -33,6 +33,9 @@
33 <ClInclude Include="Random.h"> 33 <ClInclude Include="Random.h">
34 <Filter>Header Files</Filter> 34 <Filter>Header Files</Filter>
35 </ClInclude> 35 </ClInclude>
36 <ClInclude Include="Panel.h">
37 <Filter>Header Files</Filter>
38 </ClInclude>
36 </ItemGroup> 39 </ItemGroup>
37 <ItemGroup> 40 <ItemGroup>
38 <ClCompile Include="Main.cpp"> 41 <ClCompile Include="Main.cpp">
@@ -47,6 +50,9 @@
47 <ClCompile Include="RandomizerCore.cpp"> 50 <ClCompile Include="RandomizerCore.cpp">
48 <Filter>Source Files</Filter> 51 <Filter>Source Files</Filter>
49 </ClCompile> 52 </ClCompile>
53 <ClCompile Include="Panel.cpp">
54 <Filter>Source Files</Filter>
55 </ClCompile>
50 </ItemGroup> 56 </ItemGroup>
51 <ItemGroup> 57 <ItemGroup>
52 <ResourceCompile Include="Version.rc"> 58 <ResourceCompile Include="Version.rc">
diff --git a/Source/json.hpp b/Source/json.hpp new file mode 100644 index 0000000..1e7cf51 --- /dev/null +++ b/Source/json.hpp
@@ -0,0 +1,20274 @@
1/*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4| | |__ | | | | | | version 3.4.0
5|_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8SPDX-License-Identifier: MIT
9Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
10
11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal
13in the Software without restriction, including without limitation the rights
14to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15copies of the Software, and to permit persons to whom the Software is
16furnished to do so, subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in all
19copies or substantial portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27SOFTWARE.
28*/
29
30#ifndef NLOHMANN_JSON_HPP
31#define NLOHMANN_JSON_HPP
32
33#define NLOHMANN_JSON_VERSION_MAJOR 3
34#define NLOHMANN_JSON_VERSION_MINOR 4
35#define NLOHMANN_JSON_VERSION_PATCH 0
36
37#include <algorithm> // all_of, find, for_each
38#include <cassert> // assert
39#include <ciso646> // and, not, or
40#include <cstddef> // nullptr_t, ptrdiff_t, size_t
41#include <functional> // hash, less
42#include <initializer_list> // initializer_list
43#include <iosfwd> // istream, ostream
44#include <iterator> // iterator_traits, random_access_iterator_tag
45#include <numeric> // accumulate
46#include <string> // string, stoi, to_string
47#include <utility> // declval, forward, move, pair, swap
48
49// #include <nlohmann/json_fwd.hpp>
50#ifndef NLOHMANN_JSON_FWD_HPP
51#define NLOHMANN_JSON_FWD_HPP
52
53#include <cstdint> // int64_t, uint64_t
54#include <map> // map
55#include <memory> // allocator
56#include <string> // string
57#include <vector> // vector
58
59/*!
60@brief namespace for Niels Lohmann
61@see https://github.com/nlohmann
62@since version 1.0.0
63*/
64namespace nlohmann
65{
66/*!
67@brief default JSONSerializer template argument
68
69This serializer ignores the template arguments and uses ADL
70([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
71for serialization.
72*/
73template<typename T = void, typename SFINAE = void>
74struct adl_serializer;
75
76template<template<typename U, typename V, typename... Args> class ObjectType =
77 std::map,
78 template<typename U, typename... Args> class ArrayType = std::vector,
79 class StringType = std::string, class BooleanType = bool,
80 class NumberIntegerType = std::int64_t,
81 class NumberUnsignedType = std::uint64_t,
82 class NumberFloatType = double,
83 template<typename U> class AllocatorType = std::allocator,
84 template<typename T, typename SFINAE = void> class JSONSerializer =
85 adl_serializer>
86class basic_json;
87
88/*!
89@brief JSON Pointer
90
91A JSON pointer defines a string syntax for identifying a specific value
92within a JSON document. It can be used with functions `at` and
93`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
94
95@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
96
97@since version 2.0.0
98*/
99template<typename BasicJsonType>
100class json_pointer;
101
102/*!
103@brief default JSON class
104
105This type is the default specialization of the @ref basic_json class which
106uses the standard template types.
107
108@since version 1.0.0
109*/
110using json = basic_json<>;
111} // namespace nlohmann
112
113#endif
114
115// #include <nlohmann/detail/macro_scope.hpp>
116
117
118// This file contains all internal macro definitions
119// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
120
121// exclude unsupported compilers
122#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
123 #if defined(__clang__)
124 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
125 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
126 #endif
127 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
128 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
129 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
130 #endif
131 #endif
132#endif
133
134// disable float-equal warnings on GCC/clang
135#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
136 #pragma GCC diagnostic push
137 #pragma GCC diagnostic ignored "-Wfloat-equal"
138#endif
139
140// disable documentation warnings on clang
141#if defined(__clang__)
142 #pragma GCC diagnostic push
143 #pragma GCC diagnostic ignored "-Wdocumentation"
144#endif
145
146// allow for portable deprecation warnings
147#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
148 #define JSON_DEPRECATED __attribute__((deprecated))
149#elif defined(_MSC_VER)
150 #define JSON_DEPRECATED __declspec(deprecated)
151#else
152 #define JSON_DEPRECATED
153#endif
154
155// allow to disable exceptions
156#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
157 #define JSON_THROW(exception) throw exception
158 #define JSON_TRY try
159 #define JSON_CATCH(exception) catch(exception)
160 #define JSON_INTERNAL_CATCH(exception) catch(exception)
161#else
162 #define JSON_THROW(exception) std::abort()
163 #define JSON_TRY if(true)
164 #define JSON_CATCH(exception) if(false)
165 #define JSON_INTERNAL_CATCH(exception) if(false)
166#endif
167
168// override exception macros
169#if defined(JSON_THROW_USER)
170 #undef JSON_THROW
171 #define JSON_THROW JSON_THROW_USER
172#endif
173#if defined(JSON_TRY_USER)
174 #undef JSON_TRY
175 #define JSON_TRY JSON_TRY_USER
176#endif
177#if defined(JSON_CATCH_USER)
178 #undef JSON_CATCH
179 #define JSON_CATCH JSON_CATCH_USER
180 #undef JSON_INTERNAL_CATCH
181 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
182#endif
183#if defined(JSON_INTERNAL_CATCH_USER)
184 #undef JSON_INTERNAL_CATCH
185 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
186#endif
187
188// manual branch prediction
189#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
190 #define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
191 #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
192#else
193 #define JSON_LIKELY(x) x
194 #define JSON_UNLIKELY(x) x
195#endif
196
197// C++ language standard detection
198#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
199 #define JSON_HAS_CPP_17
200 #define JSON_HAS_CPP_14
201#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
202 #define JSON_HAS_CPP_14
203#endif
204
205/*!
206@brief macro to briefly define a mapping between an enum and JSON
207@def NLOHMANN_JSON_SERIALIZE_ENUM
208@since version 3.4.0
209*/
210#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
211 template<typename BasicJsonType> \
212 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
213 { \
214 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
215 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
216 auto it = std::find_if(std::begin(m), std::end(m), \
217 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
218 { \
219 return ej_pair.first == e; \
220 }); \
221 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
222 } \
223 template<typename BasicJsonType> \
224 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
225 { \
226 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
227 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
228 auto it = std::find_if(std::begin(m), std::end(m), \
229 [j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
230 { \
231 return ej_pair.second == j; \
232 }); \
233 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
234 }
235
236// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
237// may be removed in the future once the class is split.
238
239#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
240 template<template<typename, typename, typename...> class ObjectType, \
241 template<typename, typename...> class ArrayType, \
242 class StringType, class BooleanType, class NumberIntegerType, \
243 class NumberUnsignedType, class NumberFloatType, \
244 template<typename> class AllocatorType, \
245 template<typename, typename = void> class JSONSerializer>
246
247#define NLOHMANN_BASIC_JSON_TPL \
248 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
249 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
250 AllocatorType, JSONSerializer>
251
252// #include <nlohmann/detail/meta/cpp_future.hpp>
253
254
255#include <ciso646> // not
256#include <cstddef> // size_t
257#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
258
259namespace nlohmann
260{
261namespace detail
262{
263// alias templates to reduce boilerplate
264template<bool B, typename T = void>
265using enable_if_t = typename std::enable_if<B, T>::type;
266
267template<typename T>
268using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
269
270// implementation of C++14 index_sequence and affiliates
271// source: https://stackoverflow.com/a/32223343
272template<std::size_t... Ints>
273struct index_sequence
274{
275 using type = index_sequence;
276 using value_type = std::size_t;
277 static constexpr std::size_t size() noexcept
278 {
279 return sizeof...(Ints);
280 }
281};
282
283template<class Sequence1, class Sequence2>
284struct merge_and_renumber;
285
286template<std::size_t... I1, std::size_t... I2>
287struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
288 : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
289
290template<std::size_t N>
291struct make_index_sequence
292 : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
293 typename make_index_sequence < N - N / 2 >::type > {};
294
295template<> struct make_index_sequence<0> : index_sequence<> {};
296template<> struct make_index_sequence<1> : index_sequence<0> {};
297
298template<typename... Ts>
299using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
300
301// dispatch utility (taken from ranges-v3)
302template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
303template<> struct priority_tag<0> {};
304
305// taken from ranges-v3
306template<typename T>
307struct static_const
308{
309 static constexpr T value{};
310};
311
312template<typename T>
313constexpr T static_const<T>::value;
314} // namespace detail
315} // namespace nlohmann
316
317// #include <nlohmann/detail/meta/type_traits.hpp>
318
319
320#include <ciso646> // not
321#include <limits> // numeric_limits
322#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
323#include <utility> // declval
324
325// #include <nlohmann/json_fwd.hpp>
326
327// #include <nlohmann/detail/meta/cpp_future.hpp>
328
329// #include <nlohmann/detail/meta/detected.hpp>
330
331
332#include <type_traits>
333
334// #include <nlohmann/detail/meta/void_t.hpp>
335
336
337namespace nlohmann
338{
339namespace detail
340{
341template <typename ...Ts> struct make_void
342{
343 using type = void;
344};
345template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
346} // namespace detail
347} // namespace nlohmann
348
349
350// http://en.cppreference.com/w/cpp/experimental/is_detected
351namespace nlohmann
352{
353namespace detail
354{
355struct nonesuch
356{
357 nonesuch() = delete;
358 ~nonesuch() = delete;
359 nonesuch(nonesuch const&) = delete;
360 void operator=(nonesuch const&) = delete;
361};
362
363template <class Default,
364 class AlwaysVoid,
365 template <class...> class Op,
366 class... Args>
367struct detector
368{
369 using value_t = std::false_type;
370 using type = Default;
371};
372
373template <class Default, template <class...> class Op, class... Args>
374struct detector<Default, void_t<Op<Args...>>, Op, Args...>
375{
376 using value_t = std::true_type;
377 using type = Op<Args...>;
378};
379
380template <template <class...> class Op, class... Args>
381using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
382
383template <template <class...> class Op, class... Args>
384using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
385
386template <class Default, template <class...> class Op, class... Args>
387using detected_or = detector<Default, void, Op, Args...>;
388
389template <class Default, template <class...> class Op, class... Args>
390using detected_or_t = typename detected_or<Default, Op, Args...>::type;
391
392template <class Expected, template <class...> class Op, class... Args>
393using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
394
395template <class To, template <class...> class Op, class... Args>
396using is_detected_convertible =
397 std::is_convertible<detected_t<Op, Args...>, To>;
398} // namespace detail
399} // namespace nlohmann
400
401// #include <nlohmann/detail/macro_scope.hpp>
402
403
404namespace nlohmann
405{
406/*!
407@brief detail namespace with internal helper functions
408
409This namespace collects functions that should not be exposed,
410implementations of some @ref basic_json methods, and meta-programming helpers.
411
412@since version 2.1.0
413*/
414namespace detail
415{
416/////////////
417// helpers //
418/////////////
419
420// Note to maintainers:
421//
422// Every trait in this file expects a non CV-qualified type.
423// The only exceptions are in the 'aliases for detected' section
424// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
425//
426// In this case, T has to be properly CV-qualified to constraint the function arguments
427// (e.g. to_json(BasicJsonType&, const T&))
428
429template<typename> struct is_basic_json : std::false_type {};
430
431NLOHMANN_BASIC_JSON_TPL_DECLARATION
432struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
433
434//////////////////////////
435// aliases for detected //
436//////////////////////////
437
438template <typename T>
439using mapped_type_t = typename T::mapped_type;
440
441template <typename T>
442using key_type_t = typename T::key_type;
443
444template <typename T>
445using value_type_t = typename T::value_type;
446
447template <typename T>
448using difference_type_t = typename T::difference_type;
449
450template <typename T>
451using pointer_t = typename T::pointer;
452
453template <typename T>
454using reference_t = typename T::reference;
455
456template <typename T>
457using iterator_category_t = typename T::iterator_category;
458
459template <typename T>
460using iterator_t = typename T::iterator;
461
462template <typename T, typename... Args>
463using to_json_function = decltype(T::to_json(std::declval<Args>()...));
464
465template <typename T, typename... Args>
466using from_json_function = decltype(T::from_json(std::declval<Args>()...));
467
468template <typename T, typename U>
469using get_template_function = decltype(std::declval<T>().template get<U>());
470
471// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
472template <typename BasicJsonType, typename T, typename = void>
473struct has_from_json : std::false_type {};
474
475template <typename BasicJsonType, typename T>
476struct has_from_json<BasicJsonType, T,
477 enable_if_t<not is_basic_json<T>::value>>
478{
479 using serializer = typename BasicJsonType::template json_serializer<T, void>;
480
481 static constexpr bool value =
482 is_detected_exact<void, from_json_function, serializer,
483 const BasicJsonType&, T&>::value;
484};
485
486// This trait checks if JSONSerializer<T>::from_json(json const&) exists
487// this overload is used for non-default-constructible user-defined-types
488template <typename BasicJsonType, typename T, typename = void>
489struct has_non_default_from_json : std::false_type {};
490
491template<typename BasicJsonType, typename T>
492struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
493{
494 using serializer = typename BasicJsonType::template json_serializer<T, void>;
495
496 static constexpr bool value =
497 is_detected_exact<T, from_json_function, serializer,
498 const BasicJsonType&>::value;
499};
500
501// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
502// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
503template <typename BasicJsonType, typename T, typename = void>
504struct has_to_json : std::false_type {};
505
506template <typename BasicJsonType, typename T>
507struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
508{
509 using serializer = typename BasicJsonType::template json_serializer<T, void>;
510
511 static constexpr bool value =
512 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
513 T>::value;
514};
515
516
517///////////////////
518// is_ functions //
519///////////////////
520
521template <typename T, typename = void>
522struct is_iterator_traits : std::false_type {};
523
524template <typename T>
525struct is_iterator_traits<std::iterator_traits<T>>
526{
527 private:
528 using traits = std::iterator_traits<T>;
529
530 public:
531 static constexpr auto value =
532 is_detected<value_type_t, traits>::value &&
533 is_detected<difference_type_t, traits>::value &&
534 is_detected<pointer_t, traits>::value &&
535 is_detected<iterator_category_t, traits>::value &&
536 is_detected<reference_t, traits>::value;
537};
538
539// source: https://stackoverflow.com/a/37193089/4116453
540
541template <typename T, typename = void>
542struct is_complete_type : std::false_type {};
543
544template <typename T>
545struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
546
547template <typename BasicJsonType, typename CompatibleObjectType,
548 typename = void>
549struct is_compatible_object_type_impl : std::false_type {};
550
551template <typename BasicJsonType, typename CompatibleObjectType>
552struct is_compatible_object_type_impl <
553 BasicJsonType, CompatibleObjectType,
554 enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
555 is_detected<key_type_t, CompatibleObjectType>::value >>
556{
557
558 using object_t = typename BasicJsonType::object_t;
559
560 // macOS's is_constructible does not play well with nonesuch...
561 static constexpr bool value =
562 std::is_constructible<typename object_t::key_type,
563 typename CompatibleObjectType::key_type>::value and
564 std::is_constructible<typename object_t::mapped_type,
565 typename CompatibleObjectType::mapped_type>::value;
566};
567
568template <typename BasicJsonType, typename CompatibleObjectType>
569struct is_compatible_object_type
570 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
571
572template <typename BasicJsonType, typename ConstructibleObjectType,
573 typename = void>
574struct is_constructible_object_type_impl : std::false_type {};
575
576template <typename BasicJsonType, typename ConstructibleObjectType>
577struct is_constructible_object_type_impl <
578 BasicJsonType, ConstructibleObjectType,
579 enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value and
580 is_detected<key_type_t, ConstructibleObjectType>::value >>
581{
582 using object_t = typename BasicJsonType::object_t;
583
584 static constexpr bool value =
585 (std::is_constructible<typename ConstructibleObjectType::key_type, typename object_t::key_type>::value and
586 std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value) or
587 (has_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type>::value or
588 has_non_default_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type >::value);
589};
590
591template <typename BasicJsonType, typename ConstructibleObjectType>
592struct is_constructible_object_type
593 : is_constructible_object_type_impl<BasicJsonType,
594 ConstructibleObjectType> {};
595
596template <typename BasicJsonType, typename CompatibleStringType,
597 typename = void>
598struct is_compatible_string_type_impl : std::false_type {};
599
600template <typename BasicJsonType, typename CompatibleStringType>
601struct is_compatible_string_type_impl <
602 BasicJsonType, CompatibleStringType,
603 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
604 value_type_t, CompatibleStringType>::value >>
605{
606 static constexpr auto value =
607 std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
608};
609
610template <typename BasicJsonType, typename ConstructibleStringType>
611struct is_compatible_string_type
612 : is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
613
614template <typename BasicJsonType, typename ConstructibleStringType,
615 typename = void>
616struct is_constructible_string_type_impl : std::false_type {};
617
618template <typename BasicJsonType, typename ConstructibleStringType>
619struct is_constructible_string_type_impl <
620 BasicJsonType, ConstructibleStringType,
621 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
622 value_type_t, ConstructibleStringType>::value >>
623{
624 static constexpr auto value =
625 std::is_constructible<ConstructibleStringType,
626 typename BasicJsonType::string_t>::value;
627};
628
629template <typename BasicJsonType, typename ConstructibleStringType>
630struct is_constructible_string_type
631 : is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
632
633template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
634struct is_compatible_array_type_impl : std::false_type {};
635
636template <typename BasicJsonType, typename CompatibleArrayType>
637struct is_compatible_array_type_impl <
638 BasicJsonType, CompatibleArrayType,
639 enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
640 is_detected<iterator_t, CompatibleArrayType>::value and
641// This is needed because json_reverse_iterator has a ::iterator type...
642// Therefore it is detected as a CompatibleArrayType.
643// The real fix would be to have an Iterable concept.
644 not is_iterator_traits<
645 std::iterator_traits<CompatibleArrayType>>::value >>
646{
647 static constexpr bool value =
648 std::is_constructible<BasicJsonType,
649 typename CompatibleArrayType::value_type>::value;
650};
651
652template <typename BasicJsonType, typename CompatibleArrayType>
653struct is_compatible_array_type
654 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
655
656template <typename BasicJsonType, typename ConstructibleArrayType, typename = void>
657struct is_constructible_array_type_impl : std::false_type {};
658
659template <typename BasicJsonType, typename ConstructibleArrayType>
660struct is_constructible_array_type_impl <
661 BasicJsonType, ConstructibleArrayType,
662 enable_if_t<std::is_same<ConstructibleArrayType,
663 typename BasicJsonType::value_type>::value >>
664 : std::true_type {};
665
666template <typename BasicJsonType, typename ConstructibleArrayType>
667struct is_constructible_array_type_impl <
668 BasicJsonType, ConstructibleArrayType,
669 enable_if_t<not std::is_same<ConstructibleArrayType,
670 typename BasicJsonType::value_type>::value and
671 is_detected<value_type_t, ConstructibleArrayType>::value and
672 is_detected<iterator_t, ConstructibleArrayType>::value and
673 is_complete_type<
674 detected_t<value_type_t, ConstructibleArrayType>>::value >>
675{
676 static constexpr bool value =
677 // This is needed because json_reverse_iterator has a ::iterator type,
678 // furthermore, std::back_insert_iterator (and other iterators) have a base class `iterator`...
679 // Therefore it is detected as a ConstructibleArrayType.
680 // The real fix would be to have an Iterable concept.
681 not is_iterator_traits <
682 std::iterator_traits<ConstructibleArrayType >>::value and
683
684 (std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
685 has_from_json<BasicJsonType,
686 typename ConstructibleArrayType::value_type>::value or
687 has_non_default_from_json <
688 BasicJsonType, typename ConstructibleArrayType::value_type >::value);
689};
690
691template <typename BasicJsonType, typename ConstructibleArrayType>
692struct is_constructible_array_type
693 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
694
695template <typename RealIntegerType, typename CompatibleNumberIntegerType,
696 typename = void>
697struct is_compatible_integer_type_impl : std::false_type {};
698
699template <typename RealIntegerType, typename CompatibleNumberIntegerType>
700struct is_compatible_integer_type_impl <
701 RealIntegerType, CompatibleNumberIntegerType,
702 enable_if_t<std::is_integral<RealIntegerType>::value and
703 std::is_integral<CompatibleNumberIntegerType>::value and
704 not std::is_same<bool, CompatibleNumberIntegerType>::value >>
705{
706 // is there an assert somewhere on overflows?
707 using RealLimits = std::numeric_limits<RealIntegerType>;
708 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
709
710 static constexpr auto value =
711 std::is_constructible<RealIntegerType,
712 CompatibleNumberIntegerType>::value and
713 CompatibleLimits::is_integer and
714 RealLimits::is_signed == CompatibleLimits::is_signed;
715};
716
717template <typename RealIntegerType, typename CompatibleNumberIntegerType>
718struct is_compatible_integer_type
719 : is_compatible_integer_type_impl<RealIntegerType,
720 CompatibleNumberIntegerType> {};
721
722template <typename BasicJsonType, typename CompatibleType, typename = void>
723struct is_compatible_type_impl: std::false_type {};
724
725template <typename BasicJsonType, typename CompatibleType>
726struct is_compatible_type_impl <
727 BasicJsonType, CompatibleType,
728 enable_if_t<is_complete_type<CompatibleType>::value >>
729{
730 static constexpr bool value =
731 has_to_json<BasicJsonType, CompatibleType>::value;
732};
733
734template <typename BasicJsonType, typename CompatibleType>
735struct is_compatible_type
736 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
737} // namespace detail
738} // namespace nlohmann
739
740// #include <nlohmann/detail/exceptions.hpp>
741
742
743#include <exception> // exception
744#include <stdexcept> // runtime_error
745#include <string> // to_string
746
747// #include <nlohmann/detail/input/position_t.hpp>
748
749
750#include <cstddef> // size_t
751
752namespace nlohmann
753{
754namespace detail
755{
756/// struct to capture the start position of the current token
757struct position_t
758{
759 /// the total number of characters read
760 std::size_t chars_read_total = 0;
761 /// the number of characters read in the current line
762 std::size_t chars_read_current_line = 0;
763 /// the number of lines read
764 std::size_t lines_read = 0;
765
766 /// conversion to size_t to preserve SAX interface
767 constexpr operator size_t() const
768 {
769 return chars_read_total;
770 }
771};
772
773}
774}
775
776
777namespace nlohmann
778{
779namespace detail
780{
781////////////////
782// exceptions //
783////////////////
784
785/*!
786@brief general exception of the @ref basic_json class
787
788This class is an extension of `std::exception` objects with a member @a id for
789exception ids. It is used as the base class for all exceptions thrown by the
790@ref basic_json class. This class can hence be used as "wildcard" to catch
791exceptions.
792
793Subclasses:
794- @ref parse_error for exceptions indicating a parse error
795- @ref invalid_iterator for exceptions indicating errors with iterators
796- @ref type_error for exceptions indicating executing a member function with
797 a wrong type
798- @ref out_of_range for exceptions indicating access out of the defined range
799- @ref other_error for exceptions indicating other library errors
800
801@internal
802@note To have nothrow-copy-constructible exceptions, we internally use
803 `std::runtime_error` which can cope with arbitrary-length error messages.
804 Intermediate strings are built with static functions and then passed to
805 the actual constructor.
806@endinternal
807
808@liveexample{The following code shows how arbitrary library exceptions can be
809caught.,exception}
810
811@since version 3.0.0
812*/
813class exception : public std::exception
814{
815 public:
816 /// returns the explanatory string
817 const char* what() const noexcept override
818 {
819 return m.what();
820 }
821
822 /// the id of the exception
823 const int id;
824
825 protected:
826 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
827
828 static std::string name(const std::string& ename, int id_)
829 {
830 return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
831 }
832
833 private:
834 /// an exception object as storage for error messages
835 std::runtime_error m;
836};
837
838/*!
839@brief exception indicating a parse error
840
841This exception is thrown by the library when a parse error occurs. Parse errors
842can occur during the deserialization of JSON text, CBOR, MessagePack, as well
843as when using JSON Patch.
844
845Member @a byte holds the byte index of the last read character in the input
846file.
847
848Exceptions have ids 1xx.
849
850name / id | example message | description
851------------------------------ | --------------- | -------------------------
852json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
853json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
854json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
855json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
856json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
857json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
858json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
859json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
860json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
861json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
862json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
863json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
864json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
865
866@note For an input with n bytes, 1 is the index of the first character and n+1
867 is the index of the terminating null byte or the end of file. This also
868 holds true when reading a byte vector (CBOR or MessagePack).
869
870@liveexample{The following code shows how a `parse_error` exception can be
871caught.,parse_error}
872
873@sa @ref exception for the base class of the library exceptions
874@sa @ref invalid_iterator for exceptions indicating errors with iterators
875@sa @ref type_error for exceptions indicating executing a member function with
876 a wrong type
877@sa @ref out_of_range for exceptions indicating access out of the defined range
878@sa @ref other_error for exceptions indicating other library errors
879
880@since version 3.0.0
881*/
882class parse_error : public exception
883{
884 public:
885 /*!
886 @brief create a parse error exception
887 @param[in] id_ the id of the exception
888 @param[in] position the position where the error occurred (or with
889 chars_read_total=0 if the position cannot be
890 determined)
891 @param[in] what_arg the explanatory string
892 @return parse_error object
893 */
894 static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
895 {
896 std::string w = exception::name("parse_error", id_) + "parse error" +
897 position_string(pos) + ": " + what_arg;
898 return parse_error(id_, pos.chars_read_total, w.c_str());
899 }
900
901 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
902 {
903 std::string w = exception::name("parse_error", id_) + "parse error" +
904 (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
905 ": " + what_arg;
906 return parse_error(id_, byte_, w.c_str());
907 }
908
909 /*!
910 @brief byte index of the parse error
911
912 The byte index of the last read character in the input file.
913
914 @note For an input with n bytes, 1 is the index of the first character and
915 n+1 is the index of the terminating null byte or the end of file.
916 This also holds true when reading a byte vector (CBOR or MessagePack).
917 */
918 const std::size_t byte;
919
920 private:
921 parse_error(int id_, std::size_t byte_, const char* what_arg)
922 : exception(id_, what_arg), byte(byte_) {}
923
924 static std::string position_string(const position_t& pos)
925 {
926 return " at line " + std::to_string(pos.lines_read + 1) +
927 ", column " + std::to_string(pos.chars_read_current_line);
928 }
929};
930
931/*!
932@brief exception indicating errors with iterators
933
934This exception is thrown if iterators passed to a library function do not match
935the expected semantics.
936
937Exceptions have ids 2xx.
938
939name / id | example message | description
940----------------------------------- | --------------- | -------------------------
941json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
942json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
943json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
944json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
945json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
946json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
947json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
948json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
949json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
950json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
951json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
952json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
953json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
954json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
955
956@liveexample{The following code shows how an `invalid_iterator` exception can be
957caught.,invalid_iterator}
958
959@sa @ref exception for the base class of the library exceptions
960@sa @ref parse_error for exceptions indicating a parse error
961@sa @ref type_error for exceptions indicating executing a member function with
962 a wrong type
963@sa @ref out_of_range for exceptions indicating access out of the defined range
964@sa @ref other_error for exceptions indicating other library errors
965
966@since version 3.0.0
967*/
968class invalid_iterator : public exception
969{
970 public:
971 static invalid_iterator create(int id_, const std::string& what_arg)
972 {
973 std::string w = exception::name("invalid_iterator", id_) + what_arg;
974 return invalid_iterator(id_, w.c_str());
975 }
976
977 private:
978 invalid_iterator(int id_, const char* what_arg)
979 : exception(id_, what_arg) {}
980};
981
982/*!
983@brief exception indicating executing a member function with a wrong type
984
985This exception is thrown in case of a type error; that is, a library function is
986executed on a JSON value whose type does not match the expected semantics.
987
988Exceptions have ids 3xx.
989
990name / id | example message | description
991----------------------------- | --------------- | -------------------------
992json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
993json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
994json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
995json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
996json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
997json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
998json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
999json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
1000json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
1001json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
1002json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
1003json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
1004json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
1005json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
1006json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
1007json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
1008json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) |
1009
1010@liveexample{The following code shows how a `type_error` exception can be
1011caught.,type_error}
1012
1013@sa @ref exception for the base class of the library exceptions
1014@sa @ref parse_error for exceptions indicating a parse error
1015@sa @ref invalid_iterator for exceptions indicating errors with iterators
1016@sa @ref out_of_range for exceptions indicating access out of the defined range
1017@sa @ref other_error for exceptions indicating other library errors
1018
1019@since version 3.0.0
1020*/
1021class type_error : public exception
1022{
1023 public:
1024 static type_error create(int id_, const std::string& what_arg)
1025 {
1026 std::string w = exception::name("type_error", id_) + what_arg;
1027 return type_error(id_, w.c_str());
1028 }
1029
1030 private:
1031 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
1032};
1033
1034/*!
1035@brief exception indicating access out of the defined range
1036
1037This exception is thrown in case a library function is called on an input
1038parameter that exceeds the expected range, for instance in case of array
1039indices or nonexisting object keys.
1040
1041Exceptions have ids 4xx.
1042
1043name / id | example message | description
1044------------------------------- | --------------- | -------------------------
1045json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
1046json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
1047json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
1048json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
1049json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
1050json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
1051json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. |
1052json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
1053json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
1054
1055@liveexample{The following code shows how an `out_of_range` exception can be
1056caught.,out_of_range}
1057
1058@sa @ref exception for the base class of the library exceptions
1059@sa @ref parse_error for exceptions indicating a parse error
1060@sa @ref invalid_iterator for exceptions indicating errors with iterators
1061@sa @ref type_error for exceptions indicating executing a member function with
1062 a wrong type
1063@sa @ref other_error for exceptions indicating other library errors
1064
1065@since version 3.0.0
1066*/
1067class out_of_range : public exception
1068{
1069 public:
1070 static out_of_range create(int id_, const std::string& what_arg)
1071 {
1072 std::string w = exception::name("out_of_range", id_) + what_arg;
1073 return out_of_range(id_, w.c_str());
1074 }
1075
1076 private:
1077 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
1078};
1079
1080/*!
1081@brief exception indicating other library errors
1082
1083This exception is thrown in case of errors that cannot be classified with the
1084other exception types.
1085
1086Exceptions have ids 5xx.
1087
1088name / id | example message | description
1089------------------------------ | --------------- | -------------------------
1090json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
1091
1092@sa @ref exception for the base class of the library exceptions
1093@sa @ref parse_error for exceptions indicating a parse error
1094@sa @ref invalid_iterator for exceptions indicating errors with iterators
1095@sa @ref type_error for exceptions indicating executing a member function with
1096 a wrong type
1097@sa @ref out_of_range for exceptions indicating access out of the defined range
1098
1099@liveexample{The following code shows how an `other_error` exception can be
1100caught.,other_error}
1101
1102@since version 3.0.0
1103*/
1104class other_error : public exception
1105{
1106 public:
1107 static other_error create(int id_, const std::string& what_arg)
1108 {
1109 std::string w = exception::name("other_error", id_) + what_arg;
1110 return other_error(id_, w.c_str());
1111 }
1112
1113 private:
1114 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
1115};
1116} // namespace detail
1117} // namespace nlohmann
1118
1119// #include <nlohmann/detail/value_t.hpp>
1120
1121
1122#include <array> // array
1123#include <ciso646> // and
1124#include <cstddef> // size_t
1125#include <cstdint> // uint8_t
1126
1127namespace nlohmann
1128{
1129namespace detail
1130{
1131///////////////////////////
1132// JSON type enumeration //
1133///////////////////////////
1134
1135/*!
1136@brief the JSON type enumeration
1137
1138This enumeration collects the different JSON types. It is internally used to
1139distinguish the stored values, and the functions @ref basic_json::is_null(),
1140@ref basic_json::is_object(), @ref basic_json::is_array(),
1141@ref basic_json::is_string(), @ref basic_json::is_boolean(),
1142@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
1143@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
1144@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
1145@ref basic_json::is_structured() rely on it.
1146
1147@note There are three enumeration entries (number_integer, number_unsigned, and
1148number_float), because the library distinguishes these three types for numbers:
1149@ref basic_json::number_unsigned_t is used for unsigned integers,
1150@ref basic_json::number_integer_t is used for signed integers, and
1151@ref basic_json::number_float_t is used for floating-point numbers or to
1152approximate integers which do not fit in the limits of their respective type.
1153
1154@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
1155value with the default value for a given type
1156
1157@since version 1.0.0
1158*/
1159enum class value_t : std::uint8_t
1160{
1161 null, ///< null value
1162 object, ///< object (unordered set of name/value pairs)
1163 array, ///< array (ordered collection of values)
1164 string, ///< string value
1165 boolean, ///< boolean value
1166 number_integer, ///< number value (signed integer)
1167 number_unsigned, ///< number value (unsigned integer)
1168 number_float, ///< number value (floating-point)
1169 discarded ///< discarded by the the parser callback function
1170};
1171
1172/*!
1173@brief comparison operator for JSON types
1174
1175Returns an ordering that is similar to Python:
1176- order: null < boolean < number < object < array < string
1177- furthermore, each type is not smaller than itself
1178- discarded values are not comparable
1179
1180@since version 1.0.0
1181*/
1182inline bool operator<(const value_t lhs, const value_t rhs) noexcept
1183{
1184 static constexpr std::array<std::uint8_t, 8> order = {{
1185 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
1186 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
1187 }
1188 };
1189
1190 const auto l_index = static_cast<std::size_t>(lhs);
1191 const auto r_index = static_cast<std::size_t>(rhs);
1192 return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
1193}
1194} // namespace detail
1195} // namespace nlohmann
1196
1197// #include <nlohmann/detail/conversions/from_json.hpp>
1198
1199
1200#include <algorithm> // transform
1201#include <array> // array
1202#include <ciso646> // and, not
1203#include <forward_list> // forward_list
1204#include <iterator> // inserter, front_inserter, end
1205#include <map> // map
1206#include <string> // string
1207#include <tuple> // tuple, make_tuple
1208#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
1209#include <unordered_map> // unordered_map
1210#include <utility> // pair, declval
1211#include <valarray> // valarray
1212
1213// #include <nlohmann/detail/exceptions.hpp>
1214
1215// #include <nlohmann/detail/macro_scope.hpp>
1216
1217// #include <nlohmann/detail/meta/cpp_future.hpp>
1218
1219// #include <nlohmann/detail/meta/type_traits.hpp>
1220
1221// #include <nlohmann/detail/value_t.hpp>
1222
1223
1224namespace nlohmann
1225{
1226namespace detail
1227{
1228template<typename BasicJsonType>
1229void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
1230{
1231 if (JSON_UNLIKELY(not j.is_null()))
1232 {
1233 JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
1234 }
1235 n = nullptr;
1236}
1237
1238// overloads for basic_json template parameters
1239template<typename BasicJsonType, typename ArithmeticType,
1240 enable_if_t<std::is_arithmetic<ArithmeticType>::value and
1241 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1242 int> = 0>
1243void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
1244{
1245 switch (static_cast<value_t>(j))
1246 {
1247 case value_t::number_unsigned:
1248 {
1249 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1250 break;
1251 }
1252 case value_t::number_integer:
1253 {
1254 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1255 break;
1256 }
1257 case value_t::number_float:
1258 {
1259 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1260 break;
1261 }
1262
1263 default:
1264 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1265 }
1266}
1267
1268template<typename BasicJsonType>
1269void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
1270{
1271 if (JSON_UNLIKELY(not j.is_boolean()))
1272 {
1273 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
1274 }
1275 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
1276}
1277
1278template<typename BasicJsonType>
1279void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
1280{
1281 if (JSON_UNLIKELY(not j.is_string()))
1282 {
1283 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1284 }
1285 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1286}
1287
1288template <
1289 typename BasicJsonType, typename ConstructibleStringType,
1290 enable_if_t <
1291 is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value and
1292 not std::is_same<typename BasicJsonType::string_t,
1293 ConstructibleStringType>::value,
1294 int > = 0 >
1295void from_json(const BasicJsonType& j, ConstructibleStringType& s)
1296{
1297 if (JSON_UNLIKELY(not j.is_string()))
1298 {
1299 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1300 }
1301
1302 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1303}
1304
1305template<typename BasicJsonType>
1306void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
1307{
1308 get_arithmetic_value(j, val);
1309}
1310
1311template<typename BasicJsonType>
1312void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
1313{
1314 get_arithmetic_value(j, val);
1315}
1316
1317template<typename BasicJsonType>
1318void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
1319{
1320 get_arithmetic_value(j, val);
1321}
1322
1323template<typename BasicJsonType, typename EnumType,
1324 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1325void from_json(const BasicJsonType& j, EnumType& e)
1326{
1327 typename std::underlying_type<EnumType>::type val;
1328 get_arithmetic_value(j, val);
1329 e = static_cast<EnumType>(val);
1330}
1331
1332// forward_list doesn't have an insert method
1333template<typename BasicJsonType, typename T, typename Allocator,
1334 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1335void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
1336{
1337 if (JSON_UNLIKELY(not j.is_array()))
1338 {
1339 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1340 }
1341 std::transform(j.rbegin(), j.rend(),
1342 std::front_inserter(l), [](const BasicJsonType & i)
1343 {
1344 return i.template get<T>();
1345 });
1346}
1347
1348// valarray doesn't have an insert method
1349template<typename BasicJsonType, typename T,
1350 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1351void from_json(const BasicJsonType& j, std::valarray<T>& l)
1352{
1353 if (JSON_UNLIKELY(not j.is_array()))
1354 {
1355 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1356 }
1357 l.resize(j.size());
1358 std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
1359}
1360
1361template<typename BasicJsonType>
1362void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
1363{
1364 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
1365}
1366
1367template <typename BasicJsonType, typename T, std::size_t N>
1368auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
1369 priority_tag<2> /*unused*/)
1370-> decltype(j.template get<T>(), void())
1371{
1372 for (std::size_t i = 0; i < N; ++i)
1373 {
1374 arr[i] = j.at(i).template get<T>();
1375 }
1376}
1377
1378template<typename BasicJsonType, typename ConstructibleArrayType>
1379auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
1380-> decltype(
1381 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
1382 j.template get<typename ConstructibleArrayType::value_type>(),
1383 void())
1384{
1385 using std::end;
1386
1387 arr.reserve(j.size());
1388 std::transform(j.begin(), j.end(),
1389 std::inserter(arr, end(arr)), [](const BasicJsonType & i)
1390 {
1391 // get<BasicJsonType>() returns *this, this won't call a from_json
1392 // method when value_type is BasicJsonType
1393 return i.template get<typename ConstructibleArrayType::value_type>();
1394 });
1395}
1396
1397template <typename BasicJsonType, typename ConstructibleArrayType>
1398void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
1399 priority_tag<0> /*unused*/)
1400{
1401 using std::end;
1402
1403 std::transform(
1404 j.begin(), j.end(), std::inserter(arr, end(arr)),
1405 [](const BasicJsonType & i)
1406 {
1407 // get<BasicJsonType>() returns *this, this won't call a from_json
1408 // method when value_type is BasicJsonType
1409 return i.template get<typename ConstructibleArrayType::value_type>();
1410 });
1411}
1412
1413template <typename BasicJsonType, typename ConstructibleArrayType,
1414 enable_if_t <
1415 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value and
1416 not is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value and
1417 not is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value and
1418 not is_basic_json<ConstructibleArrayType>::value,
1419 int > = 0 >
1420
1421auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
1422-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
1423j.template get<typename ConstructibleArrayType::value_type>(),
1424void())
1425{
1426 if (JSON_UNLIKELY(not j.is_array()))
1427 {
1428 JSON_THROW(type_error::create(302, "type must be array, but is " +
1429 std::string(j.type_name())));
1430 }
1431
1432 from_json_array_impl(j, arr, priority_tag<3> {});
1433}
1434
1435template<typename BasicJsonType, typename ConstructibleObjectType,
1436 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
1437void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
1438{
1439 if (JSON_UNLIKELY(not j.is_object()))
1440 {
1441 JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
1442 }
1443
1444 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1445 using value_type = typename ConstructibleObjectType::value_type;
1446 std::transform(
1447 inner_object->begin(), inner_object->end(),
1448 std::inserter(obj, obj.begin()),
1449 [](typename BasicJsonType::object_t::value_type const & p)
1450 {
1451 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
1452 });
1453}
1454
1455// overload for arithmetic types, not chosen for basic_json template arguments
1456// (BooleanType, etc..); note: Is it really necessary to provide explicit
1457// overloads for boolean_t etc. in case of a custom BooleanType which is not
1458// an arithmetic type?
1459template<typename BasicJsonType, typename ArithmeticType,
1460 enable_if_t <
1461 std::is_arithmetic<ArithmeticType>::value and
1462 not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
1463 not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
1464 not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
1465 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1466 int> = 0>
1467void from_json(const BasicJsonType& j, ArithmeticType& val)
1468{
1469 switch (static_cast<value_t>(j))
1470 {
1471 case value_t::number_unsigned:
1472 {
1473 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1474 break;
1475 }
1476 case value_t::number_integer:
1477 {
1478 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1479 break;
1480 }
1481 case value_t::number_float:
1482 {
1483 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1484 break;
1485 }
1486 case value_t::boolean:
1487 {
1488 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
1489 break;
1490 }
1491
1492 default:
1493 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1494 }
1495}
1496
1497template<typename BasicJsonType, typename A1, typename A2>
1498void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
1499{
1500 p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
1501}
1502
1503template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1504void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)
1505{
1506 t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
1507}
1508
1509template<typename BasicJsonType, typename... Args>
1510void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
1511{
1512 from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1513}
1514
1515template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
1516 typename = enable_if_t<not std::is_constructible<
1517 typename BasicJsonType::string_t, Key>::value>>
1518void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
1519{
1520 if (JSON_UNLIKELY(not j.is_array()))
1521 {
1522 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1523 }
1524 for (const auto& p : j)
1525 {
1526 if (JSON_UNLIKELY(not p.is_array()))
1527 {
1528 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1529 }
1530 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1531 }
1532}
1533
1534template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
1535 typename = enable_if_t<not std::is_constructible<
1536 typename BasicJsonType::string_t, Key>::value>>
1537void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
1538{
1539 if (JSON_UNLIKELY(not j.is_array()))
1540 {
1541 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1542 }
1543 for (const auto& p : j)
1544 {
1545 if (JSON_UNLIKELY(not p.is_array()))
1546 {
1547 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1548 }
1549 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1550 }
1551}
1552
1553struct from_json_fn
1554{
1555 template<typename BasicJsonType, typename T>
1556 auto operator()(const BasicJsonType& j, T& val) const
1557 noexcept(noexcept(from_json(j, val)))
1558 -> decltype(from_json(j, val), void())
1559 {
1560 return from_json(j, val);
1561 }
1562};
1563} // namespace detail
1564
1565/// namespace to hold default `from_json` function
1566/// to see why this is required:
1567/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
1568namespace
1569{
1570constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1571} // namespace
1572} // namespace nlohmann
1573
1574// #include <nlohmann/detail/conversions/to_json.hpp>
1575
1576
1577#include <ciso646> // or, and, not
1578#include <iterator> // begin, end
1579#include <tuple> // tuple, get
1580#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
1581#include <utility> // move, forward, declval, pair
1582#include <valarray> // valarray
1583#include <vector> // vector
1584
1585// #include <nlohmann/detail/meta/cpp_future.hpp>
1586
1587// #include <nlohmann/detail/meta/type_traits.hpp>
1588
1589// #include <nlohmann/detail/value_t.hpp>
1590
1591// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
1592
1593
1594#include <cstddef> // size_t
1595#include <string> // string, to_string
1596#include <iterator> // input_iterator_tag
1597
1598// #include <nlohmann/detail/value_t.hpp>
1599
1600
1601namespace nlohmann
1602{
1603namespace detail
1604{
1605/// proxy class for the items() function
1606template<typename IteratorType> class iteration_proxy
1607{
1608 private:
1609 /// helper class for iteration
1610 class iteration_proxy_internal
1611 {
1612 public:
1613 using difference_type = std::ptrdiff_t;
1614 using value_type = iteration_proxy_internal;
1615 using pointer = iteration_proxy_internal*;
1616 using reference = iteration_proxy_internal&;
1617 using iterator_category = std::input_iterator_tag;
1618
1619 private:
1620 /// the iterator
1621 IteratorType anchor;
1622 /// an index for arrays (used to create key names)
1623 std::size_t array_index = 0;
1624 /// last stringified array index
1625 mutable std::size_t array_index_last = 0;
1626 /// a string representation of the array index
1627 mutable std::string array_index_str = "0";
1628 /// an empty string (to return a reference for primitive values)
1629 const std::string empty_str = "";
1630
1631 public:
1632 explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
1633
1634 /// dereference operator (needed for range-based for)
1635 iteration_proxy_internal& operator*()
1636 {
1637 return *this;
1638 }
1639
1640 /// increment operator (needed for range-based for)
1641 iteration_proxy_internal& operator++()
1642 {
1643 ++anchor;
1644 ++array_index;
1645
1646 return *this;
1647 }
1648
1649 /// equality operator (needed for InputIterator)
1650 bool operator==(const iteration_proxy_internal& o) const noexcept
1651 {
1652 return anchor == o.anchor;
1653 }
1654
1655 /// inequality operator (needed for range-based for)
1656 bool operator!=(const iteration_proxy_internal& o) const noexcept
1657 {
1658 return anchor != o.anchor;
1659 }
1660
1661 /// return key of the iterator
1662 const std::string& key() const
1663 {
1664 assert(anchor.m_object != nullptr);
1665
1666 switch (anchor.m_object->type())
1667 {
1668 // use integer array index as key
1669 case value_t::array:
1670 {
1671 if (array_index != array_index_last)
1672 {
1673 array_index_str = std::to_string(array_index);
1674 array_index_last = array_index;
1675 }
1676 return array_index_str;
1677 }
1678
1679 // use key from the object
1680 case value_t::object:
1681 return anchor.key();
1682
1683 // use an empty key for all primitive types
1684 default:
1685 return empty_str;
1686 }
1687 }
1688
1689 /// return value of the iterator
1690 typename IteratorType::reference value() const
1691 {
1692 return anchor.value();
1693 }
1694 };
1695
1696 /// the container to iterate
1697 typename IteratorType::reference container;
1698
1699 public:
1700 /// construct iteration proxy from a container
1701 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
1702 : container(cont) {}
1703
1704 /// return iterator begin (needed for range-based for)
1705 iteration_proxy_internal begin() noexcept
1706 {
1707 return iteration_proxy_internal(container.begin());
1708 }
1709
1710 /// return iterator end (needed for range-based for)
1711 iteration_proxy_internal end() noexcept
1712 {
1713 return iteration_proxy_internal(container.end());
1714 }
1715};
1716} // namespace detail
1717} // namespace nlohmann
1718
1719
1720namespace nlohmann
1721{
1722namespace detail
1723{
1724//////////////////
1725// constructors //
1726//////////////////
1727
1728template<value_t> struct external_constructor;
1729
1730template<>
1731struct external_constructor<value_t::boolean>
1732{
1733 template<typename BasicJsonType>
1734 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
1735 {
1736 j.m_type = value_t::boolean;
1737 j.m_value = b;
1738 j.assert_invariant();
1739 }
1740};
1741
1742template<>
1743struct external_constructor<value_t::string>
1744{
1745 template<typename BasicJsonType>
1746 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
1747 {
1748 j.m_type = value_t::string;
1749 j.m_value = s;
1750 j.assert_invariant();
1751 }
1752
1753 template<typename BasicJsonType>
1754 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1755 {
1756 j.m_type = value_t::string;
1757 j.m_value = std::move(s);
1758 j.assert_invariant();
1759 }
1760
1761 template<typename BasicJsonType, typename CompatibleStringType,
1762 enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
1763 int> = 0>
1764 static void construct(BasicJsonType& j, const CompatibleStringType& str)
1765 {
1766 j.m_type = value_t::string;
1767 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1768 j.assert_invariant();
1769 }
1770};
1771
1772template<>
1773struct external_constructor<value_t::number_float>
1774{
1775 template<typename BasicJsonType>
1776 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
1777 {
1778 j.m_type = value_t::number_float;
1779 j.m_value = val;
1780 j.assert_invariant();
1781 }
1782};
1783
1784template<>
1785struct external_constructor<value_t::number_unsigned>
1786{
1787 template<typename BasicJsonType>
1788 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
1789 {
1790 j.m_type = value_t::number_unsigned;
1791 j.m_value = val;
1792 j.assert_invariant();
1793 }
1794};
1795
1796template<>
1797struct external_constructor<value_t::number_integer>
1798{
1799 template<typename BasicJsonType>
1800 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
1801 {
1802 j.m_type = value_t::number_integer;
1803 j.m_value = val;
1804 j.assert_invariant();
1805 }
1806};
1807
1808template<>
1809struct external_constructor<value_t::array>
1810{
1811 template<typename BasicJsonType>
1812 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
1813 {
1814 j.m_type = value_t::array;
1815 j.m_value = arr;
1816 j.assert_invariant();
1817 }
1818
1819 template<typename BasicJsonType>
1820 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1821 {
1822 j.m_type = value_t::array;
1823 j.m_value = std::move(arr);
1824 j.assert_invariant();
1825 }
1826
1827 template<typename BasicJsonType, typename CompatibleArrayType,
1828 enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
1829 int> = 0>
1830 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
1831 {
1832 using std::begin;
1833 using std::end;
1834 j.m_type = value_t::array;
1835 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1836 j.assert_invariant();
1837 }
1838
1839 template<typename BasicJsonType>
1840 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
1841 {
1842 j.m_type = value_t::array;
1843 j.m_value = value_t::array;
1844 j.m_value.array->reserve(arr.size());
1845 for (const bool x : arr)
1846 {
1847 j.m_value.array->push_back(x);
1848 }
1849 j.assert_invariant();
1850 }
1851
1852 template<typename BasicJsonType, typename T,
1853 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1854 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
1855 {
1856 j.m_type = value_t::array;
1857 j.m_value = value_t::array;
1858 j.m_value.array->resize(arr.size());
1859 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
1860 j.assert_invariant();
1861 }
1862};
1863
1864template<>
1865struct external_constructor<value_t::object>
1866{
1867 template<typename BasicJsonType>
1868 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
1869 {
1870 j.m_type = value_t::object;
1871 j.m_value = obj;
1872 j.assert_invariant();
1873 }
1874
1875 template<typename BasicJsonType>
1876 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1877 {
1878 j.m_type = value_t::object;
1879 j.m_value = std::move(obj);
1880 j.assert_invariant();
1881 }
1882
1883 template<typename BasicJsonType, typename CompatibleObjectType,
1884 enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
1885 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
1886 {
1887 using std::begin;
1888 using std::end;
1889
1890 j.m_type = value_t::object;
1891 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
1892 j.assert_invariant();
1893 }
1894};
1895
1896/////////////
1897// to_json //
1898/////////////
1899
1900template<typename BasicJsonType, typename T,
1901 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
1902void to_json(BasicJsonType& j, T b) noexcept
1903{
1904 external_constructor<value_t::boolean>::construct(j, b);
1905}
1906
1907template<typename BasicJsonType, typename CompatibleString,
1908 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
1909void to_json(BasicJsonType& j, const CompatibleString& s)
1910{
1911 external_constructor<value_t::string>::construct(j, s);
1912}
1913
1914template<typename BasicJsonType>
1915void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1916{
1917 external_constructor<value_t::string>::construct(j, std::move(s));
1918}
1919
1920template<typename BasicJsonType, typename FloatType,
1921 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
1922void to_json(BasicJsonType& j, FloatType val) noexcept
1923{
1924 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
1925}
1926
1927template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
1928 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
1929void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
1930{
1931 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
1932}
1933
1934template<typename BasicJsonType, typename CompatibleNumberIntegerType,
1935 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
1936void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
1937{
1938 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
1939}
1940
1941template<typename BasicJsonType, typename EnumType,
1942 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1943void to_json(BasicJsonType& j, EnumType e) noexcept
1944{
1945 using underlying_type = typename std::underlying_type<EnumType>::type;
1946 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
1947}
1948
1949template<typename BasicJsonType>
1950void to_json(BasicJsonType& j, const std::vector<bool>& e)
1951{
1952 external_constructor<value_t::array>::construct(j, e);
1953}
1954
1955template <typename BasicJsonType, typename CompatibleArrayType,
1956 enable_if_t<is_compatible_array_type<BasicJsonType,
1957 CompatibleArrayType>::value and
1958 not is_compatible_object_type<
1959 BasicJsonType, CompatibleArrayType>::value and
1960 not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
1961 not is_basic_json<CompatibleArrayType>::value,
1962 int> = 0>
1963void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
1964{
1965 external_constructor<value_t::array>::construct(j, arr);
1966}
1967
1968template<typename BasicJsonType, typename T,
1969 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1970void to_json(BasicJsonType& j, const std::valarray<T>& arr)
1971{
1972 external_constructor<value_t::array>::construct(j, std::move(arr));
1973}
1974
1975template<typename BasicJsonType>
1976void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1977{
1978 external_constructor<value_t::array>::construct(j, std::move(arr));
1979}
1980
1981template<typename BasicJsonType, typename CompatibleObjectType,
1982 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
1983void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
1984{
1985 external_constructor<value_t::object>::construct(j, obj);
1986}
1987
1988template<typename BasicJsonType>
1989void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1990{
1991 external_constructor<value_t::object>::construct(j, std::move(obj));
1992}
1993
1994template <
1995 typename BasicJsonType, typename T, std::size_t N,
1996 enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
1997 const T (&)[N]>::value,
1998 int> = 0 >
1999void to_json(BasicJsonType& j, const T (&arr)[N])
2000{
2001 external_constructor<value_t::array>::construct(j, arr);
2002}
2003
2004template<typename BasicJsonType, typename... Args>
2005void to_json(BasicJsonType& j, const std::pair<Args...>& p)
2006{
2007 j = {p.first, p.second};
2008}
2009
2010// for https://github.com/nlohmann/json/pull/1134
2011template<typename BasicJsonType, typename T,
2012 enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
2013void to_json(BasicJsonType& j, const T& b)
2014{
2015 j = {{b.key(), b.value()}};
2016}
2017
2018template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
2019void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
2020{
2021 j = {std::get<Idx>(t)...};
2022}
2023
2024template<typename BasicJsonType, typename... Args>
2025void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
2026{
2027 to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
2028}
2029
2030struct to_json_fn
2031{
2032 template<typename BasicJsonType, typename T>
2033 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
2034 -> decltype(to_json(j, std::forward<T>(val)), void())
2035 {
2036 return to_json(j, std::forward<T>(val));
2037 }
2038};
2039} // namespace detail
2040
2041/// namespace to hold default `to_json` function
2042namespace
2043{
2044constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
2045} // namespace
2046} // namespace nlohmann
2047
2048// #include <nlohmann/detail/input/input_adapters.hpp>
2049
2050
2051#include <cassert> // assert
2052#include <cstddef> // size_t
2053#include <cstring> // strlen
2054#include <istream> // istream
2055#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
2056#include <memory> // shared_ptr, make_shared, addressof
2057#include <numeric> // accumulate
2058#include <string> // string, char_traits
2059#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
2060#include <utility> // pair, declval
2061
2062// #include <nlohmann/detail/macro_scope.hpp>
2063
2064
2065namespace nlohmann
2066{
2067namespace detail
2068{
2069/// the supported input formats
2070enum class input_format_t { json, cbor, msgpack, ubjson, bson };
2071
2072////////////////////
2073// input adapters //
2074////////////////////
2075
2076/*!
2077@brief abstract input adapter interface
2078
2079Produces a stream of std::char_traits<char>::int_type characters from a
2080std::istream, a buffer, or some other input type. Accepts the return of
2081exactly one non-EOF character for future input. The int_type characters
2082returned consist of all valid char values as positive values (typically
2083unsigned char), plus an EOF value outside that range, specified by the value
2084of the function std::char_traits<char>::eof(). This value is typically -1, but
2085could be any arbitrary value which is not a valid char value.
2086*/
2087struct input_adapter_protocol
2088{
2089 /// get a character [0,255] or std::char_traits<char>::eof().
2090 virtual std::char_traits<char>::int_type get_character() = 0;
2091 virtual ~input_adapter_protocol() = default;
2092};
2093
2094/// a type to simplify interfaces
2095using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
2096
2097/*!
2098Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
2099beginning of input. Does not support changing the underlying std::streambuf
2100in mid-input. Maintains underlying std::istream and std::streambuf to support
2101subsequent use of standard std::istream operations to process any input
2102characters following those used in parsing the JSON input. Clears the
2103std::istream flags; any input errors (e.g., EOF) will be detected by the first
2104subsequent call for input from the std::istream.
2105*/
2106class input_stream_adapter : public input_adapter_protocol
2107{
2108 public:
2109 ~input_stream_adapter() override
2110 {
2111 // clear stream flags; we use underlying streambuf I/O, do not
2112 // maintain ifstream flags
2113 is.clear();
2114 }
2115
2116 explicit input_stream_adapter(std::istream& i)
2117 : is(i), sb(*i.rdbuf())
2118 {}
2119
2120 // delete because of pointer members
2121 input_stream_adapter(const input_stream_adapter&) = delete;
2122 input_stream_adapter& operator=(input_stream_adapter&) = delete;
2123 input_stream_adapter(input_stream_adapter&&) = delete;
2124 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
2125
2126 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
2127 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
2128 // end up as the same value, eg. 0xFFFFFFFF.
2129 std::char_traits<char>::int_type get_character() override
2130 {
2131 return sb.sbumpc();
2132 }
2133
2134 private:
2135 /// the associated input stream
2136 std::istream& is;
2137 std::streambuf& sb;
2138};
2139
2140/// input adapter for buffer input
2141class input_buffer_adapter : public input_adapter_protocol
2142{
2143 public:
2144 input_buffer_adapter(const char* b, const std::size_t l) noexcept
2145 : cursor(b), limit(b + l)
2146 {}
2147
2148 // delete because of pointer members
2149 input_buffer_adapter(const input_buffer_adapter&) = delete;
2150 input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
2151 input_buffer_adapter(input_buffer_adapter&&) = delete;
2152 input_buffer_adapter& operator=(input_buffer_adapter&&) = delete;
2153 ~input_buffer_adapter() override = default;
2154
2155 std::char_traits<char>::int_type get_character() noexcept override
2156 {
2157 if (JSON_LIKELY(cursor < limit))
2158 {
2159 return std::char_traits<char>::to_int_type(*(cursor++));
2160 }
2161
2162 return std::char_traits<char>::eof();
2163 }
2164
2165 private:
2166 /// pointer to the current character
2167 const char* cursor;
2168 /// pointer past the last character
2169 const char* const limit;
2170};
2171
2172template<typename WideStringType, size_t T>
2173struct wide_string_input_helper
2174{
2175 // UTF-32
2176 static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
2177 {
2178 utf8_bytes_index = 0;
2179
2180 if (current_wchar == str.size())
2181 {
2182 utf8_bytes[0] = std::char_traits<char>::eof();
2183 utf8_bytes_filled = 1;
2184 }
2185 else
2186 {
2187 // get the current character
2188 const auto wc = static_cast<int>(str[current_wchar++]);
2189
2190 // UTF-32 to UTF-8 encoding
2191 if (wc < 0x80)
2192 {
2193 utf8_bytes[0] = wc;
2194 utf8_bytes_filled = 1;
2195 }
2196 else if (wc <= 0x7FF)
2197 {
2198 utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
2199 utf8_bytes[1] = 0x80 | (wc & 0x3F);
2200 utf8_bytes_filled = 2;
2201 }
2202 else if (wc <= 0xFFFF)
2203 {
2204 utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
2205 utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
2206 utf8_bytes[2] = 0x80 | (wc & 0x3F);
2207 utf8_bytes_filled = 3;
2208 }
2209 else if (wc <= 0x10FFFF)
2210 {
2211 utf8_bytes[0] = 0xF0 | ((wc >> 18) & 0x07);
2212 utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
2213 utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
2214 utf8_bytes[3] = 0x80 | (wc & 0x3F);
2215 utf8_bytes_filled = 4;
2216 }
2217 else
2218 {
2219 // unknown character
2220 utf8_bytes[0] = wc;
2221 utf8_bytes_filled = 1;
2222 }
2223 }
2224 }
2225};
2226
2227template<typename WideStringType>
2228struct wide_string_input_helper<WideStringType, 2>
2229{
2230 // UTF-16
2231 static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
2232 {
2233 utf8_bytes_index = 0;
2234
2235 if (current_wchar == str.size())
2236 {
2237 utf8_bytes[0] = std::char_traits<char>::eof();
2238 utf8_bytes_filled = 1;
2239 }
2240 else
2241 {
2242 // get the current character
2243 const auto wc = static_cast<int>(str[current_wchar++]);
2244
2245 // UTF-16 to UTF-8 encoding
2246 if (wc < 0x80)
2247 {
2248 utf8_bytes[0] = wc;
2249 utf8_bytes_filled = 1;
2250 }
2251 else if (wc <= 0x7FF)
2252 {
2253 utf8_bytes[0] = 0xC0 | ((wc >> 6));
2254 utf8_bytes[1] = 0x80 | (wc & 0x3F);
2255 utf8_bytes_filled = 2;
2256 }
2257 else if (0xD800 > wc or wc >= 0xE000)
2258 {
2259 utf8_bytes[0] = 0xE0 | ((wc >> 12));
2260 utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
2261 utf8_bytes[2] = 0x80 | (wc & 0x3F);
2262 utf8_bytes_filled = 3;
2263 }
2264 else
2265 {
2266 if (current_wchar < str.size())
2267 {
2268 const auto wc2 = static_cast<int>(str[current_wchar++]);
2269 const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
2270 utf8_bytes[0] = 0xf0 | (charcode >> 18);
2271 utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
2272 utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
2273 utf8_bytes[3] = 0x80 | (charcode & 0x3F);
2274 utf8_bytes_filled = 4;
2275 }
2276 else
2277 {
2278 // unknown character
2279 ++current_wchar;
2280 utf8_bytes[0] = wc;
2281 utf8_bytes_filled = 1;
2282 }
2283 }
2284 }
2285 }
2286};
2287
2288template<typename WideStringType>
2289class wide_string_input_adapter : public input_adapter_protocol
2290{
2291 public:
2292 explicit wide_string_input_adapter(const WideStringType& w) noexcept
2293 : str(w)
2294 {}
2295
2296 std::char_traits<char>::int_type get_character() noexcept override
2297 {
2298 // check if buffer needs to be filled
2299 if (utf8_bytes_index == utf8_bytes_filled)
2300 {
2301 fill_buffer<sizeof(typename WideStringType::value_type)>();
2302
2303 assert(utf8_bytes_filled > 0);
2304 assert(utf8_bytes_index == 0);
2305 }
2306
2307 // use buffer
2308 assert(utf8_bytes_filled > 0);
2309 assert(utf8_bytes_index < utf8_bytes_filled);
2310 return utf8_bytes[utf8_bytes_index++];
2311 }
2312
2313 private:
2314 template<size_t T>
2315 void fill_buffer()
2316 {
2317 wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
2318 }
2319
2320 /// the wstring to process
2321 const WideStringType& str;
2322
2323 /// index of the current wchar in str
2324 std::size_t current_wchar = 0;
2325
2326 /// a buffer for UTF-8 bytes
2327 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
2328
2329 /// index to the utf8_codes array for the next valid byte
2330 std::size_t utf8_bytes_index = 0;
2331 /// number of valid bytes in the utf8_codes array
2332 std::size_t utf8_bytes_filled = 0;
2333};
2334
2335class input_adapter
2336{
2337 public:
2338 // native support
2339
2340 /// input adapter for input stream
2341 input_adapter(std::istream& i)
2342 : ia(std::make_shared<input_stream_adapter>(i)) {}
2343
2344 /// input adapter for input stream
2345 input_adapter(std::istream&& i)
2346 : ia(std::make_shared<input_stream_adapter>(i)) {}
2347
2348 input_adapter(const std::wstring& ws)
2349 : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
2350
2351 input_adapter(const std::u16string& ws)
2352 : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
2353
2354 input_adapter(const std::u32string& ws)
2355 : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
2356
2357 /// input adapter for buffer
2358 template<typename CharT,
2359 typename std::enable_if<
2360 std::is_pointer<CharT>::value and
2361 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2362 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2363 int>::type = 0>
2364 input_adapter(CharT b, std::size_t l)
2365 : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
2366
2367 // derived support
2368
2369 /// input adapter for string literal
2370 template<typename CharT,
2371 typename std::enable_if<
2372 std::is_pointer<CharT>::value and
2373 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2374 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2375 int>::type = 0>
2376 input_adapter(CharT b)
2377 : input_adapter(reinterpret_cast<const char*>(b),
2378 std::strlen(reinterpret_cast<const char*>(b))) {}
2379
2380 /// input adapter for iterator range with contiguous storage
2381 template<class IteratorType,
2382 typename std::enable_if<
2383 std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
2384 int>::type = 0>
2385 input_adapter(IteratorType first, IteratorType last)
2386 {
2387#ifndef NDEBUG
2388 // assertion to check that the iterator range is indeed contiguous,
2389 // see http://stackoverflow.com/a/35008842/266378 for more discussion
2390 const auto is_contiguous = std::accumulate(
2391 first, last, std::pair<bool, int>(true, 0),
2392 [&first](std::pair<bool, int> res, decltype(*first) val)
2393 {
2394 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2395 return res;
2396 }).first;
2397 assert(is_contiguous);
2398#endif
2399
2400 // assertion to check that each element is 1 byte long
2401 static_assert(
2402 sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
2403 "each element in the iterator range must have the size of 1 byte");
2404
2405 const auto len = static_cast<size_t>(std::distance(first, last));
2406 if (JSON_LIKELY(len > 0))
2407 {
2408 // there is at least one element: use the address of first
2409 ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2410 }
2411 else
2412 {
2413 // the address of first cannot be used: use nullptr
2414 ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2415 }
2416 }
2417
2418 /// input adapter for array
2419 template<class T, std::size_t N>
2420 input_adapter(T (&array)[N])
2421 : input_adapter(std::begin(array), std::end(array)) {}
2422
2423 /// input adapter for contiguous container
2424 template<class ContiguousContainer, typename
2425 std::enable_if<not std::is_pointer<ContiguousContainer>::value and
2426 std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
2427 int>::type = 0>
2428 input_adapter(const ContiguousContainer& c)
2429 : input_adapter(std::begin(c), std::end(c)) {}
2430
2431 operator input_adapter_t()
2432 {
2433 return ia;
2434 }
2435
2436 private:
2437 /// the actual adapter
2438 input_adapter_t ia = nullptr;
2439};
2440} // namespace detail
2441} // namespace nlohmann
2442
2443// #include <nlohmann/detail/input/lexer.hpp>
2444
2445
2446#include <clocale> // localeconv
2447#include <cstddef> // size_t
2448#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
2449#include <cstdio> // snprintf
2450#include <initializer_list> // initializer_list
2451#include <string> // char_traits, string
2452#include <vector> // vector
2453
2454// #include <nlohmann/detail/macro_scope.hpp>
2455
2456// #include <nlohmann/detail/input/input_adapters.hpp>
2457
2458// #include <nlohmann/detail/input/position_t.hpp>
2459
2460
2461namespace nlohmann
2462{
2463namespace detail
2464{
2465///////////
2466// lexer //
2467///////////
2468
2469/*!
2470@brief lexical analysis
2471
2472This class organizes the lexical analysis during JSON deserialization.
2473*/
2474template<typename BasicJsonType>
2475class lexer
2476{
2477 using number_integer_t = typename BasicJsonType::number_integer_t;
2478 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
2479 using number_float_t = typename BasicJsonType::number_float_t;
2480 using string_t = typename BasicJsonType::string_t;
2481
2482 public:
2483 /// token types for the parser
2484 enum class token_type
2485 {
2486 uninitialized, ///< indicating the scanner is uninitialized
2487 literal_true, ///< the `true` literal
2488 literal_false, ///< the `false` literal
2489 literal_null, ///< the `null` literal
2490 value_string, ///< a string -- use get_string() for actual value
2491 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
2492 value_integer, ///< a signed integer -- use get_number_integer() for actual value
2493 value_float, ///< an floating point number -- use get_number_float() for actual value
2494 begin_array, ///< the character for array begin `[`
2495 begin_object, ///< the character for object begin `{`
2496 end_array, ///< the character for array end `]`
2497 end_object, ///< the character for object end `}`
2498 name_separator, ///< the name separator `:`
2499 value_separator, ///< the value separator `,`
2500 parse_error, ///< indicating a parse error
2501 end_of_input, ///< indicating the end of the input buffer
2502 literal_or_value ///< a literal or the begin of a value (only for diagnostics)
2503 };
2504
2505 /// return name of values of type token_type (only used for errors)
2506 static const char* token_type_name(const token_type t) noexcept
2507 {
2508 switch (t)
2509 {
2510 case token_type::uninitialized:
2511 return "<uninitialized>";
2512 case token_type::literal_true:
2513 return "true literal";
2514 case token_type::literal_false:
2515 return "false literal";
2516 case token_type::literal_null:
2517 return "null literal";
2518 case token_type::value_string:
2519 return "string literal";
2520 case lexer::token_type::value_unsigned:
2521 case lexer::token_type::value_integer:
2522 case lexer::token_type::value_float:
2523 return "number literal";
2524 case token_type::begin_array:
2525 return "'['";
2526 case token_type::begin_object:
2527 return "'{'";
2528 case token_type::end_array:
2529 return "']'";
2530 case token_type::end_object:
2531 return "'}'";
2532 case token_type::name_separator:
2533 return "':'";
2534 case token_type::value_separator:
2535 return "','";
2536 case token_type::parse_error:
2537 return "<parse error>";
2538 case token_type::end_of_input:
2539 return "end of input";
2540 case token_type::literal_or_value:
2541 return "'[', '{', or a literal";
2542 // LCOV_EXCL_START
2543 default: // catch non-enum values
2544 return "unknown token";
2545 // LCOV_EXCL_STOP
2546 }
2547 }
2548
2549 explicit lexer(detail::input_adapter_t&& adapter)
2550 : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
2551
2552 // delete because of pointer members
2553 lexer(const lexer&) = delete;
2554 lexer(lexer&&) = delete;
2555 lexer& operator=(lexer&) = delete;
2556 lexer& operator=(lexer&&) = delete;
2557 ~lexer() = default;
2558
2559 private:
2560 /////////////////////
2561 // locales
2562 /////////////////////
2563
2564 /// return the locale-dependent decimal point
2565 static char get_decimal_point() noexcept
2566 {
2567 const auto loc = localeconv();
2568 assert(loc != nullptr);
2569 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
2570 }
2571
2572 /////////////////////
2573 // scan functions
2574 /////////////////////
2575
2576 /*!
2577 @brief get codepoint from 4 hex characters following `\u`
2578
2579 For input "\u c1 c2 c3 c4" the codepoint is:
2580 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
2581 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
2582
2583 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
2584 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
2585 conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
2586 between the ASCII value of the character and the desired integer value.
2587
2588 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
2589 non-hex character)
2590 */
2591 int get_codepoint()
2592 {
2593 // this function only makes sense after reading `\u`
2594 assert(current == 'u');
2595 int codepoint = 0;
2596
2597 const auto factors = { 12, 8, 4, 0 };
2598 for (const auto factor : factors)
2599 {
2600 get();
2601
2602 if (current >= '0' and current <= '9')
2603 {
2604 codepoint += ((current - 0x30) << factor);
2605 }
2606 else if (current >= 'A' and current <= 'F')
2607 {
2608 codepoint += ((current - 0x37) << factor);
2609 }
2610 else if (current >= 'a' and current <= 'f')
2611 {
2612 codepoint += ((current - 0x57) << factor);
2613 }
2614 else
2615 {
2616 return -1;
2617 }
2618 }
2619
2620 assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
2621 return codepoint;
2622 }
2623
2624 /*!
2625 @brief check if the next byte(s) are inside a given range
2626
2627 Adds the current byte and, for each passed range, reads a new byte and
2628 checks if it is inside the range. If a violation was detected, set up an
2629 error message and return false. Otherwise, return true.
2630
2631 @param[in] ranges list of integers; interpreted as list of pairs of
2632 inclusive lower and upper bound, respectively
2633
2634 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
2635 1, 2, or 3 pairs. This precondition is enforced by an assertion.
2636
2637 @return true if and only if no range violation was detected
2638 */
2639 bool next_byte_in_range(std::initializer_list<int> ranges)
2640 {
2641 assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
2642 add(current);
2643
2644 for (auto range = ranges.begin(); range != ranges.end(); ++range)
2645 {
2646 get();
2647 if (JSON_LIKELY(*range <= current and current <= *(++range)))
2648 {
2649 add(current);
2650 }
2651 else
2652 {
2653 error_message = "invalid string: ill-formed UTF-8 byte";
2654 return false;
2655 }
2656 }
2657
2658 return true;
2659 }
2660
2661 /*!
2662 @brief scan a string literal
2663
2664 This function scans a string according to Sect. 7 of RFC 7159. While
2665 scanning, bytes are escaped and copied into buffer token_buffer. Then the
2666 function returns successfully, token_buffer is *not* null-terminated (as it
2667 may contain \0 bytes), and token_buffer.size() is the number of bytes in the
2668 string.
2669
2670 @return token_type::value_string if string could be successfully scanned,
2671 token_type::parse_error otherwise
2672
2673 @note In case of errors, variable error_message contains a textual
2674 description.
2675 */
2676 token_type scan_string()
2677 {
2678 // reset token_buffer (ignore opening quote)
2679 reset();
2680
2681 // we entered the function by reading an open quote
2682 assert(current == '\"');
2683
2684 while (true)
2685 {
2686 // get next character
2687 switch (get())
2688 {
2689 // end of file while parsing string
2690 case std::char_traits<char>::eof():
2691 {
2692 error_message = "invalid string: missing closing quote";
2693 return token_type::parse_error;
2694 }
2695
2696 // closing quote
2697 case '\"':
2698 {
2699 return token_type::value_string;
2700 }
2701
2702 // escapes
2703 case '\\':
2704 {
2705 switch (get())
2706 {
2707 // quotation mark
2708 case '\"':
2709 add('\"');
2710 break;
2711 // reverse solidus
2712 case '\\':
2713 add('\\');
2714 break;
2715 // solidus
2716 case '/':
2717 add('/');
2718 break;
2719 // backspace
2720 case 'b':
2721 add('\b');
2722 break;
2723 // form feed
2724 case 'f':
2725 add('\f');
2726 break;
2727 // line feed
2728 case 'n':
2729 add('\n');
2730 break;
2731 // carriage return
2732 case 'r':
2733 add('\r');
2734 break;
2735 // tab
2736 case 't':
2737 add('\t');
2738 break;
2739
2740 // unicode escapes
2741 case 'u':
2742 {
2743 const int codepoint1 = get_codepoint();
2744 int codepoint = codepoint1; // start with codepoint1
2745
2746 if (JSON_UNLIKELY(codepoint1 == -1))
2747 {
2748 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
2749 return token_type::parse_error;
2750 }
2751
2752 // check if code point is a high surrogate
2753 if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
2754 {
2755 // expect next \uxxxx entry
2756 if (JSON_LIKELY(get() == '\\' and get() == 'u'))
2757 {
2758 const int codepoint2 = get_codepoint();
2759
2760 if (JSON_UNLIKELY(codepoint2 == -1))
2761 {
2762 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
2763 return token_type::parse_error;
2764 }
2765
2766 // check if codepoint2 is a low surrogate
2767 if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
2768 {
2769 // overwrite codepoint
2770 codepoint =
2771 // high surrogate occupies the most significant 22 bits
2772 (codepoint1 << 10)
2773 // low surrogate occupies the least significant 15 bits
2774 + codepoint2
2775 // there is still the 0xD800, 0xDC00 and 0x10000 noise
2776 // in the result so we have to subtract with:
2777 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
2778 - 0x35FDC00;
2779 }
2780 else
2781 {
2782 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
2783 return token_type::parse_error;
2784 }
2785 }
2786 else
2787 {
2788 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
2789 return token_type::parse_error;
2790 }
2791 }
2792 else
2793 {
2794 if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
2795 {
2796 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
2797 return token_type::parse_error;
2798 }
2799 }
2800
2801 // result of the above calculation yields a proper codepoint
2802 assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
2803
2804 // translate codepoint into bytes
2805 if (codepoint < 0x80)
2806 {
2807 // 1-byte characters: 0xxxxxxx (ASCII)
2808 add(codepoint);
2809 }
2810 else if (codepoint <= 0x7FF)
2811 {
2812 // 2-byte characters: 110xxxxx 10xxxxxx
2813 add(0xC0 | (codepoint >> 6));
2814 add(0x80 | (codepoint & 0x3F));
2815 }
2816 else if (codepoint <= 0xFFFF)
2817 {
2818 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
2819 add(0xE0 | (codepoint >> 12));
2820 add(0x80 | ((codepoint >> 6) & 0x3F));
2821 add(0x80 | (codepoint & 0x3F));
2822 }
2823 else
2824 {
2825 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2826 add(0xF0 | (codepoint >> 18));
2827 add(0x80 | ((codepoint >> 12) & 0x3F));
2828 add(0x80 | ((codepoint >> 6) & 0x3F));
2829 add(0x80 | (codepoint & 0x3F));
2830 }
2831
2832 break;
2833 }
2834
2835 // other characters after escape
2836 default:
2837 error_message = "invalid string: forbidden character after backslash";
2838 return token_type::parse_error;
2839 }
2840
2841 break;
2842 }
2843
2844 // invalid control characters
2845 case 0x00:
2846 {
2847 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
2848 return token_type::parse_error;
2849 }
2850
2851 case 0x01:
2852 {
2853 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
2854 return token_type::parse_error;
2855 }
2856
2857 case 0x02:
2858 {
2859 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
2860 return token_type::parse_error;
2861 }
2862
2863 case 0x03:
2864 {
2865 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
2866 return token_type::parse_error;
2867 }
2868
2869 case 0x04:
2870 {
2871 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
2872 return token_type::parse_error;
2873 }
2874
2875 case 0x05:
2876 {
2877 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
2878 return token_type::parse_error;
2879 }
2880
2881 case 0x06:
2882 {
2883 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
2884 return token_type::parse_error;
2885 }
2886
2887 case 0x07:
2888 {
2889 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
2890 return token_type::parse_error;
2891 }
2892
2893 case 0x08:
2894 {
2895 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
2896 return token_type::parse_error;
2897 }
2898
2899 case 0x09:
2900 {
2901 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
2902 return token_type::parse_error;
2903 }
2904
2905 case 0x0A:
2906 {
2907 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
2908 return token_type::parse_error;
2909 }
2910
2911 case 0x0B:
2912 {
2913 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
2914 return token_type::parse_error;
2915 }
2916
2917 case 0x0C:
2918 {
2919 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
2920 return token_type::parse_error;
2921 }
2922
2923 case 0x0D:
2924 {
2925 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
2926 return token_type::parse_error;
2927 }
2928
2929 case 0x0E:
2930 {
2931 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
2932 return token_type::parse_error;
2933 }
2934
2935 case 0x0F:
2936 {
2937 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
2938 return token_type::parse_error;
2939 }
2940
2941 case 0x10:
2942 {
2943 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
2944 return token_type::parse_error;
2945 }
2946
2947 case 0x11:
2948 {
2949 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
2950 return token_type::parse_error;
2951 }
2952
2953 case 0x12:
2954 {
2955 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
2956 return token_type::parse_error;
2957 }
2958
2959 case 0x13:
2960 {
2961 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
2962 return token_type::parse_error;
2963 }
2964
2965 case 0x14:
2966 {
2967 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
2968 return token_type::parse_error;
2969 }
2970
2971 case 0x15:
2972 {
2973 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
2974 return token_type::parse_error;
2975 }
2976
2977 case 0x16:
2978 {
2979 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
2980 return token_type::parse_error;
2981 }
2982
2983 case 0x17:
2984 {
2985 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
2986 return token_type::parse_error;
2987 }
2988
2989 case 0x18:
2990 {
2991 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
2992 return token_type::parse_error;
2993 }
2994
2995 case 0x19:
2996 {
2997 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
2998 return token_type::parse_error;
2999 }
3000
3001 case 0x1A:
3002 {
3003 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
3004 return token_type::parse_error;
3005 }
3006
3007 case 0x1B:
3008 {
3009 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
3010 return token_type::parse_error;
3011 }
3012
3013 case 0x1C:
3014 {
3015 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
3016 return token_type::parse_error;
3017 }
3018
3019 case 0x1D:
3020 {
3021 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
3022 return token_type::parse_error;
3023 }
3024
3025 case 0x1E:
3026 {
3027 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
3028 return token_type::parse_error;
3029 }
3030
3031 case 0x1F:
3032 {
3033 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
3034 return token_type::parse_error;
3035 }
3036
3037 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
3038 case 0x20:
3039 case 0x21:
3040 case 0x23:
3041 case 0x24:
3042 case 0x25:
3043 case 0x26:
3044 case 0x27:
3045 case 0x28:
3046 case 0x29:
3047 case 0x2A:
3048 case 0x2B:
3049 case 0x2C:
3050 case 0x2D:
3051 case 0x2E:
3052 case 0x2F:
3053 case 0x30:
3054 case 0x31:
3055 case 0x32:
3056 case 0x33:
3057 case 0x34:
3058 case 0x35:
3059 case 0x36:
3060 case 0x37:
3061 case 0x38:
3062 case 0x39:
3063 case 0x3A:
3064 case 0x3B:
3065 case 0x3C:
3066 case 0x3D:
3067 case 0x3E:
3068 case 0x3F:
3069 case 0x40:
3070 case 0x41:
3071 case 0x42:
3072 case 0x43:
3073 case 0x44:
3074 case 0x45:
3075 case 0x46:
3076 case 0x47:
3077 case 0x48:
3078 case 0x49:
3079 case 0x4A:
3080 case 0x4B:
3081 case 0x4C:
3082 case 0x4D:
3083 case 0x4E:
3084 case 0x4F:
3085 case 0x50:
3086 case 0x51:
3087 case 0x52:
3088 case 0x53:
3089 case 0x54:
3090 case 0x55:
3091 case 0x56:
3092 case 0x57:
3093 case 0x58:
3094 case 0x59:
3095 case 0x5A:
3096 case 0x5B:
3097 case 0x5D:
3098 case 0x5E:
3099 case 0x5F:
3100 case 0x60:
3101 case 0x61:
3102 case 0x62:
3103 case 0x63:
3104 case 0x64:
3105 case 0x65:
3106 case 0x66:
3107 case 0x67:
3108 case 0x68:
3109 case 0x69:
3110 case 0x6A:
3111 case 0x6B:
3112 case 0x6C:
3113 case 0x6D:
3114 case 0x6E:
3115 case 0x6F:
3116 case 0x70:
3117 case 0x71:
3118 case 0x72:
3119 case 0x73:
3120 case 0x74:
3121 case 0x75:
3122 case 0x76:
3123 case 0x77:
3124 case 0x78:
3125 case 0x79:
3126 case 0x7A:
3127 case 0x7B:
3128 case 0x7C:
3129 case 0x7D:
3130 case 0x7E:
3131 case 0x7F:
3132 {
3133 add(current);
3134 break;
3135 }
3136
3137 // U+0080..U+07FF: bytes C2..DF 80..BF
3138 case 0xC2:
3139 case 0xC3:
3140 case 0xC4:
3141 case 0xC5:
3142 case 0xC6:
3143 case 0xC7:
3144 case 0xC8:
3145 case 0xC9:
3146 case 0xCA:
3147 case 0xCB:
3148 case 0xCC:
3149 case 0xCD:
3150 case 0xCE:
3151 case 0xCF:
3152 case 0xD0:
3153 case 0xD1:
3154 case 0xD2:
3155 case 0xD3:
3156 case 0xD4:
3157 case 0xD5:
3158 case 0xD6:
3159 case 0xD7:
3160 case 0xD8:
3161 case 0xD9:
3162 case 0xDA:
3163 case 0xDB:
3164 case 0xDC:
3165 case 0xDD:
3166 case 0xDE:
3167 case 0xDF:
3168 {
3169 if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
3170 {
3171 return token_type::parse_error;
3172 }
3173 break;
3174 }
3175
3176 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
3177 case 0xE0:
3178 {
3179 if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
3180 {
3181 return token_type::parse_error;
3182 }
3183 break;
3184 }
3185
3186 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
3187 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
3188 case 0xE1:
3189 case 0xE2:
3190 case 0xE3:
3191 case 0xE4:
3192 case 0xE5:
3193 case 0xE6:
3194 case 0xE7:
3195 case 0xE8:
3196 case 0xE9:
3197 case 0xEA:
3198 case 0xEB:
3199 case 0xEC:
3200 case 0xEE:
3201 case 0xEF:
3202 {
3203 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
3204 {
3205 return token_type::parse_error;
3206 }
3207 break;
3208 }
3209
3210 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
3211 case 0xED:
3212 {
3213 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
3214 {
3215 return token_type::parse_error;
3216 }
3217 break;
3218 }
3219
3220 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
3221 case 0xF0:
3222 {
3223 if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
3224 {
3225 return token_type::parse_error;
3226 }
3227 break;
3228 }
3229
3230 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
3231 case 0xF1:
3232 case 0xF2:
3233 case 0xF3:
3234 {
3235 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
3236 {
3237 return token_type::parse_error;
3238 }
3239 break;
3240 }
3241
3242 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
3243 case 0xF4:
3244 {
3245 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
3246 {
3247 return token_type::parse_error;
3248 }
3249 break;
3250 }
3251
3252 // remaining bytes (80..C1 and F5..FF) are ill-formed
3253 default:
3254 {
3255 error_message = "invalid string: ill-formed UTF-8 byte";
3256 return token_type::parse_error;
3257 }
3258 }
3259 }
3260 }
3261
3262 static void strtof(float& f, const char* str, char** endptr) noexcept
3263 {
3264 f = std::strtof(str, endptr);
3265 }
3266
3267 static void strtof(double& f, const char* str, char** endptr) noexcept
3268 {
3269 f = std::strtod(str, endptr);
3270 }
3271
3272 static void strtof(long double& f, const char* str, char** endptr) noexcept
3273 {
3274 f = std::strtold(str, endptr);
3275 }
3276
3277 /*!
3278 @brief scan a number literal
3279
3280 This function scans a string according to Sect. 6 of RFC 7159.
3281
3282 The function is realized with a deterministic finite state machine derived
3283 from the grammar described in RFC 7159. Starting in state "init", the
3284 input is read and used to determined the next state. Only state "done"
3285 accepts the number. State "error" is a trap state to model errors. In the
3286 table below, "anything" means any character but the ones listed before.
3287
3288 state | 0 | 1-9 | e E | + | - | . | anything
3289 ---------|----------|----------|----------|---------|---------|----------|-----------
3290 init | zero | any1 | [error] | [error] | minus | [error] | [error]
3291 minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
3292 zero | done | done | exponent | done | done | decimal1 | done
3293 any1 | any1 | any1 | exponent | done | done | decimal1 | done
3294 decimal1 | decimal2 | [error] | [error] | [error] | [error] | [error] | [error]
3295 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
3296 exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
3297 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
3298 any2 | any2 | any2 | done | done | done | done | done
3299
3300 The state machine is realized with one label per state (prefixed with
3301 "scan_number_") and `goto` statements between them. The state machine
3302 contains cycles, but any cycle can be left when EOF is read. Therefore,
3303 the function is guaranteed to terminate.
3304
3305 During scanning, the read bytes are stored in token_buffer. This string is
3306 then converted to a signed integer, an unsigned integer, or a
3307 floating-point number.
3308
3309 @return token_type::value_unsigned, token_type::value_integer, or
3310 token_type::value_float if number could be successfully scanned,
3311 token_type::parse_error otherwise
3312
3313 @note The scanner is independent of the current locale. Internally, the
3314 locale's decimal point is used instead of `.` to work with the
3315 locale-dependent converters.
3316 */
3317 token_type scan_number() // lgtm [cpp/use-of-goto]
3318 {
3319 // reset token_buffer to store the number's bytes
3320 reset();
3321
3322 // the type of the parsed number; initially set to unsigned; will be
3323 // changed if minus sign, decimal point or exponent is read
3324 token_type number_type = token_type::value_unsigned;
3325
3326 // state (init): we just found out we need to scan a number
3327 switch (current)
3328 {
3329 case '-':
3330 {
3331 add(current);
3332 goto scan_number_minus;
3333 }
3334
3335 case '0':
3336 {
3337 add(current);
3338 goto scan_number_zero;
3339 }
3340
3341 case '1':
3342 case '2':
3343 case '3':
3344 case '4':
3345 case '5':
3346 case '6':
3347 case '7':
3348 case '8':
3349 case '9':
3350 {
3351 add(current);
3352 goto scan_number_any1;
3353 }
3354
3355 // LCOV_EXCL_START
3356 default:
3357 {
3358 // all other characters are rejected outside scan_number()
3359 assert(false);
3360 }
3361 // LCOV_EXCL_STOP
3362 }
3363
3364scan_number_minus:
3365 // state: we just parsed a leading minus sign
3366 number_type = token_type::value_integer;
3367 switch (get())
3368 {
3369 case '0':
3370 {
3371 add(current);
3372 goto scan_number_zero;
3373 }
3374
3375 case '1':
3376 case '2':
3377 case '3':
3378 case '4':
3379 case '5':
3380 case '6':
3381 case '7':
3382 case '8':
3383 case '9':
3384 {
3385 add(current);
3386 goto scan_number_any1;
3387 }
3388
3389 default:
3390 {
3391 error_message = "invalid number; expected digit after '-'";
3392 return token_type::parse_error;
3393 }
3394 }
3395
3396scan_number_zero:
3397 // state: we just parse a zero (maybe with a leading minus sign)
3398 switch (get())
3399 {
3400 case '.':
3401 {
3402 add(decimal_point_char);
3403 goto scan_number_decimal1;
3404 }
3405
3406 case 'e':
3407 case 'E':
3408 {
3409 add(current);
3410 goto scan_number_exponent;
3411 }
3412
3413 default:
3414 goto scan_number_done;
3415 }
3416
3417scan_number_any1:
3418 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
3419 switch (get())
3420 {
3421 case '0':
3422 case '1':
3423 case '2':
3424 case '3':
3425 case '4':
3426 case '5':
3427 case '6':
3428 case '7':
3429 case '8':
3430 case '9':
3431 {
3432 add(current);
3433 goto scan_number_any1;
3434 }
3435
3436 case '.':
3437 {
3438 add(decimal_point_char);
3439 goto scan_number_decimal1;
3440 }
3441
3442 case 'e':
3443 case 'E':
3444 {
3445 add(current);
3446 goto scan_number_exponent;
3447 }
3448
3449 default:
3450 goto scan_number_done;
3451 }
3452
3453scan_number_decimal1:
3454 // state: we just parsed a decimal point
3455 number_type = token_type::value_float;
3456 switch (get())
3457 {
3458 case '0':
3459 case '1':
3460 case '2':
3461 case '3':
3462 case '4':
3463 case '5':
3464 case '6':
3465 case '7':
3466 case '8':
3467 case '9':
3468 {
3469 add(current);
3470 goto scan_number_decimal2;
3471 }
3472
3473 default:
3474 {
3475 error_message = "invalid number; expected digit after '.'";
3476 return token_type::parse_error;
3477 }
3478 }
3479
3480scan_number_decimal2:
3481 // we just parsed at least one number after a decimal point
3482 switch (get())
3483 {
3484 case '0':
3485 case '1':
3486 case '2':
3487 case '3':
3488 case '4':
3489 case '5':
3490 case '6':
3491 case '7':
3492 case '8':
3493 case '9':
3494 {
3495 add(current);
3496 goto scan_number_decimal2;
3497 }
3498
3499 case 'e':
3500 case 'E':
3501 {
3502 add(current);
3503 goto scan_number_exponent;
3504 }
3505
3506 default:
3507 goto scan_number_done;
3508 }
3509
3510scan_number_exponent:
3511 // we just parsed an exponent
3512 number_type = token_type::value_float;
3513 switch (get())
3514 {
3515 case '+':
3516 case '-':
3517 {
3518 add(current);
3519 goto scan_number_sign;
3520 }
3521
3522 case '0':
3523 case '1':
3524 case '2':
3525 case '3':
3526 case '4':
3527 case '5':
3528 case '6':
3529 case '7':
3530 case '8':
3531 case '9':
3532 {
3533 add(current);
3534 goto scan_number_any2;
3535 }
3536
3537 default:
3538 {
3539 error_message =
3540 "invalid number; expected '+', '-', or digit after exponent";
3541 return token_type::parse_error;
3542 }
3543 }
3544
3545scan_number_sign:
3546 // we just parsed an exponent sign
3547 switch (get())
3548 {
3549 case '0':
3550 case '1':
3551 case '2':
3552 case '3':
3553 case '4':
3554 case '5':
3555 case '6':
3556 case '7':
3557 case '8':
3558 case '9':
3559 {
3560 add(current);
3561 goto scan_number_any2;
3562 }
3563
3564 default:
3565 {
3566 error_message = "invalid number; expected digit after exponent sign";
3567 return token_type::parse_error;
3568 }
3569 }
3570
3571scan_number_any2:
3572 // we just parsed a number after the exponent or exponent sign
3573 switch (get())
3574 {
3575 case '0':
3576 case '1':
3577 case '2':
3578 case '3':
3579 case '4':
3580 case '5':
3581 case '6':
3582 case '7':
3583 case '8':
3584 case '9':
3585 {
3586 add(current);
3587 goto scan_number_any2;
3588 }
3589
3590 default:
3591 goto scan_number_done;
3592 }
3593
3594scan_number_done:
3595 // unget the character after the number (we only read it to know that
3596 // we are done scanning a number)
3597 unget();
3598
3599 char* endptr = nullptr;
3600 errno = 0;
3601
3602 // try to parse integers first and fall back to floats
3603 if (number_type == token_type::value_unsigned)
3604 {
3605 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
3606
3607 // we checked the number format before
3608 assert(endptr == token_buffer.data() + token_buffer.size());
3609
3610 if (errno == 0)
3611 {
3612 value_unsigned = static_cast<number_unsigned_t>(x);
3613 if (value_unsigned == x)
3614 {
3615 return token_type::value_unsigned;
3616 }
3617 }
3618 }
3619 else if (number_type == token_type::value_integer)
3620 {
3621 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
3622
3623 // we checked the number format before
3624 assert(endptr == token_buffer.data() + token_buffer.size());
3625
3626 if (errno == 0)
3627 {
3628 value_integer = static_cast<number_integer_t>(x);
3629 if (value_integer == x)
3630 {
3631 return token_type::value_integer;
3632 }
3633 }
3634 }
3635
3636 // this code is reached if we parse a floating-point number or if an
3637 // integer conversion above failed
3638 strtof(value_float, token_buffer.data(), &endptr);
3639
3640 // we checked the number format before
3641 assert(endptr == token_buffer.data() + token_buffer.size());
3642
3643 return token_type::value_float;
3644 }
3645
3646 /*!
3647 @param[in] literal_text the literal text to expect
3648 @param[in] length the length of the passed literal text
3649 @param[in] return_type the token type to return on success
3650 */
3651 token_type scan_literal(const char* literal_text, const std::size_t length,
3652 token_type return_type)
3653 {
3654 assert(current == literal_text[0]);
3655 for (std::size_t i = 1; i < length; ++i)
3656 {
3657 if (JSON_UNLIKELY(get() != literal_text[i]))
3658 {
3659 error_message = "invalid literal";
3660 return token_type::parse_error;
3661 }
3662 }
3663 return return_type;
3664 }
3665
3666 /////////////////////
3667 // input management
3668 /////////////////////
3669
3670 /// reset token_buffer; current character is beginning of token
3671 void reset() noexcept
3672 {
3673 token_buffer.clear();
3674 token_string.clear();
3675 token_string.push_back(std::char_traits<char>::to_char_type(current));
3676 }
3677
3678 /*
3679 @brief get next character from the input
3680
3681 This function provides the interface to the used input adapter. It does
3682 not throw in case the input reached EOF, but returns a
3683 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
3684 for use in error messages.
3685
3686 @return character read from the input
3687 */
3688 std::char_traits<char>::int_type get()
3689 {
3690 ++position.chars_read_total;
3691 ++position.chars_read_current_line;
3692
3693 if (next_unget)
3694 {
3695 // just reset the next_unget variable and work with current
3696 next_unget = false;
3697 }
3698 else
3699 {
3700 current = ia->get_character();
3701 }
3702
3703 if (JSON_LIKELY(current != std::char_traits<char>::eof()))
3704 {
3705 token_string.push_back(std::char_traits<char>::to_char_type(current));
3706 }
3707
3708 if (current == '\n')
3709 {
3710 ++position.lines_read;
3711 ++position.chars_read_current_line = 0;
3712 }
3713
3714 return current;
3715 }
3716
3717 /*!
3718 @brief unget current character (read it again on next get)
3719
3720 We implement unget by setting variable next_unget to true. The input is not
3721 changed - we just simulate ungetting by modifying chars_read_total,
3722 chars_read_current_line, and token_string. The next call to get() will
3723 behave as if the unget character is read again.
3724 */
3725 void unget()
3726 {
3727 next_unget = true;
3728
3729 --position.chars_read_total;
3730
3731 // in case we "unget" a newline, we have to also decrement the lines_read
3732 if (position.chars_read_current_line == 0)
3733 {
3734 if (position.lines_read > 0)
3735 {
3736 --position.lines_read;
3737 }
3738 }
3739 else
3740 {
3741 --position.chars_read_current_line;
3742 }
3743
3744 if (JSON_LIKELY(current != std::char_traits<char>::eof()))
3745 {
3746 assert(token_string.size() != 0);
3747 token_string.pop_back();
3748 }
3749 }
3750
3751 /// add a character to token_buffer
3752 void add(int c)
3753 {
3754 token_buffer.push_back(std::char_traits<char>::to_char_type(c));
3755 }
3756
3757 public:
3758 /////////////////////
3759 // value getters
3760 /////////////////////
3761
3762 /// return integer value
3763 constexpr number_integer_t get_number_integer() const noexcept
3764 {
3765 return value_integer;
3766 }
3767
3768 /// return unsigned integer value
3769 constexpr number_unsigned_t get_number_unsigned() const noexcept
3770 {
3771 return value_unsigned;
3772 }
3773
3774 /// return floating-point value
3775 constexpr number_float_t get_number_float() const noexcept
3776 {
3777 return value_float;
3778 }
3779
3780 /// return current string value (implicitly resets the token; useful only once)
3781 string_t& get_string()
3782 {
3783 return token_buffer;
3784 }
3785
3786 /////////////////////
3787 // diagnostics
3788 /////////////////////
3789
3790 /// return position of last read token
3791 constexpr position_t get_position() const noexcept
3792 {
3793 return position;
3794 }
3795
3796 /// return the last read token (for errors only). Will never contain EOF
3797 /// (an arbitrary value that is not a valid char value, often -1), because
3798 /// 255 may legitimately occur. May contain NUL, which should be escaped.
3799 std::string get_token_string() const
3800 {
3801 // escape control characters
3802 std::string result;
3803 for (const auto c : token_string)
3804 {
3805 if ('\x00' <= c and c <= '\x1F')
3806 {
3807 // escape control characters
3808 char cs[9];
3809 snprintf(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
3810 result += cs;
3811 }
3812 else
3813 {
3814 // add character as is
3815 result.push_back(c);
3816 }
3817 }
3818
3819 return result;
3820 }
3821
3822 /// return syntax error message
3823 constexpr const char* get_error_message() const noexcept
3824 {
3825 return error_message;
3826 }
3827
3828 /////////////////////
3829 // actual scanner
3830 /////////////////////
3831
3832 /*!
3833 @brief skip the UTF-8 byte order mark
3834 @return true iff there is no BOM or the correct BOM has been skipped
3835 */
3836 bool skip_bom()
3837 {
3838 if (get() == 0xEF)
3839 {
3840 // check if we completely parse the BOM
3841 return get() == 0xBB and get() == 0xBF;
3842 }
3843
3844 // the first character is not the beginning of the BOM; unget it to
3845 // process is later
3846 unget();
3847 return true;
3848 }
3849
3850 token_type scan()
3851 {
3852 // initially, skip the BOM
3853 if (position.chars_read_total == 0 and not skip_bom())
3854 {
3855 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
3856 return token_type::parse_error;
3857 }
3858
3859 // read next character and ignore whitespace
3860 do
3861 {
3862 get();
3863 }
3864 while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
3865
3866 switch (current)
3867 {
3868 // structural characters
3869 case '[':
3870 return token_type::begin_array;
3871 case ']':
3872 return token_type::end_array;
3873 case '{':
3874 return token_type::begin_object;
3875 case '}':
3876 return token_type::end_object;
3877 case ':':
3878 return token_type::name_separator;
3879 case ',':
3880 return token_type::value_separator;
3881
3882 // literals
3883 case 't':
3884 return scan_literal("true", 4, token_type::literal_true);
3885 case 'f':
3886 return scan_literal("false", 5, token_type::literal_false);
3887 case 'n':
3888 return scan_literal("null", 4, token_type::literal_null);
3889
3890 // string
3891 case '\"':
3892 return scan_string();
3893
3894 // number
3895 case '-':
3896 case '0':
3897 case '1':
3898 case '2':
3899 case '3':
3900 case '4':
3901 case '5':
3902 case '6':
3903 case '7':
3904 case '8':
3905 case '9':
3906 return scan_number();
3907
3908 // end of input (the null byte is needed when parsing from
3909 // string literals)
3910 case '\0':
3911 case std::char_traits<char>::eof():
3912 return token_type::end_of_input;
3913
3914 // error
3915 default:
3916 error_message = "invalid literal";
3917 return token_type::parse_error;
3918 }
3919 }
3920
3921 private:
3922 /// input adapter
3923 detail::input_adapter_t ia = nullptr;
3924
3925 /// the current character
3926 std::char_traits<char>::int_type current = std::char_traits<char>::eof();
3927
3928 /// whether the next get() call should just return current
3929 bool next_unget = false;
3930
3931 /// the start position of the current token
3932 position_t position;
3933
3934 /// raw input token string (for error messages)
3935 std::vector<char> token_string {};
3936
3937 /// buffer for variable-length tokens (numbers, strings)
3938 string_t token_buffer {};
3939
3940 /// a description of occurred lexer errors
3941 const char* error_message = "";
3942
3943 // number values
3944 number_integer_t value_integer = 0;
3945 number_unsigned_t value_unsigned = 0;
3946 number_float_t value_float = 0;
3947
3948 /// the decimal point
3949 const char decimal_point_char = '.';
3950};
3951} // namespace detail
3952} // namespace nlohmann
3953
3954// #include <nlohmann/detail/input/parser.hpp>
3955
3956
3957#include <cassert> // assert
3958#include <cmath> // isfinite
3959#include <cstdint> // uint8_t
3960#include <functional> // function
3961#include <string> // string
3962#include <utility> // move
3963
3964// #include <nlohmann/detail/exceptions.hpp>
3965
3966// #include <nlohmann/detail/macro_scope.hpp>
3967
3968// #include <nlohmann/detail/meta/is_sax.hpp>
3969
3970
3971#include <cstdint> // size_t
3972#include <utility> // declval
3973
3974// #include <nlohmann/detail/meta/detected.hpp>
3975
3976// #include <nlohmann/detail/meta/type_traits.hpp>
3977
3978
3979namespace nlohmann
3980{
3981namespace detail
3982{
3983template <typename T>
3984using null_function_t = decltype(std::declval<T&>().null());
3985
3986template <typename T>
3987using boolean_function_t =
3988 decltype(std::declval<T&>().boolean(std::declval<bool>()));
3989
3990template <typename T, typename Integer>
3991using number_integer_function_t =
3992 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
3993
3994template <typename T, typename Unsigned>
3995using number_unsigned_function_t =
3996 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
3997
3998template <typename T, typename Float, typename String>
3999using number_float_function_t = decltype(std::declval<T&>().number_float(
4000 std::declval<Float>(), std::declval<const String&>()));
4001
4002template <typename T, typename String>
4003using string_function_t =
4004 decltype(std::declval<T&>().string(std::declval<String&>()));
4005
4006template <typename T>
4007using start_object_function_t =
4008 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
4009
4010template <typename T, typename String>
4011using key_function_t =
4012 decltype(std::declval<T&>().key(std::declval<String&>()));
4013
4014template <typename T>
4015using end_object_function_t = decltype(std::declval<T&>().end_object());
4016
4017template <typename T>
4018using start_array_function_t =
4019 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
4020
4021template <typename T>
4022using end_array_function_t = decltype(std::declval<T&>().end_array());
4023
4024template <typename T, typename Exception>
4025using parse_error_function_t = decltype(std::declval<T&>().parse_error(
4026 std::declval<std::size_t>(), std::declval<const std::string&>(),
4027 std::declval<const Exception&>()));
4028
4029template <typename SAX, typename BasicJsonType>
4030struct is_sax
4031{
4032 private:
4033 static_assert(is_basic_json<BasicJsonType>::value,
4034 "BasicJsonType must be of type basic_json<...>");
4035
4036 using number_integer_t = typename BasicJsonType::number_integer_t;
4037 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4038 using number_float_t = typename BasicJsonType::number_float_t;
4039 using string_t = typename BasicJsonType::string_t;
4040 using exception_t = typename BasicJsonType::exception;
4041
4042 public:
4043 static constexpr bool value =
4044 is_detected_exact<bool, null_function_t, SAX>::value &&
4045 is_detected_exact<bool, boolean_function_t, SAX>::value &&
4046 is_detected_exact<bool, number_integer_function_t, SAX,
4047 number_integer_t>::value &&
4048 is_detected_exact<bool, number_unsigned_function_t, SAX,
4049 number_unsigned_t>::value &&
4050 is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
4051 string_t>::value &&
4052 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
4053 is_detected_exact<bool, start_object_function_t, SAX>::value &&
4054 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
4055 is_detected_exact<bool, end_object_function_t, SAX>::value &&
4056 is_detected_exact<bool, start_array_function_t, SAX>::value &&
4057 is_detected_exact<bool, end_array_function_t, SAX>::value &&
4058 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
4059};
4060
4061template <typename SAX, typename BasicJsonType>
4062struct is_sax_static_asserts
4063{
4064 private:
4065 static_assert(is_basic_json<BasicJsonType>::value,
4066 "BasicJsonType must be of type basic_json<...>");
4067
4068 using number_integer_t = typename BasicJsonType::number_integer_t;
4069 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4070 using number_float_t = typename BasicJsonType::number_float_t;
4071 using string_t = typename BasicJsonType::string_t;
4072 using exception_t = typename BasicJsonType::exception;
4073
4074 public:
4075 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
4076 "Missing/invalid function: bool null()");
4077 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
4078 "Missing/invalid function: bool boolean(bool)");
4079 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
4080 "Missing/invalid function: bool boolean(bool)");
4081 static_assert(
4082 is_detected_exact<bool, number_integer_function_t, SAX,
4083 number_integer_t>::value,
4084 "Missing/invalid function: bool number_integer(number_integer_t)");
4085 static_assert(
4086 is_detected_exact<bool, number_unsigned_function_t, SAX,
4087 number_unsigned_t>::value,
4088 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
4089 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
4090 number_float_t, string_t>::value,
4091 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
4092 static_assert(
4093 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
4094 "Missing/invalid function: bool string(string_t&)");
4095 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
4096 "Missing/invalid function: bool start_object(std::size_t)");
4097 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
4098 "Missing/invalid function: bool key(string_t&)");
4099 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
4100 "Missing/invalid function: bool end_object()");
4101 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
4102 "Missing/invalid function: bool start_array(std::size_t)");
4103 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
4104 "Missing/invalid function: bool end_array()");
4105 static_assert(
4106 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
4107 "Missing/invalid function: bool parse_error(std::size_t, const "
4108 "std::string&, const exception&)");
4109};
4110} // namespace detail
4111} // namespace nlohmann
4112
4113// #include <nlohmann/detail/input/input_adapters.hpp>
4114
4115// #include <nlohmann/detail/input/json_sax.hpp>
4116
4117
4118#include <cstddef>
4119#include <string>
4120#include <vector>
4121
4122// #include <nlohmann/detail/input/parser.hpp>
4123
4124// #include <nlohmann/detail/exceptions.hpp>
4125
4126
4127namespace nlohmann
4128{
4129
4130/*!
4131@brief SAX interface
4132
4133This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
4134Each function is called in different situations while the input is parsed. The
4135boolean return value informs the parser whether to continue processing the
4136input.
4137*/
4138template<typename BasicJsonType>
4139struct json_sax
4140{
4141 /// type for (signed) integers
4142 using number_integer_t = typename BasicJsonType::number_integer_t;
4143 /// type for unsigned integers
4144 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4145 /// type for floating-point numbers
4146 using number_float_t = typename BasicJsonType::number_float_t;
4147 /// type for strings
4148 using string_t = typename BasicJsonType::string_t;
4149
4150 /*!
4151 @brief a null value was read
4152 @return whether parsing should proceed
4153 */
4154 virtual bool null() = 0;
4155
4156 /*!
4157 @brief a boolean value was read
4158 @param[in] val boolean value
4159 @return whether parsing should proceed
4160 */
4161 virtual bool boolean(bool val) = 0;
4162
4163 /*!
4164 @brief an integer number was read
4165 @param[in] val integer value
4166 @return whether parsing should proceed
4167 */
4168 virtual bool number_integer(number_integer_t val) = 0;
4169
4170 /*!
4171 @brief an unsigned integer number was read
4172 @param[in] val unsigned integer value
4173 @return whether parsing should proceed
4174 */
4175 virtual bool number_unsigned(number_unsigned_t val) = 0;
4176
4177 /*!
4178 @brief an floating-point number was read
4179 @param[in] val floating-point value
4180 @param[in] s raw token value
4181 @return whether parsing should proceed
4182 */
4183 virtual bool number_float(number_float_t val, const string_t& s) = 0;
4184
4185 /*!
4186 @brief a string was read
4187 @param[in] val string value
4188 @return whether parsing should proceed
4189 @note It is safe to move the passed string.
4190 */
4191 virtual bool string(string_t& val) = 0;
4192
4193 /*!
4194 @brief the beginning of an object was read
4195 @param[in] elements number of object elements or -1 if unknown
4196 @return whether parsing should proceed
4197 @note binary formats may report the number of elements
4198 */
4199 virtual bool start_object(std::size_t elements) = 0;
4200
4201 /*!
4202 @brief an object key was read
4203 @param[in] val object key
4204 @return whether parsing should proceed
4205 @note It is safe to move the passed string.
4206 */
4207 virtual bool key(string_t& val) = 0;
4208
4209 /*!
4210 @brief the end of an object was read
4211 @return whether parsing should proceed
4212 */
4213 virtual bool end_object() = 0;
4214
4215 /*!
4216 @brief the beginning of an array was read
4217 @param[in] elements number of array elements or -1 if unknown
4218 @return whether parsing should proceed
4219 @note binary formats may report the number of elements
4220 */
4221 virtual bool start_array(std::size_t elements) = 0;
4222
4223 /*!
4224 @brief the end of an array was read
4225 @return whether parsing should proceed
4226 */
4227 virtual bool end_array() = 0;
4228
4229 /*!
4230 @brief a parse error occurred
4231 @param[in] position the position in the input where the error occurs
4232 @param[in] last_token the last read token
4233 @param[in] ex an exception object describing the error
4234 @return whether parsing should proceed (must return false)
4235 */
4236 virtual bool parse_error(std::size_t position,
4237 const std::string& last_token,
4238 const detail::exception& ex) = 0;
4239
4240 virtual ~json_sax() = default;
4241};
4242
4243
4244namespace detail
4245{
4246/*!
4247@brief SAX implementation to create a JSON value from SAX events
4248
4249This class implements the @ref json_sax interface and processes the SAX events
4250to create a JSON value which makes it basically a DOM parser. The structure or
4251hierarchy of the JSON value is managed by the stack `ref_stack` which contains
4252a pointer to the respective array or object for each recursion depth.
4253
4254After successful parsing, the value that is passed by reference to the
4255constructor contains the parsed value.
4256
4257@tparam BasicJsonType the JSON type
4258*/
4259template<typename BasicJsonType>
4260class json_sax_dom_parser
4261{
4262 public:
4263 using number_integer_t = typename BasicJsonType::number_integer_t;
4264 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4265 using number_float_t = typename BasicJsonType::number_float_t;
4266 using string_t = typename BasicJsonType::string_t;
4267
4268 /*!
4269 @param[in, out] r reference to a JSON value that is manipulated while
4270 parsing
4271 @param[in] allow_exceptions_ whether parse errors yield exceptions
4272 */
4273 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
4274 : root(r), allow_exceptions(allow_exceptions_)
4275 {}
4276
4277 bool null()
4278 {
4279 handle_value(nullptr);
4280 return true;
4281 }
4282
4283 bool boolean(bool val)
4284 {
4285 handle_value(val);
4286 return true;
4287 }
4288
4289 bool number_integer(number_integer_t val)
4290 {
4291 handle_value(val);
4292 return true;
4293 }
4294
4295 bool number_unsigned(number_unsigned_t val)
4296 {
4297 handle_value(val);
4298 return true;
4299 }
4300
4301 bool number_float(number_float_t val, const string_t& /*unused*/)
4302 {
4303 handle_value(val);
4304 return true;
4305 }
4306
4307 bool string(string_t& val)
4308 {
4309 handle_value(val);
4310 return true;
4311 }
4312
4313 bool start_object(std::size_t len)
4314 {
4315 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
4316
4317 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4318 {
4319 JSON_THROW(out_of_range::create(408,
4320 "excessive object size: " + std::to_string(len)));
4321 }
4322
4323 return true;
4324 }
4325
4326 bool key(string_t& val)
4327 {
4328 // add null at given key and store the reference for later
4329 object_element = &(ref_stack.back()->m_value.object->operator[](val));
4330 return true;
4331 }
4332
4333 bool end_object()
4334 {
4335 ref_stack.pop_back();
4336 return true;
4337 }
4338
4339 bool start_array(std::size_t len)
4340 {
4341 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
4342
4343 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4344 {
4345 JSON_THROW(out_of_range::create(408,
4346 "excessive array size: " + std::to_string(len)));
4347 }
4348
4349 return true;
4350 }
4351
4352 bool end_array()
4353 {
4354 ref_stack.pop_back();
4355 return true;
4356 }
4357
4358 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
4359 const detail::exception& ex)
4360 {
4361 errored = true;
4362 if (allow_exceptions)
4363 {
4364 // determine the proper exception type from the id
4365 switch ((ex.id / 100) % 100)
4366 {
4367 case 1:
4368 JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
4369 case 4:
4370 JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
4371 // LCOV_EXCL_START
4372 case 2:
4373 JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
4374 case 3:
4375 JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
4376 case 5:
4377 JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
4378 default:
4379 assert(false);
4380 // LCOV_EXCL_STOP
4381 }
4382 }
4383 return false;
4384 }
4385
4386 constexpr bool is_errored() const
4387 {
4388 return errored;
4389 }
4390
4391 private:
4392 /*!
4393 @invariant If the ref stack is empty, then the passed value will be the new
4394 root.
4395 @invariant If the ref stack contains a value, then it is an array or an
4396 object to which we can add elements
4397 */
4398 template<typename Value>
4399 BasicJsonType* handle_value(Value&& v)
4400 {
4401 if (ref_stack.empty())
4402 {
4403 root = BasicJsonType(std::forward<Value>(v));
4404 return &root;
4405 }
4406
4407 assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4408
4409 if (ref_stack.back()->is_array())
4410 {
4411 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4412 return &(ref_stack.back()->m_value.array->back());
4413 }
4414 else
4415 {
4416 assert(object_element);
4417 *object_element = BasicJsonType(std::forward<Value>(v));
4418 return object_element;
4419 }
4420 }
4421
4422 /// the parsed JSON value
4423 BasicJsonType& root;
4424 /// stack to model hierarchy of values
4425 std::vector<BasicJsonType*> ref_stack;
4426 /// helper to hold the reference for the next object element
4427 BasicJsonType* object_element = nullptr;
4428 /// whether a syntax error occurred
4429 bool errored = false;
4430 /// whether to throw exceptions in case of errors
4431 const bool allow_exceptions = true;
4432};
4433
4434template<typename BasicJsonType>
4435class json_sax_dom_callback_parser
4436{
4437 public:
4438 using number_integer_t = typename BasicJsonType::number_integer_t;
4439 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4440 using number_float_t = typename BasicJsonType::number_float_t;
4441 using string_t = typename BasicJsonType::string_t;
4442 using parser_callback_t = typename BasicJsonType::parser_callback_t;
4443 using parse_event_t = typename BasicJsonType::parse_event_t;
4444
4445 json_sax_dom_callback_parser(BasicJsonType& r,
4446 const parser_callback_t cb,
4447 const bool allow_exceptions_ = true)
4448 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
4449 {
4450 keep_stack.push_back(true);
4451 }
4452
4453 bool null()
4454 {
4455 handle_value(nullptr);
4456 return true;
4457 }
4458
4459 bool boolean(bool val)
4460 {
4461 handle_value(val);
4462 return true;
4463 }
4464
4465 bool number_integer(number_integer_t val)
4466 {
4467 handle_value(val);
4468 return true;
4469 }
4470
4471 bool number_unsigned(number_unsigned_t val)
4472 {
4473 handle_value(val);
4474 return true;
4475 }
4476
4477 bool number_float(number_float_t val, const string_t& /*unused*/)
4478 {
4479 handle_value(val);
4480 return true;
4481 }
4482
4483 bool string(string_t& val)
4484 {
4485 handle_value(val);
4486 return true;
4487 }
4488
4489 bool start_object(std::size_t len)
4490 {
4491 // check callback for object start
4492 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
4493 keep_stack.push_back(keep);
4494
4495 auto val = handle_value(BasicJsonType::value_t::object, true);
4496 ref_stack.push_back(val.second);
4497
4498 // check object limit
4499 if (ref_stack.back())
4500 {
4501 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4502 {
4503 JSON_THROW(out_of_range::create(408,
4504 "excessive object size: " + std::to_string(len)));
4505 }
4506 }
4507
4508 return true;
4509 }
4510
4511 bool key(string_t& val)
4512 {
4513 BasicJsonType k = BasicJsonType(val);
4514
4515 // check callback for key
4516 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
4517 key_keep_stack.push_back(keep);
4518
4519 // add discarded value at given key and store the reference for later
4520 if (keep and ref_stack.back())
4521 {
4522 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
4523 }
4524
4525 return true;
4526 }
4527
4528 bool end_object()
4529 {
4530 if (ref_stack.back())
4531 {
4532 if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
4533 {
4534 // discard object
4535 *ref_stack.back() = discarded;
4536 }
4537 }
4538
4539 assert(not ref_stack.empty());
4540 assert(not keep_stack.empty());
4541 ref_stack.pop_back();
4542 keep_stack.pop_back();
4543
4544 if (not ref_stack.empty() and ref_stack.back())
4545 {
4546 // remove discarded value
4547 if (ref_stack.back()->is_object())
4548 {
4549 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
4550 {
4551 if (it->is_discarded())
4552 {
4553 ref_stack.back()->erase(it);
4554 break;
4555 }
4556 }
4557 }
4558 }
4559
4560 return true;
4561 }
4562
4563 bool start_array(std::size_t len)
4564 {
4565 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
4566 keep_stack.push_back(keep);
4567
4568 auto val = handle_value(BasicJsonType::value_t::array, true);
4569 ref_stack.push_back(val.second);
4570
4571 // check array limit
4572 if (ref_stack.back())
4573 {
4574 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4575 {
4576 JSON_THROW(out_of_range::create(408,
4577 "excessive array size: " + std::to_string(len)));
4578 }
4579 }
4580
4581 return true;
4582 }
4583
4584 bool end_array()
4585 {
4586 bool keep = true;
4587
4588 if (ref_stack.back())
4589 {
4590 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
4591 if (not keep)
4592 {
4593 // discard array
4594 *ref_stack.back() = discarded;
4595 }
4596 }
4597
4598 assert(not ref_stack.empty());
4599 assert(not keep_stack.empty());
4600 ref_stack.pop_back();
4601 keep_stack.pop_back();
4602
4603 // remove discarded value
4604 if (not keep and not ref_stack.empty())
4605 {
4606 if (ref_stack.back()->is_array())
4607 {
4608 ref_stack.back()->m_value.array->pop_back();
4609 }
4610 }
4611
4612 return true;
4613 }
4614
4615 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
4616 const detail::exception& ex)
4617 {
4618 errored = true;
4619 if (allow_exceptions)
4620 {
4621 // determine the proper exception type from the id
4622 switch ((ex.id / 100) % 100)
4623 {
4624 case 1:
4625 JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
4626 case 4:
4627 JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
4628 // LCOV_EXCL_START
4629 case 2:
4630 JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
4631 case 3:
4632 JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
4633 case 5:
4634 JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
4635 default:
4636 assert(false);
4637 // LCOV_EXCL_STOP
4638 }
4639 }
4640 return false;
4641 }
4642
4643 constexpr bool is_errored() const
4644 {
4645 return errored;
4646 }
4647
4648 private:
4649 /*!
4650 @param[in] v value to add to the JSON value we build during parsing
4651 @param[in] skip_callback whether we should skip calling the callback
4652 function; this is required after start_array() and
4653 start_object() SAX events, because otherwise we would call the
4654 callback function with an empty array or object, respectively.
4655
4656 @invariant If the ref stack is empty, then the passed value will be the new
4657 root.
4658 @invariant If the ref stack contains a value, then it is an array or an
4659 object to which we can add elements
4660
4661 @return pair of boolean (whether value should be kept) and pointer (to the
4662 passed value in the ref_stack hierarchy; nullptr if not kept)
4663 */
4664 template<typename Value>
4665 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
4666 {
4667 assert(not keep_stack.empty());
4668
4669 // do not handle this value if we know it would be added to a discarded
4670 // container
4671 if (not keep_stack.back())
4672 {
4673 return {false, nullptr};
4674 }
4675
4676 // create value
4677 auto value = BasicJsonType(std::forward<Value>(v));
4678
4679 // check callback
4680 const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
4681
4682 // do not handle this value if we just learnt it shall be discarded
4683 if (not keep)
4684 {
4685 return {false, nullptr};
4686 }
4687
4688 if (ref_stack.empty())
4689 {
4690 root = std::move(value);
4691 return {true, &root};
4692 }
4693
4694 // skip this value if we already decided to skip the parent
4695 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
4696 if (not ref_stack.back())
4697 {
4698 return {false, nullptr};
4699 }
4700
4701 // we now only expect arrays and objects
4702 assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4703
4704 if (ref_stack.back()->is_array())
4705 {
4706 ref_stack.back()->m_value.array->push_back(std::move(value));
4707 return {true, &(ref_stack.back()->m_value.array->back())};
4708 }
4709 else
4710 {
4711 // check if we should store an element for the current key
4712 assert(not key_keep_stack.empty());
4713 const bool store_element = key_keep_stack.back();
4714 key_keep_stack.pop_back();
4715
4716 if (not store_element)
4717 {
4718 return {false, nullptr};
4719 }
4720
4721 assert(object_element);
4722 *object_element = std::move(value);
4723 return {true, object_element};
4724 }
4725 }
4726
4727 /// the parsed JSON value
4728 BasicJsonType& root;
4729 /// stack to model hierarchy of values
4730 std::vector<BasicJsonType*> ref_stack;
4731 /// stack to manage which values to keep
4732 std::vector<bool> keep_stack;
4733 /// stack to manage which object keys to keep
4734 std::vector<bool> key_keep_stack;
4735 /// helper to hold the reference for the next object element
4736 BasicJsonType* object_element = nullptr;
4737 /// whether a syntax error occurred
4738 bool errored = false;
4739 /// callback function
4740 const parser_callback_t callback = nullptr;
4741 /// whether to throw exceptions in case of errors
4742 const bool allow_exceptions = true;
4743 /// a discarded value for the callback
4744 BasicJsonType discarded = BasicJsonType::value_t::discarded;
4745};
4746
4747template<typename BasicJsonType>
4748class json_sax_acceptor
4749{
4750 public:
4751 using number_integer_t = typename BasicJsonType::number_integer_t;
4752 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4753 using number_float_t = typename BasicJsonType::number_float_t;
4754 using string_t = typename BasicJsonType::string_t;
4755
4756 bool null()
4757 {
4758 return true;
4759 }
4760
4761 bool boolean(bool /*unused*/)
4762 {
4763 return true;
4764 }
4765
4766 bool number_integer(number_integer_t /*unused*/)
4767 {
4768 return true;
4769 }
4770
4771 bool number_unsigned(number_unsigned_t /*unused*/)
4772 {
4773 return true;
4774 }
4775
4776 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
4777 {
4778 return true;
4779 }
4780
4781 bool string(string_t& /*unused*/)
4782 {
4783 return true;
4784 }
4785
4786 bool start_object(std::size_t /*unused*/ = std::size_t(-1))
4787 {
4788 return true;
4789 }
4790
4791 bool key(string_t& /*unused*/)
4792 {
4793 return true;
4794 }
4795
4796 bool end_object()
4797 {
4798 return true;
4799 }
4800
4801 bool start_array(std::size_t /*unused*/ = std::size_t(-1))
4802 {
4803 return true;
4804 }
4805
4806 bool end_array()
4807 {
4808 return true;
4809 }
4810
4811 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
4812 {
4813 return false;
4814 }
4815};
4816} // namespace detail
4817
4818} // namespace nlohmann
4819
4820// #include <nlohmann/detail/input/lexer.hpp>
4821
4822// #include <nlohmann/detail/value_t.hpp>
4823
4824
4825namespace nlohmann
4826{
4827namespace detail
4828{
4829////////////
4830// parser //
4831////////////
4832
4833/*!
4834@brief syntax analysis
4835
4836This class implements a recursive decent parser.
4837*/
4838template<typename BasicJsonType>
4839class parser
4840{
4841 using number_integer_t = typename BasicJsonType::number_integer_t;
4842 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4843 using number_float_t = typename BasicJsonType::number_float_t;
4844 using string_t = typename BasicJsonType::string_t;
4845 using lexer_t = lexer<BasicJsonType>;
4846 using token_type = typename lexer_t::token_type;
4847
4848 public:
4849 enum class parse_event_t : uint8_t
4850 {
4851 /// the parser read `{` and started to process a JSON object
4852 object_start,
4853 /// the parser read `}` and finished processing a JSON object
4854 object_end,
4855 /// the parser read `[` and started to process a JSON array
4856 array_start,
4857 /// the parser read `]` and finished processing a JSON array
4858 array_end,
4859 /// the parser read a key of a value in an object
4860 key,
4861 /// the parser finished reading a JSON value
4862 value
4863 };
4864
4865 using parser_callback_t =
4866 std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
4867
4868 /// a parser reading from an input adapter
4869 explicit parser(detail::input_adapter_t&& adapter,
4870 const parser_callback_t cb = nullptr,
4871 const bool allow_exceptions_ = true)
4872 : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
4873 {
4874 // read first token
4875 get_token();
4876 }
4877
4878 /*!
4879 @brief public parser interface
4880
4881 @param[in] strict whether to expect the last token to be EOF
4882 @param[in,out] result parsed JSON value
4883
4884 @throw parse_error.101 in case of an unexpected token
4885 @throw parse_error.102 if to_unicode fails or surrogate error
4886 @throw parse_error.103 if to_unicode fails
4887 */
4888 void parse(const bool strict, BasicJsonType& result)
4889 {
4890 if (callback)
4891 {
4892 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
4893 sax_parse_internal(&sdp);
4894 result.assert_invariant();
4895
4896 // in strict mode, input must be completely read
4897 if (strict and (get_token() != token_type::end_of_input))
4898 {
4899 sdp.parse_error(m_lexer.get_position(),
4900 m_lexer.get_token_string(),
4901 parse_error::create(101, m_lexer.get_position(),
4902 exception_message(token_type::end_of_input, "value")));
4903 }
4904
4905 // in case of an error, return discarded value
4906 if (sdp.is_errored())
4907 {
4908 result = value_t::discarded;
4909 return;
4910 }
4911
4912 // set top-level value to null if it was discarded by the callback
4913 // function
4914 if (result.is_discarded())
4915 {
4916 result = nullptr;
4917 }
4918 }
4919 else
4920 {
4921 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
4922 sax_parse_internal(&sdp);
4923 result.assert_invariant();
4924
4925 // in strict mode, input must be completely read
4926 if (strict and (get_token() != token_type::end_of_input))
4927 {
4928 sdp.parse_error(m_lexer.get_position(),
4929 m_lexer.get_token_string(),
4930 parse_error::create(101, m_lexer.get_position(),
4931 exception_message(token_type::end_of_input, "value")));
4932 }
4933
4934 // in case of an error, return discarded value
4935 if (sdp.is_errored())
4936 {
4937 result = value_t::discarded;
4938 return;
4939 }
4940 }
4941 }
4942
4943 /*!
4944 @brief public accept interface
4945
4946 @param[in] strict whether to expect the last token to be EOF
4947 @return whether the input is a proper JSON text
4948 */
4949 bool accept(const bool strict = true)
4950 {
4951 json_sax_acceptor<BasicJsonType> sax_acceptor;
4952 return sax_parse(&sax_acceptor, strict);
4953 }
4954
4955 template <typename SAX>
4956 bool sax_parse(SAX* sax, const bool strict = true)
4957 {
4958 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
4959 const bool result = sax_parse_internal(sax);
4960
4961 // strict mode: next byte must be EOF
4962 if (result and strict and (get_token() != token_type::end_of_input))
4963 {
4964 return sax->parse_error(m_lexer.get_position(),
4965 m_lexer.get_token_string(),
4966 parse_error::create(101, m_lexer.get_position(),
4967 exception_message(token_type::end_of_input, "value")));
4968 }
4969
4970 return result;
4971 }
4972
4973 private:
4974 template <typename SAX>
4975 bool sax_parse_internal(SAX* sax)
4976 {
4977 // stack to remember the hierarchy of structured values we are parsing
4978 // true = array; false = object
4979 std::vector<bool> states;
4980 // value to avoid a goto (see comment where set to true)
4981 bool skip_to_state_evaluation = false;
4982
4983 while (true)
4984 {
4985 if (not skip_to_state_evaluation)
4986 {
4987 // invariant: get_token() was called before each iteration
4988 switch (last_token)
4989 {
4990 case token_type::begin_object:
4991 {
4992 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
4993 {
4994 return false;
4995 }
4996
4997 // closing } -> we are done
4998 if (get_token() == token_type::end_object)
4999 {
5000 if (JSON_UNLIKELY(not sax->end_object()))
5001 {
5002 return false;
5003 }
5004 break;
5005 }
5006
5007 // parse key
5008 if (JSON_UNLIKELY(last_token != token_type::value_string))
5009 {
5010 return sax->parse_error(m_lexer.get_position(),
5011 m_lexer.get_token_string(),
5012 parse_error::create(101, m_lexer.get_position(),
5013 exception_message(token_type::value_string, "object key")));
5014 }
5015 if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
5016 {
5017 return false;
5018 }
5019
5020 // parse separator (:)
5021 if (JSON_UNLIKELY(get_token() != token_type::name_separator))
5022 {
5023 return sax->parse_error(m_lexer.get_position(),
5024 m_lexer.get_token_string(),
5025 parse_error::create(101, m_lexer.get_position(),
5026 exception_message(token_type::name_separator, "object separator")));
5027 }
5028
5029 // remember we are now inside an object
5030 states.push_back(false);
5031
5032 // parse values
5033 get_token();
5034 continue;
5035 }
5036
5037 case token_type::begin_array:
5038 {
5039 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
5040 {
5041 return false;
5042 }
5043
5044 // closing ] -> we are done
5045 if (get_token() == token_type::end_array)
5046 {
5047 if (JSON_UNLIKELY(not sax->end_array()))
5048 {
5049 return false;
5050 }
5051 break;
5052 }
5053
5054 // remember we are now inside an array
5055 states.push_back(true);
5056
5057 // parse values (no need to call get_token)
5058 continue;
5059 }
5060
5061 case token_type::value_float:
5062 {
5063 const auto res = m_lexer.get_number_float();
5064
5065 if (JSON_UNLIKELY(not std::isfinite(res)))
5066 {
5067 return sax->parse_error(m_lexer.get_position(),
5068 m_lexer.get_token_string(),
5069 out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
5070 }
5071 else
5072 {
5073 if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
5074 {
5075 return false;
5076 }
5077 break;
5078 }
5079 }
5080
5081 case token_type::literal_false:
5082 {
5083 if (JSON_UNLIKELY(not sax->boolean(false)))
5084 {
5085 return false;
5086 }
5087 break;
5088 }
5089
5090 case token_type::literal_null:
5091 {
5092 if (JSON_UNLIKELY(not sax->null()))
5093 {
5094 return false;
5095 }
5096 break;
5097 }
5098
5099 case token_type::literal_true:
5100 {
5101 if (JSON_UNLIKELY(not sax->boolean(true)))
5102 {
5103 return false;
5104 }
5105 break;
5106 }
5107
5108 case token_type::value_integer:
5109 {
5110 if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
5111 {
5112 return false;
5113 }
5114 break;
5115 }
5116
5117 case token_type::value_string:
5118 {
5119 if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
5120 {
5121 return false;
5122 }
5123 break;
5124 }
5125
5126 case token_type::value_unsigned:
5127 {
5128 if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
5129 {
5130 return false;
5131 }
5132 break;
5133 }
5134
5135 case token_type::parse_error:
5136 {
5137 // using "uninitialized" to avoid "expected" message
5138 return sax->parse_error(m_lexer.get_position(),
5139 m_lexer.get_token_string(),
5140 parse_error::create(101, m_lexer.get_position(),
5141 exception_message(token_type::uninitialized, "value")));
5142 }
5143
5144 default: // the last token was unexpected
5145 {
5146 return sax->parse_error(m_lexer.get_position(),
5147 m_lexer.get_token_string(),
5148 parse_error::create(101, m_lexer.get_position(),
5149 exception_message(token_type::literal_or_value, "value")));
5150 }
5151 }
5152 }
5153 else
5154 {
5155 skip_to_state_evaluation = false;
5156 }
5157
5158 // we reached this line after we successfully parsed a value
5159 if (states.empty())
5160 {
5161 // empty stack: we reached the end of the hierarchy: done
5162 return true;
5163 }
5164 else
5165 {
5166 if (states.back()) // array
5167 {
5168 // comma -> next value
5169 if (get_token() == token_type::value_separator)
5170 {
5171 // parse a new value
5172 get_token();
5173 continue;
5174 }
5175
5176 // closing ]
5177 if (JSON_LIKELY(last_token == token_type::end_array))
5178 {
5179 if (JSON_UNLIKELY(not sax->end_array()))
5180 {
5181 return false;
5182 }
5183
5184 // We are done with this array. Before we can parse a
5185 // new value, we need to evaluate the new state first.
5186 // By setting skip_to_state_evaluation to false, we
5187 // are effectively jumping to the beginning of this if.
5188 assert(not states.empty());
5189 states.pop_back();
5190 skip_to_state_evaluation = true;
5191 continue;
5192 }
5193 else
5194 {
5195 return sax->parse_error(m_lexer.get_position(),
5196 m_lexer.get_token_string(),
5197 parse_error::create(101, m_lexer.get_position(),
5198 exception_message(token_type::end_array, "array")));
5199 }
5200 }
5201 else // object
5202 {
5203 // comma -> next value
5204 if (get_token() == token_type::value_separator)
5205 {
5206 // parse key
5207 if (JSON_UNLIKELY(get_token() != token_type::value_string))
5208 {
5209 return sax->parse_error(m_lexer.get_position(),
5210 m_lexer.get_token_string(),
5211 parse_error::create(101, m_lexer.get_position(),
5212 exception_message(token_type::value_string, "object key")));
5213 }
5214 else
5215 {
5216 if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
5217 {
5218 return false;
5219 }
5220 }
5221
5222 // parse separator (:)
5223 if (JSON_UNLIKELY(get_token() != token_type::name_separator))
5224 {
5225 return sax->parse_error(m_lexer.get_position(),
5226 m_lexer.get_token_string(),
5227 parse_error::create(101, m_lexer.get_position(),
5228 exception_message(token_type::name_separator, "object separator")));
5229 }
5230
5231 // parse values
5232 get_token();
5233 continue;
5234 }
5235
5236 // closing }
5237 if (JSON_LIKELY(last_token == token_type::end_object))
5238 {
5239 if (JSON_UNLIKELY(not sax->end_object()))
5240 {
5241 return false;
5242 }
5243
5244 // We are done with this object. Before we can parse a
5245 // new value, we need to evaluate the new state first.
5246 // By setting skip_to_state_evaluation to false, we
5247 // are effectively jumping to the beginning of this if.
5248 assert(not states.empty());
5249 states.pop_back();
5250 skip_to_state_evaluation = true;
5251 continue;
5252 }
5253 else
5254 {
5255 return sax->parse_error(m_lexer.get_position(),
5256 m_lexer.get_token_string(),
5257 parse_error::create(101, m_lexer.get_position(),
5258 exception_message(token_type::end_object, "object")));
5259 }
5260 }
5261 }
5262 }
5263 }
5264
5265 /// get next token from lexer
5266 token_type get_token()
5267 {
5268 return (last_token = m_lexer.scan());
5269 }
5270
5271 std::string exception_message(const token_type expected, const std::string& context)
5272 {
5273 std::string error_msg = "syntax error ";
5274
5275 if (not context.empty())
5276 {
5277 error_msg += "while parsing " + context + " ";
5278 }
5279
5280 error_msg += "- ";
5281
5282 if (last_token == token_type::parse_error)
5283 {
5284 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
5285 m_lexer.get_token_string() + "'";
5286 }
5287 else
5288 {
5289 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
5290 }
5291
5292 if (expected != token_type::uninitialized)
5293 {
5294 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
5295 }
5296
5297 return error_msg;
5298 }
5299
5300 private:
5301 /// callback function
5302 const parser_callback_t callback = nullptr;
5303 /// the type of the last read token
5304 token_type last_token = token_type::uninitialized;
5305 /// the lexer
5306 lexer_t m_lexer;
5307 /// whether to throw exceptions in case of errors
5308 const bool allow_exceptions = true;
5309};
5310} // namespace detail
5311} // namespace nlohmann
5312
5313// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5314
5315
5316#include <cstddef> // ptrdiff_t
5317#include <limits> // numeric_limits
5318
5319namespace nlohmann
5320{
5321namespace detail
5322{
5323/*
5324@brief an iterator for primitive JSON types
5325
5326This class models an iterator for primitive JSON types (boolean, number,
5327string). It's only purpose is to allow the iterator/const_iterator classes
5328to "iterate" over primitive values. Internally, the iterator is modeled by
5329a `difference_type` variable. Value begin_value (`0`) models the begin,
5330end_value (`1`) models past the end.
5331*/
5332class primitive_iterator_t
5333{
5334 private:
5335 using difference_type = std::ptrdiff_t;
5336 static constexpr difference_type begin_value = 0;
5337 static constexpr difference_type end_value = begin_value + 1;
5338
5339 /// iterator as signed integer type
5340 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
5341
5342 public:
5343 constexpr difference_type get_value() const noexcept
5344 {
5345 return m_it;
5346 }
5347
5348 /// set iterator to a defined beginning
5349 void set_begin() noexcept
5350 {
5351 m_it = begin_value;
5352 }
5353
5354 /// set iterator to a defined past the end
5355 void set_end() noexcept
5356 {
5357 m_it = end_value;
5358 }
5359
5360 /// return whether the iterator can be dereferenced
5361 constexpr bool is_begin() const noexcept
5362 {
5363 return m_it == begin_value;
5364 }
5365
5366 /// return whether the iterator is at end
5367 constexpr bool is_end() const noexcept
5368 {
5369 return m_it == end_value;
5370 }
5371
5372 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5373 {
5374 return lhs.m_it == rhs.m_it;
5375 }
5376
5377 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5378 {
5379 return lhs.m_it < rhs.m_it;
5380 }
5381
5382 primitive_iterator_t operator+(difference_type n) noexcept
5383 {
5384 auto result = *this;
5385 result += n;
5386 return result;
5387 }
5388
5389 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5390 {
5391 return lhs.m_it - rhs.m_it;
5392 }
5393
5394 primitive_iterator_t& operator++() noexcept
5395 {
5396 ++m_it;
5397 return *this;
5398 }
5399
5400 primitive_iterator_t const operator++(int) noexcept
5401 {
5402 auto result = *this;
5403 ++m_it;
5404 return result;
5405 }
5406
5407 primitive_iterator_t& operator--() noexcept
5408 {
5409 --m_it;
5410 return *this;
5411 }
5412
5413 primitive_iterator_t const operator--(int) noexcept
5414 {
5415 auto result = *this;
5416 --m_it;
5417 return result;
5418 }
5419
5420 primitive_iterator_t& operator+=(difference_type n) noexcept
5421 {
5422 m_it += n;
5423 return *this;
5424 }
5425
5426 primitive_iterator_t& operator-=(difference_type n) noexcept
5427 {
5428 m_it -= n;
5429 return *this;
5430 }
5431};
5432} // namespace detail
5433} // namespace nlohmann
5434
5435// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5436
5437
5438// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5439
5440
5441namespace nlohmann
5442{
5443namespace detail
5444{
5445/*!
5446@brief an iterator value
5447
5448@note This structure could easily be a union, but MSVC currently does not allow
5449unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
5450*/
5451template<typename BasicJsonType> struct internal_iterator
5452{
5453 /// iterator for JSON objects
5454 typename BasicJsonType::object_t::iterator object_iterator {};
5455 /// iterator for JSON arrays
5456 typename BasicJsonType::array_t::iterator array_iterator {};
5457 /// generic iterator for all other types
5458 primitive_iterator_t primitive_iterator {};
5459};
5460} // namespace detail
5461} // namespace nlohmann
5462
5463// #include <nlohmann/detail/iterators/iter_impl.hpp>
5464
5465
5466#include <ciso646> // not
5467#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
5468#include <type_traits> // conditional, is_const, remove_const
5469
5470// #include <nlohmann/detail/exceptions.hpp>
5471
5472// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5473
5474// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5475
5476// #include <nlohmann/detail/macro_scope.hpp>
5477
5478// #include <nlohmann/detail/meta/cpp_future.hpp>
5479
5480// #include <nlohmann/detail/value_t.hpp>
5481
5482
5483namespace nlohmann
5484{
5485namespace detail
5486{
5487// forward declare, to be able to friend it later on
5488template<typename IteratorType> class iteration_proxy;
5489
5490/*!
5491@brief a template for a bidirectional iterator for the @ref basic_json class
5492
5493This class implements a both iterators (iterator and const_iterator) for the
5494@ref basic_json class.
5495
5496@note An iterator is called *initialized* when a pointer to a JSON value has
5497 been set (e.g., by a constructor or a copy assignment). If the iterator is
5498 default-constructed, it is *uninitialized* and most methods are undefined.
5499 **The library uses assertions to detect calls on uninitialized iterators.**
5500
5501@requirement The class satisfies the following concept requirements:
5502-
5503[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
5504 The iterator that can be moved can be moved in both directions (i.e.
5505 incremented and decremented).
5506
5507@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
5508 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
5509*/
5510template<typename BasicJsonType>
5511class iter_impl
5512{
5513 /// allow basic_json to access private members
5514 friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
5515 friend BasicJsonType;
5516 friend iteration_proxy<iter_impl>;
5517
5518 using object_t = typename BasicJsonType::object_t;
5519 using array_t = typename BasicJsonType::array_t;
5520 // make sure BasicJsonType is basic_json or const basic_json
5521 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
5522 "iter_impl only accepts (const) basic_json");
5523
5524 public:
5525
5526 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
5527 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
5528 /// A user-defined iterator should provide publicly accessible typedefs named
5529 /// iterator_category, value_type, difference_type, pointer, and reference.
5530 /// Note that value_type is required to be non-const, even for constant iterators.
5531 using iterator_category = std::bidirectional_iterator_tag;
5532
5533 /// the type of the values when the iterator is dereferenced
5534 using value_type = typename BasicJsonType::value_type;
5535 /// a type to represent differences between iterators
5536 using difference_type = typename BasicJsonType::difference_type;
5537 /// defines a pointer to the type iterated over (value_type)
5538 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
5539 typename BasicJsonType::const_pointer,
5540 typename BasicJsonType::pointer>::type;
5541 /// defines a reference to the type iterated over (value_type)
5542 using reference =
5543 typename std::conditional<std::is_const<BasicJsonType>::value,
5544 typename BasicJsonType::const_reference,
5545 typename BasicJsonType::reference>::type;
5546
5547 /// default constructor
5548 iter_impl() = default;
5549
5550 /*!
5551 @brief constructor for a given JSON instance
5552 @param[in] object pointer to a JSON object for this iterator
5553 @pre object != nullptr
5554 @post The iterator is initialized; i.e. `m_object != nullptr`.
5555 */
5556 explicit iter_impl(pointer object) noexcept : m_object(object)
5557 {
5558 assert(m_object != nullptr);
5559
5560 switch (m_object->m_type)
5561 {
5562 case value_t::object:
5563 {
5564 m_it.object_iterator = typename object_t::iterator();
5565 break;
5566 }
5567
5568 case value_t::array:
5569 {
5570 m_it.array_iterator = typename array_t::iterator();
5571 break;
5572 }
5573
5574 default:
5575 {
5576 m_it.primitive_iterator = primitive_iterator_t();
5577 break;
5578 }
5579 }
5580 }
5581
5582 /*!
5583 @note The conventional copy constructor and copy assignment are implicitly
5584 defined. Combined with the following converting constructor and
5585 assignment, they support: (1) copy from iterator to iterator, (2)
5586 copy from const iterator to const iterator, and (3) conversion from
5587 iterator to const iterator. However conversion from const iterator
5588 to iterator is not defined.
5589 */
5590
5591 /*!
5592 @brief converting constructor
5593 @param[in] other non-const iterator to copy from
5594 @note It is not checked whether @a other is initialized.
5595 */
5596 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5597 : m_object(other.m_object), m_it(other.m_it) {}
5598
5599 /*!
5600 @brief converting assignment
5601 @param[in,out] other non-const iterator to copy from
5602 @return const/non-const iterator
5603 @note It is not checked whether @a other is initialized.
5604 */
5605 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5606 {
5607 m_object = other.m_object;
5608 m_it = other.m_it;
5609 return *this;
5610 }
5611
5612 private:
5613 /*!
5614 @brief set the iterator to the first value
5615 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5616 */
5617 void set_begin() noexcept
5618 {
5619 assert(m_object != nullptr);
5620
5621 switch (m_object->m_type)
5622 {
5623 case value_t::object:
5624 {
5625 m_it.object_iterator = m_object->m_value.object->begin();
5626 break;
5627 }
5628
5629 case value_t::array:
5630 {
5631 m_it.array_iterator = m_object->m_value.array->begin();
5632 break;
5633 }
5634
5635 case value_t::null:
5636 {
5637 // set to end so begin()==end() is true: null is empty
5638 m_it.primitive_iterator.set_end();
5639 break;
5640 }
5641
5642 default:
5643 {
5644 m_it.primitive_iterator.set_begin();
5645 break;
5646 }
5647 }
5648 }
5649
5650 /*!
5651 @brief set the iterator past the last value
5652 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5653 */
5654 void set_end() noexcept
5655 {
5656 assert(m_object != nullptr);
5657
5658 switch (m_object->m_type)
5659 {
5660 case value_t::object:
5661 {
5662 m_it.object_iterator = m_object->m_value.object->end();
5663 break;
5664 }
5665
5666 case value_t::array:
5667 {
5668 m_it.array_iterator = m_object->m_value.array->end();
5669 break;
5670 }
5671
5672 default:
5673 {
5674 m_it.primitive_iterator.set_end();
5675 break;
5676 }
5677 }
5678 }
5679
5680 public:
5681 /*!
5682 @brief return a reference to the value pointed to by the iterator
5683 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5684 */
5685 reference operator*() const
5686 {
5687 assert(m_object != nullptr);
5688
5689 switch (m_object->m_type)
5690 {
5691 case value_t::object:
5692 {
5693 assert(m_it.object_iterator != m_object->m_value.object->end());
5694 return m_it.object_iterator->second;
5695 }
5696
5697 case value_t::array:
5698 {
5699 assert(m_it.array_iterator != m_object->m_value.array->end());
5700 return *m_it.array_iterator;
5701 }
5702
5703 case value_t::null:
5704 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5705
5706 default:
5707 {
5708 if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
5709 {
5710 return *m_object;
5711 }
5712
5713 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5714 }
5715 }
5716 }
5717
5718 /*!
5719 @brief dereference the iterator
5720 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5721 */
5722 pointer operator->() const
5723 {
5724 assert(m_object != nullptr);
5725
5726 switch (m_object->m_type)
5727 {
5728 case value_t::object:
5729 {
5730 assert(m_it.object_iterator != m_object->m_value.object->end());
5731 return &(m_it.object_iterator->second);
5732 }
5733
5734 case value_t::array:
5735 {
5736 assert(m_it.array_iterator != m_object->m_value.array->end());
5737 return &*m_it.array_iterator;
5738 }
5739
5740 default:
5741 {
5742 if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
5743 {
5744 return m_object;
5745 }
5746
5747 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5748 }
5749 }
5750 }
5751
5752 /*!
5753 @brief post-increment (it++)
5754 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5755 */
5756 iter_impl const operator++(int)
5757 {
5758 auto result = *this;
5759 ++(*this);
5760 return result;
5761 }
5762
5763 /*!
5764 @brief pre-increment (++it)
5765 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5766 */
5767 iter_impl& operator++()
5768 {
5769 assert(m_object != nullptr);
5770
5771 switch (m_object->m_type)
5772 {
5773 case value_t::object:
5774 {
5775 std::advance(m_it.object_iterator, 1);
5776 break;
5777 }
5778
5779 case value_t::array:
5780 {
5781 std::advance(m_it.array_iterator, 1);
5782 break;
5783 }
5784
5785 default:
5786 {
5787 ++m_it.primitive_iterator;
5788 break;
5789 }
5790 }
5791
5792 return *this;
5793 }
5794
5795 /*!
5796 @brief post-decrement (it--)
5797 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5798 */
5799 iter_impl const operator--(int)
5800 {
5801 auto result = *this;
5802 --(*this);
5803 return result;
5804 }
5805
5806 /*!
5807 @brief pre-decrement (--it)
5808 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5809 */
5810 iter_impl& operator--()
5811 {
5812 assert(m_object != nullptr);
5813
5814 switch (m_object->m_type)
5815 {
5816 case value_t::object:
5817 {
5818 std::advance(m_it.object_iterator, -1);
5819 break;
5820 }
5821
5822 case value_t::array:
5823 {
5824 std::advance(m_it.array_iterator, -1);
5825 break;
5826 }
5827
5828 default:
5829 {
5830 --m_it.primitive_iterator;
5831 break;
5832 }
5833 }
5834
5835 return *this;
5836 }
5837
5838 /*!
5839 @brief comparison: equal
5840 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5841 */
5842 bool operator==(const iter_impl& other) const
5843 {
5844 // if objects are not the same, the comparison is undefined
5845 if (JSON_UNLIKELY(m_object != other.m_object))
5846 {
5847 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
5848 }
5849
5850 assert(m_object != nullptr);
5851
5852 switch (m_object->m_type)
5853 {
5854 case value_t::object:
5855 return (m_it.object_iterator == other.m_it.object_iterator);
5856
5857 case value_t::array:
5858 return (m_it.array_iterator == other.m_it.array_iterator);
5859
5860 default:
5861 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5862 }
5863 }
5864
5865 /*!
5866 @brief comparison: not equal
5867 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5868 */
5869 bool operator!=(const iter_impl& other) const
5870 {
5871 return not operator==(other);
5872 }
5873
5874 /*!
5875 @brief comparison: smaller
5876 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5877 */
5878 bool operator<(const iter_impl& other) const
5879 {
5880 // if objects are not the same, the comparison is undefined
5881 if (JSON_UNLIKELY(m_object != other.m_object))
5882 {
5883 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
5884 }
5885
5886 assert(m_object != nullptr);
5887
5888 switch (m_object->m_type)
5889 {
5890 case value_t::object:
5891 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
5892
5893 case value_t::array:
5894 return (m_it.array_iterator < other.m_it.array_iterator);
5895
5896 default:
5897 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
5898 }
5899 }
5900
5901 /*!
5902 @brief comparison: less than or equal
5903 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5904 */
5905 bool operator<=(const iter_impl& other) const
5906 {
5907 return not other.operator < (*this);
5908 }
5909
5910 /*!
5911 @brief comparison: greater than
5912 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5913 */
5914 bool operator>(const iter_impl& other) const
5915 {
5916 return not operator<=(other);
5917 }
5918
5919 /*!
5920 @brief comparison: greater than or equal
5921 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5922 */
5923 bool operator>=(const iter_impl& other) const
5924 {
5925 return not operator<(other);
5926 }
5927
5928 /*!
5929 @brief add to iterator
5930 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5931 */
5932 iter_impl& operator+=(difference_type i)
5933 {
5934 assert(m_object != nullptr);
5935
5936 switch (m_object->m_type)
5937 {
5938 case value_t::object:
5939 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
5940
5941 case value_t::array:
5942 {
5943 std::advance(m_it.array_iterator, i);
5944 break;
5945 }
5946
5947 default:
5948 {
5949 m_it.primitive_iterator += i;
5950 break;
5951 }
5952 }
5953
5954 return *this;
5955 }
5956
5957 /*!
5958 @brief subtract from iterator
5959 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5960 */
5961 iter_impl& operator-=(difference_type i)
5962 {
5963 return operator+=(-i);
5964 }
5965
5966 /*!
5967 @brief add to iterator
5968 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5969 */
5970 iter_impl operator+(difference_type i) const
5971 {
5972 auto result = *this;
5973 result += i;
5974 return result;
5975 }
5976
5977 /*!
5978 @brief addition of distance and iterator
5979 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5980 */
5981 friend iter_impl operator+(difference_type i, const iter_impl& it)
5982 {
5983 auto result = it;
5984 result += i;
5985 return result;
5986 }
5987
5988 /*!
5989 @brief subtract from iterator
5990 @pre The iterator is initialized; i.e. `m_object != nullptr`.
5991 */
5992 iter_impl operator-(difference_type i) const
5993 {
5994 auto result = *this;
5995 result -= i;
5996 return result;
5997 }
5998
5999 /*!
6000 @brief return difference
6001 @pre The iterator is initialized; i.e. `m_object != nullptr`.
6002 */
6003 difference_type operator-(const iter_impl& other) const
6004 {
6005 assert(m_object != nullptr);
6006
6007 switch (m_object->m_type)
6008 {
6009 case value_t::object:
6010 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
6011
6012 case value_t::array:
6013 return m_it.array_iterator - other.m_it.array_iterator;
6014
6015 default:
6016 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6017 }
6018 }
6019
6020 /*!
6021 @brief access to successor
6022 @pre The iterator is initialized; i.e. `m_object != nullptr`.
6023 */
6024 reference operator[](difference_type n) const
6025 {
6026 assert(m_object != nullptr);
6027
6028 switch (m_object->m_type)
6029 {
6030 case value_t::object:
6031 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
6032
6033 case value_t::array:
6034 return *std::next(m_it.array_iterator, n);
6035
6036 case value_t::null:
6037 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
6038
6039 default:
6040 {
6041 if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
6042 {
6043 return *m_object;
6044 }
6045
6046 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
6047 }
6048 }
6049 }
6050
6051 /*!
6052 @brief return the key of an object iterator
6053 @pre The iterator is initialized; i.e. `m_object != nullptr`.
6054 */
6055 const typename object_t::key_type& key() const
6056 {
6057 assert(m_object != nullptr);
6058
6059 if (JSON_LIKELY(m_object->is_object()))
6060 {
6061 return m_it.object_iterator->first;
6062 }
6063
6064 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
6065 }
6066
6067 /*!
6068 @brief return the value of an iterator
6069 @pre The iterator is initialized; i.e. `m_object != nullptr`.
6070 */
6071 reference value() const
6072 {
6073 return operator*();
6074 }
6075
6076 private:
6077 /// associated JSON instance
6078 pointer m_object = nullptr;
6079 /// the actual iterator of the associated instance
6080 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it;
6081};
6082} // namespace detail
6083} // namespace nlohmann
6084
6085// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
6086
6087// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
6088
6089
6090#include <cstddef> // ptrdiff_t
6091#include <iterator> // reverse_iterator
6092#include <utility> // declval
6093
6094namespace nlohmann
6095{
6096namespace detail
6097{
6098//////////////////////
6099// reverse_iterator //
6100//////////////////////
6101
6102/*!
6103@brief a template for a reverse iterator class
6104
6105@tparam Base the base iterator type to reverse. Valid types are @ref
6106iterator (to create @ref reverse_iterator) and @ref const_iterator (to
6107create @ref const_reverse_iterator).
6108
6109@requirement The class satisfies the following concept requirements:
6110-
6111[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
6112 The iterator that can be moved can be moved in both directions (i.e.
6113 incremented and decremented).
6114- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
6115 It is possible to write to the pointed-to element (only if @a Base is
6116 @ref iterator).
6117
6118@since version 1.0.0
6119*/
6120template<typename Base>
6121class json_reverse_iterator : public std::reverse_iterator<Base>
6122{
6123 public:
6124 using difference_type = std::ptrdiff_t;
6125 /// shortcut to the reverse iterator adapter
6126 using base_iterator = std::reverse_iterator<Base>;
6127 /// the reference type for the pointed-to element
6128 using reference = typename Base::reference;
6129
6130 /// create reverse iterator from iterator
6131 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
6132 : base_iterator(it) {}
6133
6134 /// create reverse iterator from base class
6135 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
6136
6137 /// post-increment (it++)
6138 json_reverse_iterator const operator++(int)
6139 {
6140 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
6141 }
6142
6143 /// pre-increment (++it)
6144 json_reverse_iterator& operator++()
6145 {
6146 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
6147 }
6148
6149 /// post-decrement (it--)
6150 json_reverse_iterator const operator--(int)
6151 {
6152 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
6153 }
6154
6155 /// pre-decrement (--it)
6156 json_reverse_iterator& operator--()
6157 {
6158 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
6159 }
6160
6161 /// add to iterator
6162 json_reverse_iterator& operator+=(difference_type i)
6163 {
6164 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
6165 }
6166
6167 /// add to iterator
6168 json_reverse_iterator operator+(difference_type i) const
6169 {
6170 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
6171 }
6172
6173 /// subtract from iterator
6174 json_reverse_iterator operator-(difference_type i) const
6175 {
6176 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
6177 }
6178
6179 /// return difference
6180 difference_type operator-(const json_reverse_iterator& other) const
6181 {
6182 return base_iterator(*this) - base_iterator(other);
6183 }
6184
6185 /// access to successor
6186 reference operator[](difference_type n) const
6187 {
6188 return *(this->operator+(n));
6189 }
6190
6191 /// return the key of an object iterator
6192 auto key() const -> decltype(std::declval<Base>().key())
6193 {
6194 auto it = --this->base();
6195 return it.key();
6196 }
6197
6198 /// return the value of an iterator
6199 reference value() const
6200 {
6201 auto it = --this->base();
6202 return it.operator * ();
6203 }
6204};
6205} // namespace detail
6206} // namespace nlohmann
6207
6208// #include <nlohmann/detail/output/output_adapters.hpp>
6209
6210
6211#include <algorithm> // copy
6212#include <cstddef> // size_t
6213#include <ios> // streamsize
6214#include <iterator> // back_inserter
6215#include <memory> // shared_ptr, make_shared
6216#include <ostream> // basic_ostream
6217#include <string> // basic_string
6218#include <vector> // vector
6219
6220namespace nlohmann
6221{
6222namespace detail
6223{
6224/// abstract output adapter interface
6225template<typename CharType> struct output_adapter_protocol
6226{
6227 virtual void write_character(CharType c) = 0;
6228 virtual void write_characters(const CharType* s, std::size_t length) = 0;
6229 virtual ~output_adapter_protocol() = default;
6230};
6231
6232/// a type to simplify interfaces
6233template<typename CharType>
6234using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
6235
6236/// output adapter for byte vectors
6237template<typename CharType>
6238class output_vector_adapter : public output_adapter_protocol<CharType>
6239{
6240 public:
6241 explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
6242 : v(vec)
6243 {}
6244
6245 void write_character(CharType c) override
6246 {
6247 v.push_back(c);
6248 }
6249
6250 void write_characters(const CharType* s, std::size_t length) override
6251 {
6252 std::copy(s, s + length, std::back_inserter(v));
6253 }
6254
6255 private:
6256 std::vector<CharType>& v;
6257};
6258
6259/// output adapter for output streams
6260template<typename CharType>
6261class output_stream_adapter : public output_adapter_protocol<CharType>
6262{
6263 public:
6264 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
6265 : stream(s)
6266 {}
6267
6268 void write_character(CharType c) override
6269 {
6270 stream.put(c);
6271 }
6272
6273 void write_characters(const CharType* s, std::size_t length) override
6274 {
6275 stream.write(s, static_cast<std::streamsize>(length));
6276 }
6277
6278 private:
6279 std::basic_ostream<CharType>& stream;
6280};
6281
6282/// output adapter for basic_string
6283template<typename CharType, typename StringType = std::basic_string<CharType>>
6284class output_string_adapter : public output_adapter_protocol<CharType>
6285{
6286 public:
6287 explicit output_string_adapter(StringType& s) noexcept
6288 : str(s)
6289 {}
6290
6291 void write_character(CharType c) override
6292 {
6293 str.push_back(c);
6294 }
6295
6296 void write_characters(const CharType* s, std::size_t length) override
6297 {
6298 str.append(s, length);
6299 }
6300
6301 private:
6302 StringType& str;
6303};
6304
6305template<typename CharType, typename StringType = std::basic_string<CharType>>
6306class output_adapter
6307{
6308 public:
6309 output_adapter(std::vector<CharType>& vec)
6310 : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
6311
6312 output_adapter(std::basic_ostream<CharType>& s)
6313 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
6314
6315 output_adapter(StringType& s)
6316 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
6317
6318 operator output_adapter_t<CharType>()
6319 {
6320 return oa;
6321 }
6322
6323 private:
6324 output_adapter_t<CharType> oa = nullptr;
6325};
6326} // namespace detail
6327} // namespace nlohmann
6328
6329// #include <nlohmann/detail/input/binary_reader.hpp>
6330
6331
6332#include <algorithm> // generate_n
6333#include <array> // array
6334#include <cassert> // assert
6335#include <cmath> // ldexp
6336#include <cstddef> // size_t
6337#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6338#include <cstdio> // snprintf
6339#include <cstring> // memcpy
6340#include <iterator> // back_inserter
6341#include <limits> // numeric_limits
6342#include <string> // char_traits, string
6343#include <utility> // make_pair, move
6344
6345// #include <nlohmann/detail/input/input_adapters.hpp>
6346
6347// #include <nlohmann/detail/input/json_sax.hpp>
6348
6349// #include <nlohmann/detail/exceptions.hpp>
6350
6351// #include <nlohmann/detail/macro_scope.hpp>
6352
6353// #include <nlohmann/detail/meta/is_sax.hpp>
6354
6355// #include <nlohmann/detail/value_t.hpp>
6356
6357
6358namespace nlohmann
6359{
6360namespace detail
6361{
6362///////////////////
6363// binary reader //
6364///////////////////
6365
6366/*!
6367@brief deserialization of CBOR, MessagePack, and UBJSON values
6368*/
6369template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
6370class binary_reader
6371{
6372 using number_integer_t = typename BasicJsonType::number_integer_t;
6373 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6374 using number_float_t = typename BasicJsonType::number_float_t;
6375 using string_t = typename BasicJsonType::string_t;
6376 using json_sax_t = SAX;
6377
6378 public:
6379 /*!
6380 @brief create a binary reader
6381
6382 @param[in] adapter input adapter to read from
6383 */
6384 explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
6385 {
6386 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
6387 assert(ia);
6388 }
6389
6390 /*!
6391 @param[in] format the binary format to parse
6392 @param[in] sax_ a SAX event processor
6393 @param[in] strict whether to expect the input to be consumed completed
6394
6395 @return
6396 */
6397 bool sax_parse(const input_format_t format,
6398 json_sax_t* sax_,
6399 const bool strict = true)
6400 {
6401 sax = sax_;
6402 bool result = false;
6403
6404 switch (format)
6405 {
6406 case input_format_t::bson:
6407 result = parse_bson_internal();
6408 break;
6409
6410 case input_format_t::cbor:
6411 result = parse_cbor_internal();
6412 break;
6413
6414 case input_format_t::msgpack:
6415 result = parse_msgpack_internal();
6416 break;
6417
6418 case input_format_t::ubjson:
6419 result = parse_ubjson_internal();
6420 break;
6421
6422 // LCOV_EXCL_START
6423 default:
6424 assert(false);
6425 // LCOV_EXCL_STOP
6426 }
6427
6428 // strict mode: next byte must be EOF
6429 if (result and strict)
6430 {
6431 if (format == input_format_t::ubjson)
6432 {
6433 get_ignore_noop();
6434 }
6435 else
6436 {
6437 get();
6438 }
6439
6440 if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
6441 {
6442 return sax->parse_error(chars_read, get_token_string(),
6443 parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
6444 }
6445 }
6446
6447 return result;
6448 }
6449
6450 /*!
6451 @brief determine system byte order
6452
6453 @return true if and only if system's byte order is little endian
6454
6455 @note from http://stackoverflow.com/a/1001328/266378
6456 */
6457 static constexpr bool little_endianess(int num = 1) noexcept
6458 {
6459 return (*reinterpret_cast<char*>(&num) == 1);
6460 }
6461
6462 private:
6463 //////////
6464 // BSON //
6465 //////////
6466
6467 /*!
6468 @brief Reads in a BSON-object and passes it to the SAX-parser.
6469 @return whether a valid BSON-value was passed to the SAX parser
6470 */
6471 bool parse_bson_internal()
6472 {
6473 std::int32_t document_size;
6474 get_number<std::int32_t, true>(input_format_t::bson, document_size);
6475
6476 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
6477 {
6478 return false;
6479 }
6480
6481 if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/false)))
6482 {
6483 return false;
6484 }
6485
6486 return sax->end_object();
6487 }
6488
6489 /*!
6490 @brief Parses a C-style string from the BSON input.
6491 @param[in, out] result A reference to the string variable where the read
6492 string is to be stored.
6493 @return `true` if the \x00-byte indicating the end of the string was
6494 encountered before the EOF; false` indicates an unexpected EOF.
6495 */
6496 bool get_bson_cstr(string_t& result)
6497 {
6498 auto out = std::back_inserter(result);
6499 while (true)
6500 {
6501 get();
6502 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring")))
6503 {
6504 return false;
6505 }
6506 if (current == 0x00)
6507 {
6508 return true;
6509 }
6510 *out++ = static_cast<char>(current);
6511 }
6512
6513 return true;
6514 }
6515
6516 /*!
6517 @brief Parses a zero-terminated string of length @a len from the BSON
6518 input.
6519 @param[in] len The length (including the zero-byte at the end) of the
6520 string to be read.
6521 @param[in, out] result A reference to the string variable where the read
6522 string is to be stored.
6523 @tparam NumberType The type of the length @a len
6524 @pre len >= 1
6525 @return `true` if the string was successfully parsed
6526 */
6527 template<typename NumberType>
6528 bool get_bson_string(const NumberType len, string_t& result)
6529 {
6530 if (JSON_UNLIKELY(len < 1))
6531 {
6532 auto last_token = get_token_string();
6533 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string")));
6534 }
6535
6536 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) and get() != std::char_traits<char>::eof();
6537 }
6538
6539 /*!
6540 @brief Read a BSON document element of the given @a element_type.
6541 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
6542 @param[in] element_type_parse_position The position in the input stream,
6543 where the `element_type` was read.
6544 @warning Not all BSON element types are supported yet. An unsupported
6545 @a element_type will give rise to a parse_error.114:
6546 Unsupported BSON record type 0x...
6547 @return whether a valid BSON-object/array was passed to the SAX parser
6548 */
6549 bool parse_bson_element_internal(const int element_type,
6550 const std::size_t element_type_parse_position)
6551 {
6552 switch (element_type)
6553 {
6554 case 0x01: // double
6555 {
6556 double number;
6557 return get_number<double, true>(input_format_t::bson, number) and sax->number_float(static_cast<number_float_t>(number), "");
6558 }
6559
6560 case 0x02: // string
6561 {
6562 std::int32_t len;
6563 string_t value;
6564 return get_number<std::int32_t, true>(input_format_t::bson, len) and get_bson_string(len, value) and sax->string(value);
6565 }
6566
6567 case 0x03: // object
6568 {
6569 return parse_bson_internal();
6570 }
6571
6572 case 0x04: // array
6573 {
6574 return parse_bson_array();
6575 }
6576
6577 case 0x08: // boolean
6578 {
6579 return sax->boolean(static_cast<bool>(get()));
6580 }
6581
6582 case 0x0A: // null
6583 {
6584 return sax->null();
6585 }
6586
6587 case 0x10: // int32
6588 {
6589 std::int32_t value;
6590 return get_number<std::int32_t, true>(input_format_t::bson, value) and sax->number_integer(value);
6591 }
6592
6593 case 0x12: // int64
6594 {
6595 std::int64_t value;
6596 return get_number<std::int64_t, true>(input_format_t::bson, value) and sax->number_integer(value);
6597 }
6598
6599 default: // anything else not supported (yet)
6600 {
6601 char cr[3];
6602 snprintf(cr, sizeof(cr), "%.2hhX", static_cast<unsigned char>(element_type));
6603 return sax->parse_error(element_type_parse_position, std::string(cr), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr)));
6604 }
6605 }
6606 }
6607
6608 /*!
6609 @brief Read a BSON element list (as specified in the BSON-spec)
6610
6611 The same binary layout is used for objects and arrays, hence it must be
6612 indicated with the argument @a is_array which one is expected
6613 (true --> array, false --> object).
6614
6615 @param[in] is_array Determines if the element list being read is to be
6616 treated as an object (@a is_array == false), or as an
6617 array (@a is_array == true).
6618 @return whether a valid BSON-object/array was passed to the SAX parser
6619 */
6620 bool parse_bson_element_list(const bool is_array)
6621 {
6622 string_t key;
6623 while (int element_type = get())
6624 {
6625 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list")))
6626 {
6627 return false;
6628 }
6629
6630 const std::size_t element_type_parse_position = chars_read;
6631 if (JSON_UNLIKELY(not get_bson_cstr(key)))
6632 {
6633 return false;
6634 }
6635
6636 if (not is_array)
6637 {
6638 sax->key(key);
6639 }
6640
6641 if (JSON_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
6642 {
6643 return false;
6644 }
6645
6646 // get_bson_cstr only appends
6647 key.clear();
6648 }
6649
6650 return true;
6651 }
6652
6653 /*!
6654 @brief Reads an array from the BSON input and passes it to the SAX-parser.
6655 @return whether a valid BSON-array was passed to the SAX parser
6656 */
6657 bool parse_bson_array()
6658 {
6659 std::int32_t document_size;
6660 get_number<std::int32_t, true>(input_format_t::bson, document_size);
6661
6662 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
6663 {
6664 return false;
6665 }
6666
6667 if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/true)))
6668 {
6669 return false;
6670 }
6671
6672 return sax->end_array();
6673 }
6674
6675 //////////
6676 // CBOR //
6677 //////////
6678
6679 /*!
6680 @param[in] get_char whether a new character should be retrieved from the
6681 input (true, default) or whether the last read
6682 character should be considered instead
6683
6684 @return whether a valid CBOR value was passed to the SAX parser
6685 */
6686 bool parse_cbor_internal(const bool get_char = true)
6687 {
6688 switch (get_char ? get() : current)
6689 {
6690 // EOF
6691 case std::char_traits<char>::eof():
6692 return unexpect_eof(input_format_t::cbor, "value");
6693
6694 // Integer 0x00..0x17 (0..23)
6695 case 0x00:
6696 case 0x01:
6697 case 0x02:
6698 case 0x03:
6699 case 0x04:
6700 case 0x05:
6701 case 0x06:
6702 case 0x07:
6703 case 0x08:
6704 case 0x09:
6705 case 0x0A:
6706 case 0x0B:
6707 case 0x0C:
6708 case 0x0D:
6709 case 0x0E:
6710 case 0x0F:
6711 case 0x10:
6712 case 0x11:
6713 case 0x12:
6714 case 0x13:
6715 case 0x14:
6716 case 0x15:
6717 case 0x16:
6718 case 0x17:
6719 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
6720
6721 case 0x18: // Unsigned integer (one-byte uint8_t follows)
6722 {
6723 uint8_t number;
6724 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6725 }
6726
6727 case 0x19: // Unsigned integer (two-byte uint16_t follows)
6728 {
6729 uint16_t number;
6730 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6731 }
6732
6733 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
6734 {
6735 uint32_t number;
6736 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6737 }
6738
6739 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
6740 {
6741 uint64_t number;
6742 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6743 }
6744
6745 // Negative integer -1-0x00..-1-0x17 (-1..-24)
6746 case 0x20:
6747 case 0x21:
6748 case 0x22:
6749 case 0x23:
6750 case 0x24:
6751 case 0x25:
6752 case 0x26:
6753 case 0x27:
6754 case 0x28:
6755 case 0x29:
6756 case 0x2A:
6757 case 0x2B:
6758 case 0x2C:
6759 case 0x2D:
6760 case 0x2E:
6761 case 0x2F:
6762 case 0x30:
6763 case 0x31:
6764 case 0x32:
6765 case 0x33:
6766 case 0x34:
6767 case 0x35:
6768 case 0x36:
6769 case 0x37:
6770 return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
6771
6772 case 0x38: // Negative integer (one-byte uint8_t follows)
6773 {
6774 uint8_t number;
6775 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6776 }
6777
6778 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
6779 {
6780 uint16_t number;
6781 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6782 }
6783
6784 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
6785 {
6786 uint32_t number;
6787 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6788 }
6789
6790 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
6791 {
6792 uint64_t number;
6793 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
6794 - static_cast<number_integer_t>(number));
6795 }
6796
6797 // UTF-8 string (0x00..0x17 bytes follow)
6798 case 0x60:
6799 case 0x61:
6800 case 0x62:
6801 case 0x63:
6802 case 0x64:
6803 case 0x65:
6804 case 0x66:
6805 case 0x67:
6806 case 0x68:
6807 case 0x69:
6808 case 0x6A:
6809 case 0x6B:
6810 case 0x6C:
6811 case 0x6D:
6812 case 0x6E:
6813 case 0x6F:
6814 case 0x70:
6815 case 0x71:
6816 case 0x72:
6817 case 0x73:
6818 case 0x74:
6819 case 0x75:
6820 case 0x76:
6821 case 0x77:
6822 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
6823 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
6824 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
6825 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
6826 case 0x7F: // UTF-8 string (indefinite length)
6827 {
6828 string_t s;
6829 return get_cbor_string(s) and sax->string(s);
6830 }
6831
6832 // array (0x00..0x17 data items follow)
6833 case 0x80:
6834 case 0x81:
6835 case 0x82:
6836 case 0x83:
6837 case 0x84:
6838 case 0x85:
6839 case 0x86:
6840 case 0x87:
6841 case 0x88:
6842 case 0x89:
6843 case 0x8A:
6844 case 0x8B:
6845 case 0x8C:
6846 case 0x8D:
6847 case 0x8E:
6848 case 0x8F:
6849 case 0x90:
6850 case 0x91:
6851 case 0x92:
6852 case 0x93:
6853 case 0x94:
6854 case 0x95:
6855 case 0x96:
6856 case 0x97:
6857 return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
6858
6859 case 0x98: // array (one-byte uint8_t for n follows)
6860 {
6861 uint8_t len;
6862 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
6863 }
6864
6865 case 0x99: // array (two-byte uint16_t for n follow)
6866 {
6867 uint16_t len;
6868 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
6869 }
6870
6871 case 0x9A: // array (four-byte uint32_t for n follow)
6872 {
6873 uint32_t len;
6874 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
6875 }
6876
6877 case 0x9B: // array (eight-byte uint64_t for n follow)
6878 {
6879 uint64_t len;
6880 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
6881 }
6882
6883 case 0x9F: // array (indefinite length)
6884 return get_cbor_array(std::size_t(-1));
6885
6886 // map (0x00..0x17 pairs of data items follow)
6887 case 0xA0:
6888 case 0xA1:
6889 case 0xA2:
6890 case 0xA3:
6891 case 0xA4:
6892 case 0xA5:
6893 case 0xA6:
6894 case 0xA7:
6895 case 0xA8:
6896 case 0xA9:
6897 case 0xAA:
6898 case 0xAB:
6899 case 0xAC:
6900 case 0xAD:
6901 case 0xAE:
6902 case 0xAF:
6903 case 0xB0:
6904 case 0xB1:
6905 case 0xB2:
6906 case 0xB3:
6907 case 0xB4:
6908 case 0xB5:
6909 case 0xB6:
6910 case 0xB7:
6911 return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
6912
6913 case 0xB8: // map (one-byte uint8_t for n follows)
6914 {
6915 uint8_t len;
6916 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
6917 }
6918
6919 case 0xB9: // map (two-byte uint16_t for n follow)
6920 {
6921 uint16_t len;
6922 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
6923 }
6924
6925 case 0xBA: // map (four-byte uint32_t for n follow)
6926 {
6927 uint32_t len;
6928 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
6929 }
6930
6931 case 0xBB: // map (eight-byte uint64_t for n follow)
6932 {
6933 uint64_t len;
6934 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
6935 }
6936
6937 case 0xBF: // map (indefinite length)
6938 return get_cbor_object(std::size_t(-1));
6939
6940 case 0xF4: // false
6941 return sax->boolean(false);
6942
6943 case 0xF5: // true
6944 return sax->boolean(true);
6945
6946 case 0xF6: // null
6947 return sax->null();
6948
6949 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
6950 {
6951 const int byte1_raw = get();
6952 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
6953 {
6954 return false;
6955 }
6956 const int byte2_raw = get();
6957 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
6958 {
6959 return false;
6960 }
6961
6962 const auto byte1 = static_cast<unsigned char>(byte1_raw);
6963 const auto byte2 = static_cast<unsigned char>(byte2_raw);
6964
6965 // code from RFC 7049, Appendix D, Figure 3:
6966 // As half-precision floating-point numbers were only added
6967 // to IEEE 754 in 2008, today's programming platforms often
6968 // still only have limited support for them. It is very
6969 // easy to include at least decoding support for them even
6970 // without such support. An example of a small decoder for
6971 // half-precision floating-point numbers in the C language
6972 // is shown in Fig. 3.
6973 const int half = (byte1 << 8) + byte2;
6974 const double val = [&half]
6975 {
6976 const int exp = (half >> 10) & 0x1F;
6977 const int mant = half & 0x3FF;
6978 assert(0 <= exp and exp <= 32);
6979 assert(0 <= mant and mant <= 1024);
6980 switch (exp)
6981 {
6982 case 0:
6983 return std::ldexp(mant, -24);
6984 case 31:
6985 return (mant == 0)
6986 ? std::numeric_limits<double>::infinity()
6987 : std::numeric_limits<double>::quiet_NaN();
6988 default:
6989 return std::ldexp(mant + 1024, exp - 25);
6990 }
6991 }();
6992 return sax->number_float((half & 0x8000) != 0
6993 ? static_cast<number_float_t>(-val)
6994 : static_cast<number_float_t>(val), "");
6995 }
6996
6997 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
6998 {
6999 float number;
7000 return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
7001 }
7002
7003 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
7004 {
7005 double number;
7006 return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
7007 }
7008
7009 default: // anything else (0xFF is handled inside the other types)
7010 {
7011 auto last_token = get_token_string();
7012 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
7013 }
7014 }
7015 }
7016
7017 /*!
7018 @brief reads a CBOR string
7019
7020 This function first reads starting bytes to determine the expected
7021 string length and then copies this number of bytes into a string.
7022 Additionally, CBOR's strings with indefinite lengths are supported.
7023
7024 @param[out] result created string
7025
7026 @return whether string creation completed
7027 */
7028 bool get_cbor_string(string_t& result)
7029 {
7030 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "string")))
7031 {
7032 return false;
7033 }
7034
7035 switch (current)
7036 {
7037 // UTF-8 string (0x00..0x17 bytes follow)
7038 case 0x60:
7039 case 0x61:
7040 case 0x62:
7041 case 0x63:
7042 case 0x64:
7043 case 0x65:
7044 case 0x66:
7045 case 0x67:
7046 case 0x68:
7047 case 0x69:
7048 case 0x6A:
7049 case 0x6B:
7050 case 0x6C:
7051 case 0x6D:
7052 case 0x6E:
7053 case 0x6F:
7054 case 0x70:
7055 case 0x71:
7056 case 0x72:
7057 case 0x73:
7058 case 0x74:
7059 case 0x75:
7060 case 0x76:
7061 case 0x77:
7062 {
7063 return get_string(input_format_t::cbor, current & 0x1F, result);
7064 }
7065
7066 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
7067 {
7068 uint8_t len;
7069 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7070 }
7071
7072 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
7073 {
7074 uint16_t len;
7075 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7076 }
7077
7078 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
7079 {
7080 uint32_t len;
7081 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7082 }
7083
7084 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
7085 {
7086 uint64_t len;
7087 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7088 }
7089
7090 case 0x7F: // UTF-8 string (indefinite length)
7091 {
7092 while (get() != 0xFF)
7093 {
7094 string_t chunk;
7095 if (not get_cbor_string(chunk))
7096 {
7097 return false;
7098 }
7099 result.append(chunk);
7100 }
7101 return true;
7102 }
7103
7104 default:
7105 {
7106 auto last_token = get_token_string();
7107 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string")));
7108 }
7109 }
7110 }
7111
7112 /*!
7113 @param[in] len the length of the array or std::size_t(-1) for an
7114 array of indefinite size
7115 @return whether array creation completed
7116 */
7117 bool get_cbor_array(const std::size_t len)
7118 {
7119 if (JSON_UNLIKELY(not sax->start_array(len)))
7120 {
7121 return false;
7122 }
7123
7124 if (len != std::size_t(-1))
7125 {
7126 for (std::size_t i = 0; i < len; ++i)
7127 {
7128 if (JSON_UNLIKELY(not parse_cbor_internal()))
7129 {
7130 return false;
7131 }
7132 }
7133 }
7134 else
7135 {
7136 while (get() != 0xFF)
7137 {
7138 if (JSON_UNLIKELY(not parse_cbor_internal(false)))
7139 {
7140 return false;
7141 }
7142 }
7143 }
7144
7145 return sax->end_array();
7146 }
7147
7148 /*!
7149 @param[in] len the length of the object or std::size_t(-1) for an
7150 object of indefinite size
7151 @return whether object creation completed
7152 */
7153 bool get_cbor_object(const std::size_t len)
7154 {
7155 if (not JSON_UNLIKELY(sax->start_object(len)))
7156 {
7157 return false;
7158 }
7159
7160 string_t key;
7161 if (len != std::size_t(-1))
7162 {
7163 for (std::size_t i = 0; i < len; ++i)
7164 {
7165 get();
7166 if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7167 {
7168 return false;
7169 }
7170
7171 if (JSON_UNLIKELY(not parse_cbor_internal()))
7172 {
7173 return false;
7174 }
7175 key.clear();
7176 }
7177 }
7178 else
7179 {
7180 while (get() != 0xFF)
7181 {
7182 if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7183 {
7184 return false;
7185 }
7186
7187 if (JSON_UNLIKELY(not parse_cbor_internal()))
7188 {
7189 return false;
7190 }
7191 key.clear();
7192 }
7193 }
7194
7195 return sax->end_object();
7196 }
7197
7198 /////////////
7199 // MsgPack //
7200 /////////////
7201
7202 /*!
7203 @return whether a valid MessagePack value was passed to the SAX parser
7204 */
7205 bool parse_msgpack_internal()
7206 {
7207 switch (get())
7208 {
7209 // EOF
7210 case std::char_traits<char>::eof():
7211 return unexpect_eof(input_format_t::msgpack, "value");
7212
7213 // positive fixint
7214 case 0x00:
7215 case 0x01:
7216 case 0x02:
7217 case 0x03:
7218 case 0x04:
7219 case 0x05:
7220 case 0x06:
7221 case 0x07:
7222 case 0x08:
7223 case 0x09:
7224 case 0x0A:
7225 case 0x0B:
7226 case 0x0C:
7227 case 0x0D:
7228 case 0x0E:
7229 case 0x0F:
7230 case 0x10:
7231 case 0x11:
7232 case 0x12:
7233 case 0x13:
7234 case 0x14:
7235 case 0x15:
7236 case 0x16:
7237 case 0x17:
7238 case 0x18:
7239 case 0x19:
7240 case 0x1A:
7241 case 0x1B:
7242 case 0x1C:
7243 case 0x1D:
7244 case 0x1E:
7245 case 0x1F:
7246 case 0x20:
7247 case 0x21:
7248 case 0x22:
7249 case 0x23:
7250 case 0x24:
7251 case 0x25:
7252 case 0x26:
7253 case 0x27:
7254 case 0x28:
7255 case 0x29:
7256 case 0x2A:
7257 case 0x2B:
7258 case 0x2C:
7259 case 0x2D:
7260 case 0x2E:
7261 case 0x2F:
7262 case 0x30:
7263 case 0x31:
7264 case 0x32:
7265 case 0x33:
7266 case 0x34:
7267 case 0x35:
7268 case 0x36:
7269 case 0x37:
7270 case 0x38:
7271 case 0x39:
7272 case 0x3A:
7273 case 0x3B:
7274 case 0x3C:
7275 case 0x3D:
7276 case 0x3E:
7277 case 0x3F:
7278 case 0x40:
7279 case 0x41:
7280 case 0x42:
7281 case 0x43:
7282 case 0x44:
7283 case 0x45:
7284 case 0x46:
7285 case 0x47:
7286 case 0x48:
7287 case 0x49:
7288 case 0x4A:
7289 case 0x4B:
7290 case 0x4C:
7291 case 0x4D:
7292 case 0x4E:
7293 case 0x4F:
7294 case 0x50:
7295 case 0x51:
7296 case 0x52:
7297 case 0x53:
7298 case 0x54:
7299 case 0x55:
7300 case 0x56:
7301 case 0x57:
7302 case 0x58:
7303 case 0x59:
7304 case 0x5A:
7305 case 0x5B:
7306 case 0x5C:
7307 case 0x5D:
7308 case 0x5E:
7309 case 0x5F:
7310 case 0x60:
7311 case 0x61:
7312 case 0x62:
7313 case 0x63:
7314 case 0x64:
7315 case 0x65:
7316 case 0x66:
7317 case 0x67:
7318 case 0x68:
7319 case 0x69:
7320 case 0x6A:
7321 case 0x6B:
7322 case 0x6C:
7323 case 0x6D:
7324 case 0x6E:
7325 case 0x6F:
7326 case 0x70:
7327 case 0x71:
7328 case 0x72:
7329 case 0x73:
7330 case 0x74:
7331 case 0x75:
7332 case 0x76:
7333 case 0x77:
7334 case 0x78:
7335 case 0x79:
7336 case 0x7A:
7337 case 0x7B:
7338 case 0x7C:
7339 case 0x7D:
7340 case 0x7E:
7341 case 0x7F:
7342 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
7343
7344 // fixmap
7345 case 0x80:
7346 case 0x81:
7347 case 0x82:
7348 case 0x83:
7349 case 0x84:
7350 case 0x85:
7351 case 0x86:
7352 case 0x87:
7353 case 0x88:
7354 case 0x89:
7355 case 0x8A:
7356 case 0x8B:
7357 case 0x8C:
7358 case 0x8D:
7359 case 0x8E:
7360 case 0x8F:
7361 return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
7362
7363 // fixarray
7364 case 0x90:
7365 case 0x91:
7366 case 0x92:
7367 case 0x93:
7368 case 0x94:
7369 case 0x95:
7370 case 0x96:
7371 case 0x97:
7372 case 0x98:
7373 case 0x99:
7374 case 0x9A:
7375 case 0x9B:
7376 case 0x9C:
7377 case 0x9D:
7378 case 0x9E:
7379 case 0x9F:
7380 return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
7381
7382 // fixstr
7383 case 0xA0:
7384 case 0xA1:
7385 case 0xA2:
7386 case 0xA3:
7387 case 0xA4:
7388 case 0xA5:
7389 case 0xA6:
7390 case 0xA7:
7391 case 0xA8:
7392 case 0xA9:
7393 case 0xAA:
7394 case 0xAB:
7395 case 0xAC:
7396 case 0xAD:
7397 case 0xAE:
7398 case 0xAF:
7399 case 0xB0:
7400 case 0xB1:
7401 case 0xB2:
7402 case 0xB3:
7403 case 0xB4:
7404 case 0xB5:
7405 case 0xB6:
7406 case 0xB7:
7407 case 0xB8:
7408 case 0xB9:
7409 case 0xBA:
7410 case 0xBB:
7411 case 0xBC:
7412 case 0xBD:
7413 case 0xBE:
7414 case 0xBF:
7415 {
7416 string_t s;
7417 return get_msgpack_string(s) and sax->string(s);
7418 }
7419
7420 case 0xC0: // nil
7421 return sax->null();
7422
7423 case 0xC2: // false
7424 return sax->boolean(false);
7425
7426 case 0xC3: // true
7427 return sax->boolean(true);
7428
7429 case 0xCA: // float 32
7430 {
7431 float number;
7432 return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
7433 }
7434
7435 case 0xCB: // float 64
7436 {
7437 double number;
7438 return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
7439 }
7440
7441 case 0xCC: // uint 8
7442 {
7443 uint8_t number;
7444 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7445 }
7446
7447 case 0xCD: // uint 16
7448 {
7449 uint16_t number;
7450 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7451 }
7452
7453 case 0xCE: // uint 32
7454 {
7455 uint32_t number;
7456 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7457 }
7458
7459 case 0xCF: // uint 64
7460 {
7461 uint64_t number;
7462 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7463 }
7464
7465 case 0xD0: // int 8
7466 {
7467 int8_t number;
7468 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7469 }
7470
7471 case 0xD1: // int 16
7472 {
7473 int16_t number;
7474 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7475 }
7476
7477 case 0xD2: // int 32
7478 {
7479 int32_t number;
7480 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7481 }
7482
7483 case 0xD3: // int 64
7484 {
7485 int64_t number;
7486 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7487 }
7488
7489 case 0xD9: // str 8
7490 case 0xDA: // str 16
7491 case 0xDB: // str 32
7492 {
7493 string_t s;
7494 return get_msgpack_string(s) and sax->string(s);
7495 }
7496
7497 case 0xDC: // array 16
7498 {
7499 uint16_t len;
7500 return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
7501 }
7502
7503 case 0xDD: // array 32
7504 {
7505 uint32_t len;
7506 return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
7507 }
7508
7509 case 0xDE: // map 16
7510 {
7511 uint16_t len;
7512 return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
7513 }
7514
7515 case 0xDF: // map 32
7516 {
7517 uint32_t len;
7518 return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
7519 }
7520
7521 // negative fixint
7522 case 0xE0:
7523 case 0xE1:
7524 case 0xE2:
7525 case 0xE3:
7526 case 0xE4:
7527 case 0xE5:
7528 case 0xE6:
7529 case 0xE7:
7530 case 0xE8:
7531 case 0xE9:
7532 case 0xEA:
7533 case 0xEB:
7534 case 0xEC:
7535 case 0xED:
7536 case 0xEE:
7537 case 0xEF:
7538 case 0xF0:
7539 case 0xF1:
7540 case 0xF2:
7541 case 0xF3:
7542 case 0xF4:
7543 case 0xF5:
7544 case 0xF6:
7545 case 0xF7:
7546 case 0xF8:
7547 case 0xF9:
7548 case 0xFA:
7549 case 0xFB:
7550 case 0xFC:
7551 case 0xFD:
7552 case 0xFE:
7553 case 0xFF:
7554 return sax->number_integer(static_cast<int8_t>(current));
7555
7556 default: // anything else
7557 {
7558 auto last_token = get_token_string();
7559 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value")));
7560 }
7561 }
7562 }
7563
7564 /*!
7565 @brief reads a MessagePack string
7566
7567 This function first reads starting bytes to determine the expected
7568 string length and then copies this number of bytes into a string.
7569
7570 @param[out] result created string
7571
7572 @return whether string creation completed
7573 */
7574 bool get_msgpack_string(string_t& result)
7575 {
7576 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::msgpack, "string")))
7577 {
7578 return false;
7579 }
7580
7581 switch (current)
7582 {
7583 // fixstr
7584 case 0xA0:
7585 case 0xA1:
7586 case 0xA2:
7587 case 0xA3:
7588 case 0xA4:
7589 case 0xA5:
7590 case 0xA6:
7591 case 0xA7:
7592 case 0xA8:
7593 case 0xA9:
7594 case 0xAA:
7595 case 0xAB:
7596 case 0xAC:
7597 case 0xAD:
7598 case 0xAE:
7599 case 0xAF:
7600 case 0xB0:
7601 case 0xB1:
7602 case 0xB2:
7603 case 0xB3:
7604 case 0xB4:
7605 case 0xB5:
7606 case 0xB6:
7607 case 0xB7:
7608 case 0xB8:
7609 case 0xB9:
7610 case 0xBA:
7611 case 0xBB:
7612 case 0xBC:
7613 case 0xBD:
7614 case 0xBE:
7615 case 0xBF:
7616 {
7617 return get_string(input_format_t::msgpack, current & 0x1F, result);
7618 }
7619
7620 case 0xD9: // str 8
7621 {
7622 uint8_t len;
7623 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
7624 }
7625
7626 case 0xDA: // str 16
7627 {
7628 uint16_t len;
7629 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
7630 }
7631
7632 case 0xDB: // str 32
7633 {
7634 uint32_t len;
7635 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
7636 }
7637
7638 default:
7639 {
7640 auto last_token = get_token_string();
7641 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string")));
7642 }
7643 }
7644 }
7645
7646 /*!
7647 @param[in] len the length of the array
7648 @return whether array creation completed
7649 */
7650 bool get_msgpack_array(const std::size_t len)
7651 {
7652 if (JSON_UNLIKELY(not sax->start_array(len)))
7653 {
7654 return false;
7655 }
7656
7657 for (std::size_t i = 0; i < len; ++i)
7658 {
7659 if (JSON_UNLIKELY(not parse_msgpack_internal()))
7660 {
7661 return false;
7662 }
7663 }
7664
7665 return sax->end_array();
7666 }
7667
7668 /*!
7669 @param[in] len the length of the object
7670 @return whether object creation completed
7671 */
7672 bool get_msgpack_object(const std::size_t len)
7673 {
7674 if (JSON_UNLIKELY(not sax->start_object(len)))
7675 {
7676 return false;
7677 }
7678
7679 string_t key;
7680 for (std::size_t i = 0; i < len; ++i)
7681 {
7682 get();
7683 if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
7684 {
7685 return false;
7686 }
7687
7688 if (JSON_UNLIKELY(not parse_msgpack_internal()))
7689 {
7690 return false;
7691 }
7692 key.clear();
7693 }
7694
7695 return sax->end_object();
7696 }
7697
7698 ////////////
7699 // UBJSON //
7700 ////////////
7701
7702 /*!
7703 @param[in] get_char whether a new character should be retrieved from the
7704 input (true, default) or whether the last read
7705 character should be considered instead
7706
7707 @return whether a valid UBJSON value was passed to the SAX parser
7708 */
7709 bool parse_ubjson_internal(const bool get_char = true)
7710 {
7711 return get_ubjson_value(get_char ? get_ignore_noop() : current);
7712 }
7713
7714 /*!
7715 @brief reads a UBJSON string
7716
7717 This function is either called after reading the 'S' byte explicitly
7718 indicating a string, or in case of an object key where the 'S' byte can be
7719 left out.
7720
7721 @param[out] result created string
7722 @param[in] get_char whether a new character should be retrieved from the
7723 input (true, default) or whether the last read
7724 character should be considered instead
7725
7726 @return whether string creation completed
7727 */
7728 bool get_ubjson_string(string_t& result, const bool get_char = true)
7729 {
7730 if (get_char)
7731 {
7732 get(); // TODO: may we ignore N here?
7733 }
7734
7735 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
7736 {
7737 return false;
7738 }
7739
7740 switch (current)
7741 {
7742 case 'U':
7743 {
7744 uint8_t len;
7745 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7746 }
7747
7748 case 'i':
7749 {
7750 int8_t len;
7751 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7752 }
7753
7754 case 'I':
7755 {
7756 int16_t len;
7757 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7758 }
7759
7760 case 'l':
7761 {
7762 int32_t len;
7763 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7764 }
7765
7766 case 'L':
7767 {
7768 int64_t len;
7769 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7770 }
7771
7772 default:
7773 auto last_token = get_token_string();
7774 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string")));
7775 }
7776 }
7777
7778 /*!
7779 @param[out] result determined size
7780 @return whether size determination completed
7781 */
7782 bool get_ubjson_size_value(std::size_t& result)
7783 {
7784 switch (get_ignore_noop())
7785 {
7786 case 'U':
7787 {
7788 uint8_t number;
7789 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7790 {
7791 return false;
7792 }
7793 result = static_cast<std::size_t>(number);
7794 return true;
7795 }
7796
7797 case 'i':
7798 {
7799 int8_t number;
7800 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7801 {
7802 return false;
7803 }
7804 result = static_cast<std::size_t>(number);
7805 return true;
7806 }
7807
7808 case 'I':
7809 {
7810 int16_t number;
7811 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7812 {
7813 return false;
7814 }
7815 result = static_cast<std::size_t>(number);
7816 return true;
7817 }
7818
7819 case 'l':
7820 {
7821 int32_t number;
7822 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7823 {
7824 return false;
7825 }
7826 result = static_cast<std::size_t>(number);
7827 return true;
7828 }
7829
7830 case 'L':
7831 {
7832 int64_t number;
7833 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7834 {
7835 return false;
7836 }
7837 result = static_cast<std::size_t>(number);
7838 return true;
7839 }
7840
7841 default:
7842 {
7843 auto last_token = get_token_string();
7844 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size")));
7845 }
7846 }
7847 }
7848
7849 /*!
7850 @brief determine the type and size for a container
7851
7852 In the optimized UBJSON format, a type and a size can be provided to allow
7853 for a more compact representation.
7854
7855 @param[out] result pair of the size and the type
7856
7857 @return whether pair creation completed
7858 */
7859 bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
7860 {
7861 result.first = string_t::npos; // size
7862 result.second = 0; // type
7863
7864 get_ignore_noop();
7865
7866 if (current == '$')
7867 {
7868 result.second = get(); // must not ignore 'N', because 'N' maybe the type
7869 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "type")))
7870 {
7871 return false;
7872 }
7873
7874 get_ignore_noop();
7875 if (JSON_UNLIKELY(current != '#'))
7876 {
7877 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
7878 {
7879 return false;
7880 }
7881 auto last_token = get_token_string();
7882 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size")));
7883 }
7884
7885 return get_ubjson_size_value(result.first);
7886 }
7887 else if (current == '#')
7888 {
7889 return get_ubjson_size_value(result.first);
7890 }
7891 return true;
7892 }
7893
7894 /*!
7895 @param prefix the previously read or set type prefix
7896 @return whether value creation completed
7897 */
7898 bool get_ubjson_value(const int prefix)
7899 {
7900 switch (prefix)
7901 {
7902 case std::char_traits<char>::eof(): // EOF
7903 return unexpect_eof(input_format_t::ubjson, "value");
7904
7905 case 'T': // true
7906 return sax->boolean(true);
7907 case 'F': // false
7908 return sax->boolean(false);
7909
7910 case 'Z': // null
7911 return sax->null();
7912
7913 case 'U':
7914 {
7915 uint8_t number;
7916 return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
7917 }
7918
7919 case 'i':
7920 {
7921 int8_t number;
7922 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
7923 }
7924
7925 case 'I':
7926 {
7927 int16_t number;
7928 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
7929 }
7930
7931 case 'l':
7932 {
7933 int32_t number;
7934 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
7935 }
7936
7937 case 'L':
7938 {
7939 int64_t number;
7940 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
7941 }
7942
7943 case 'd':
7944 {
7945 float number;
7946 return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
7947 }
7948
7949 case 'D':
7950 {
7951 double number;
7952 return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
7953 }
7954
7955 case 'C': // char
7956 {
7957 get();
7958 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "char")))
7959 {
7960 return false;
7961 }
7962 if (JSON_UNLIKELY(current > 127))
7963 {
7964 auto last_token = get_token_string();
7965 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char")));
7966 }
7967 string_t s(1, static_cast<char>(current));
7968 return sax->string(s);
7969 }
7970
7971 case 'S': // string
7972 {
7973 string_t s;
7974 return get_ubjson_string(s) and sax->string(s);
7975 }
7976
7977 case '[': // array
7978 return get_ubjson_array();
7979
7980 case '{': // object
7981 return get_ubjson_object();
7982
7983 default: // anything else
7984 {
7985 auto last_token = get_token_string();
7986 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value")));
7987 }
7988 }
7989 }
7990
7991 /*!
7992 @return whether array creation completed
7993 */
7994 bool get_ubjson_array()
7995 {
7996 std::pair<std::size_t, int> size_and_type;
7997 if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
7998 {
7999 return false;
8000 }
8001
8002 if (size_and_type.first != string_t::npos)
8003 {
8004 if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
8005 {
8006 return false;
8007 }
8008
8009 if (size_and_type.second != 0)
8010 {
8011 if (size_and_type.second != 'N')
8012 {
8013 for (std::size_t i = 0; i < size_and_type.first; ++i)
8014 {
8015 if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
8016 {
8017 return false;
8018 }
8019 }
8020 }
8021 }
8022 else
8023 {
8024 for (std::size_t i = 0; i < size_and_type.first; ++i)
8025 {
8026 if (JSON_UNLIKELY(not parse_ubjson_internal()))
8027 {
8028 return false;
8029 }
8030 }
8031 }
8032 }
8033 else
8034 {
8035 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
8036 {
8037 return false;
8038 }
8039
8040 while (current != ']')
8041 {
8042 if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
8043 {
8044 return false;
8045 }
8046 get_ignore_noop();
8047 }
8048 }
8049
8050 return sax->end_array();
8051 }
8052
8053 /*!
8054 @return whether object creation completed
8055 */
8056 bool get_ubjson_object()
8057 {
8058 std::pair<std::size_t, int> size_and_type;
8059 if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
8060 {
8061 return false;
8062 }
8063
8064 string_t key;
8065 if (size_and_type.first != string_t::npos)
8066 {
8067 if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
8068 {
8069 return false;
8070 }
8071
8072 if (size_and_type.second != 0)
8073 {
8074 for (std::size_t i = 0; i < size_and_type.first; ++i)
8075 {
8076 if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
8077 {
8078 return false;
8079 }
8080 if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
8081 {
8082 return false;
8083 }
8084 key.clear();
8085 }
8086 }
8087 else
8088 {
8089 for (std::size_t i = 0; i < size_and_type.first; ++i)
8090 {
8091 if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
8092 {
8093 return false;
8094 }
8095 if (JSON_UNLIKELY(not parse_ubjson_internal()))
8096 {
8097 return false;
8098 }
8099 key.clear();
8100 }
8101 }
8102 }
8103 else
8104 {
8105 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
8106 {
8107 return false;
8108 }
8109
8110 while (current != '}')
8111 {
8112 if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
8113 {
8114 return false;
8115 }
8116 if (JSON_UNLIKELY(not parse_ubjson_internal()))
8117 {
8118 return false;
8119 }
8120 get_ignore_noop();
8121 key.clear();
8122 }
8123 }
8124
8125 return sax->end_object();
8126 }
8127
8128 ///////////////////////
8129 // Utility functions //
8130 ///////////////////////
8131
8132 /*!
8133 @brief get next character from the input
8134
8135 This function provides the interface to the used input adapter. It does
8136 not throw in case the input reached EOF, but returns a -'ve valued
8137 `std::char_traits<char>::eof()` in that case.
8138
8139 @return character read from the input
8140 */
8141 int get()
8142 {
8143 ++chars_read;
8144 return (current = ia->get_character());
8145 }
8146
8147 /*!
8148 @return character read from the input after ignoring all 'N' entries
8149 */
8150 int get_ignore_noop()
8151 {
8152 do
8153 {
8154 get();
8155 }
8156 while (current == 'N');
8157
8158 return current;
8159 }
8160
8161 /*
8162 @brief read a number from the input
8163
8164 @tparam NumberType the type of the number
8165 @param[in] format the current format (for diagnostics)
8166 @param[out] result number of type @a NumberType
8167
8168 @return whether conversion completed
8169
8170 @note This function needs to respect the system's endianess, because
8171 bytes in CBOR, MessagePack, and UBJSON are stored in network order
8172 (big endian) and therefore need reordering on little endian systems.
8173 */
8174 template<typename NumberType, bool InputIsLittleEndian = false>
8175 bool get_number(const input_format_t format, NumberType& result)
8176 {
8177 // step 1: read input into array with system's byte order
8178 std::array<uint8_t, sizeof(NumberType)> vec;
8179 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
8180 {
8181 get();
8182 if (JSON_UNLIKELY(not unexpect_eof(format, "number")))
8183 {
8184 return false;
8185 }
8186
8187 // reverse byte order prior to conversion if necessary
8188 if (is_little_endian && !InputIsLittleEndian)
8189 {
8190 vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
8191 }
8192 else
8193 {
8194 vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
8195 }
8196 }
8197
8198 // step 2: convert array into number of type T and return
8199 std::memcpy(&result, vec.data(), sizeof(NumberType));
8200 return true;
8201 }
8202
8203 /*!
8204 @brief create a string by reading characters from the input
8205
8206 @tparam NumberType the type of the number
8207 @param[in] format the current format (for diagnostics)
8208 @param[in] len number of characters to read
8209 @param[out] result string created by reading @a len bytes
8210
8211 @return whether string creation completed
8212
8213 @note We can not reserve @a len bytes for the result, because @a len
8214 may be too large. Usually, @ref unexpect_eof() detects the end of
8215 the input before we run out of string memory.
8216 */
8217 template<typename NumberType>
8218 bool get_string(const input_format_t format,
8219 const NumberType len,
8220 string_t& result)
8221 {
8222 bool success = true;
8223 std::generate_n(std::back_inserter(result), len, [this, &success, &format]()
8224 {
8225 get();
8226 if (JSON_UNLIKELY(not unexpect_eof(format, "string")))
8227 {
8228 success = false;
8229 }
8230 return static_cast<char>(current);
8231 });
8232 return success;
8233 }
8234
8235 /*!
8236 @param[in] format the current format (for diagnostics)
8237 @param[in] context further context information (for diagnostics)
8238 @return whether the last read character is not EOF
8239 */
8240 bool unexpect_eof(const input_format_t format, const char* context) const
8241 {
8242 if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
8243 {
8244 return sax->parse_error(chars_read, "<end of file>",
8245 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
8246 }
8247 return true;
8248 }
8249
8250 /*!
8251 @return a string representation of the last read byte
8252 */
8253 std::string get_token_string() const
8254 {
8255 char cr[3];
8256 snprintf(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
8257 return std::string{cr};
8258 }
8259
8260 /*!
8261 @param[in] format the current format
8262 @param[in] detail a detailed error message
8263 @param[in] context further contect information
8264 @return a message string to use in the parse_error exceptions
8265 */
8266 std::string exception_message(const input_format_t format,
8267 const std::string& detail,
8268 const std::string& context) const
8269 {
8270 std::string error_msg = "syntax error while parsing ";
8271
8272 switch (format)
8273 {
8274 case input_format_t::cbor:
8275 error_msg += "CBOR";
8276 break;
8277
8278 case input_format_t::msgpack:
8279 error_msg += "MessagePack";
8280 break;
8281
8282 case input_format_t::ubjson:
8283 error_msg += "UBJSON";
8284 break;
8285
8286 case input_format_t::bson:
8287 error_msg += "BSON";
8288 break;
8289
8290 // LCOV_EXCL_START
8291 default:
8292 assert(false);
8293 // LCOV_EXCL_STOP
8294 }
8295
8296 return error_msg + " " + context + ": " + detail;
8297 }
8298
8299 private:
8300 /// input adapter
8301 input_adapter_t ia = nullptr;
8302
8303 /// the current character
8304 int current = std::char_traits<char>::eof();
8305
8306 /// the number of characters read
8307 std::size_t chars_read = 0;
8308
8309 /// whether we can assume little endianess
8310 const bool is_little_endian = little_endianess();
8311
8312 /// the SAX parser
8313 json_sax_t* sax = nullptr;
8314};
8315} // namespace detail
8316} // namespace nlohmann
8317
8318// #include <nlohmann/detail/output/binary_writer.hpp>
8319
8320
8321#include <algorithm> // reverse
8322#include <array> // array
8323#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
8324#include <cstring> // memcpy
8325#include <limits> // numeric_limits
8326
8327// #include <nlohmann/detail/input/binary_reader.hpp>
8328
8329// #include <nlohmann/detail/output/output_adapters.hpp>
8330
8331
8332namespace nlohmann
8333{
8334namespace detail
8335{
8336///////////////////
8337// binary writer //
8338///////////////////
8339
8340/*!
8341@brief serialization to CBOR and MessagePack values
8342*/
8343template<typename BasicJsonType, typename CharType>
8344class binary_writer
8345{
8346 using string_t = typename BasicJsonType::string_t;
8347
8348 public:
8349 /*!
8350 @brief create a binary writer
8351
8352 @param[in] adapter output adapter to write to
8353 */
8354 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
8355 {
8356 assert(oa);
8357 }
8358
8359 /*!
8360 @param[in] j JSON value to serialize
8361 @pre j.type() == value_t::object
8362 */
8363 void write_bson(const BasicJsonType& j)
8364 {
8365 switch (j.type())
8366 {
8367 case value_t::object:
8368 {
8369 write_bson_object(*j.m_value.object);
8370 break;
8371 }
8372
8373 default:
8374 {
8375 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
8376 }
8377 }
8378 }
8379
8380 /*!
8381 @param[in] j JSON value to serialize
8382 */
8383 void write_cbor(const BasicJsonType& j)
8384 {
8385 switch (j.type())
8386 {
8387 case value_t::null:
8388 {
8389 oa->write_character(to_char_type(0xF6));
8390 break;
8391 }
8392
8393 case value_t::boolean:
8394 {
8395 oa->write_character(j.m_value.boolean
8396 ? to_char_type(0xF5)
8397 : to_char_type(0xF4));
8398 break;
8399 }
8400
8401 case value_t::number_integer:
8402 {
8403 if (j.m_value.number_integer >= 0)
8404 {
8405 // CBOR does not differentiate between positive signed
8406 // integers and unsigned integers. Therefore, we used the
8407 // code from the value_t::number_unsigned case here.
8408 if (j.m_value.number_integer <= 0x17)
8409 {
8410 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8411 }
8412 else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
8413 {
8414 oa->write_character(to_char_type(0x18));
8415 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8416 }
8417 else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
8418 {
8419 oa->write_character(to_char_type(0x19));
8420 write_number(static_cast<uint16_t>(j.m_value.number_integer));
8421 }
8422 else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
8423 {
8424 oa->write_character(to_char_type(0x1A));
8425 write_number(static_cast<uint32_t>(j.m_value.number_integer));
8426 }
8427 else
8428 {
8429 oa->write_character(to_char_type(0x1B));
8430 write_number(static_cast<uint64_t>(j.m_value.number_integer));
8431 }
8432 }
8433 else
8434 {
8435 // The conversions below encode the sign in the first
8436 // byte, and the value is converted to a positive number.
8437 const auto positive_number = -1 - j.m_value.number_integer;
8438 if (j.m_value.number_integer >= -24)
8439 {
8440 write_number(static_cast<uint8_t>(0x20 + positive_number));
8441 }
8442 else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
8443 {
8444 oa->write_character(to_char_type(0x38));
8445 write_number(static_cast<uint8_t>(positive_number));
8446 }
8447 else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
8448 {
8449 oa->write_character(to_char_type(0x39));
8450 write_number(static_cast<uint16_t>(positive_number));
8451 }
8452 else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
8453 {
8454 oa->write_character(to_char_type(0x3A));
8455 write_number(static_cast<uint32_t>(positive_number));
8456 }
8457 else
8458 {
8459 oa->write_character(to_char_type(0x3B));
8460 write_number(static_cast<uint64_t>(positive_number));
8461 }
8462 }
8463 break;
8464 }
8465
8466 case value_t::number_unsigned:
8467 {
8468 if (j.m_value.number_unsigned <= 0x17)
8469 {
8470 write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
8471 }
8472 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8473 {
8474 oa->write_character(to_char_type(0x18));
8475 write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
8476 }
8477 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8478 {
8479 oa->write_character(to_char_type(0x19));
8480 write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
8481 }
8482 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8483 {
8484 oa->write_character(to_char_type(0x1A));
8485 write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
8486 }
8487 else
8488 {
8489 oa->write_character(to_char_type(0x1B));
8490 write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
8491 }
8492 break;
8493 }
8494
8495 case value_t::number_float:
8496 {
8497 oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
8498 write_number(j.m_value.number_float);
8499 break;
8500 }
8501
8502 case value_t::string:
8503 {
8504 // step 1: write control byte and the string length
8505 const auto N = j.m_value.string->size();
8506 if (N <= 0x17)
8507 {
8508 write_number(static_cast<uint8_t>(0x60 + N));
8509 }
8510 else if (N <= (std::numeric_limits<uint8_t>::max)())
8511 {
8512 oa->write_character(to_char_type(0x78));
8513 write_number(static_cast<uint8_t>(N));
8514 }
8515 else if (N <= (std::numeric_limits<uint16_t>::max)())
8516 {
8517 oa->write_character(to_char_type(0x79));
8518 write_number(static_cast<uint16_t>(N));
8519 }
8520 else if (N <= (std::numeric_limits<uint32_t>::max)())
8521 {
8522 oa->write_character(to_char_type(0x7A));
8523 write_number(static_cast<uint32_t>(N));
8524 }
8525 // LCOV_EXCL_START
8526 else if (N <= (std::numeric_limits<uint64_t>::max)())
8527 {
8528 oa->write_character(to_char_type(0x7B));
8529 write_number(static_cast<uint64_t>(N));
8530 }
8531 // LCOV_EXCL_STOP
8532
8533 // step 2: write the string
8534 oa->write_characters(
8535 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8536 j.m_value.string->size());
8537 break;
8538 }
8539
8540 case value_t::array:
8541 {
8542 // step 1: write control byte and the array size
8543 const auto N = j.m_value.array->size();
8544 if (N <= 0x17)
8545 {
8546 write_number(static_cast<uint8_t>(0x80 + N));
8547 }
8548 else if (N <= (std::numeric_limits<uint8_t>::max)())
8549 {
8550 oa->write_character(to_char_type(0x98));
8551 write_number(static_cast<uint8_t>(N));
8552 }
8553 else if (N <= (std::numeric_limits<uint16_t>::max)())
8554 {
8555 oa->write_character(to_char_type(0x99));
8556 write_number(static_cast<uint16_t>(N));
8557 }
8558 else if (N <= (std::numeric_limits<uint32_t>::max)())
8559 {
8560 oa->write_character(to_char_type(0x9A));
8561 write_number(static_cast<uint32_t>(N));
8562 }
8563 // LCOV_EXCL_START
8564 else if (N <= (std::numeric_limits<uint64_t>::max)())
8565 {
8566 oa->write_character(to_char_type(0x9B));
8567 write_number(static_cast<uint64_t>(N));
8568 }
8569 // LCOV_EXCL_STOP
8570
8571 // step 2: write each element
8572 for (const auto& el : *j.m_value.array)
8573 {
8574 write_cbor(el);
8575 }
8576 break;
8577 }
8578
8579 case value_t::object:
8580 {
8581 // step 1: write control byte and the object size
8582 const auto N = j.m_value.object->size();
8583 if (N <= 0x17)
8584 {
8585 write_number(static_cast<uint8_t>(0xA0 + N));
8586 }
8587 else if (N <= (std::numeric_limits<uint8_t>::max)())
8588 {
8589 oa->write_character(to_char_type(0xB8));
8590 write_number(static_cast<uint8_t>(N));
8591 }
8592 else if (N <= (std::numeric_limits<uint16_t>::max)())
8593 {
8594 oa->write_character(to_char_type(0xB9));
8595 write_number(static_cast<uint16_t>(N));
8596 }
8597 else if (N <= (std::numeric_limits<uint32_t>::max)())
8598 {
8599 oa->write_character(to_char_type(0xBA));
8600 write_number(static_cast<uint32_t>(N));
8601 }
8602 // LCOV_EXCL_START
8603 else if (N <= (std::numeric_limits<uint64_t>::max)())
8604 {
8605 oa->write_character(to_char_type(0xBB));
8606 write_number(static_cast<uint64_t>(N));
8607 }
8608 // LCOV_EXCL_STOP
8609
8610 // step 2: write each element
8611 for (const auto& el : *j.m_value.object)
8612 {
8613 write_cbor(el.first);
8614 write_cbor(el.second);
8615 }
8616 break;
8617 }
8618
8619 default:
8620 break;
8621 }
8622 }
8623
8624 /*!
8625 @param[in] j JSON value to serialize
8626 */
8627 void write_msgpack(const BasicJsonType& j)
8628 {
8629 switch (j.type())
8630 {
8631 case value_t::null: // nil
8632 {
8633 oa->write_character(to_char_type(0xC0));
8634 break;
8635 }
8636
8637 case value_t::boolean: // true and false
8638 {
8639 oa->write_character(j.m_value.boolean
8640 ? to_char_type(0xC3)
8641 : to_char_type(0xC2));
8642 break;
8643 }
8644
8645 case value_t::number_integer:
8646 {
8647 if (j.m_value.number_integer >= 0)
8648 {
8649 // MessagePack does not differentiate between positive
8650 // signed integers and unsigned integers. Therefore, we used
8651 // the code from the value_t::number_unsigned case here.
8652 if (j.m_value.number_unsigned < 128)
8653 {
8654 // positive fixnum
8655 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8656 }
8657 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8658 {
8659 // uint 8
8660 oa->write_character(to_char_type(0xCC));
8661 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8662 }
8663 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8664 {
8665 // uint 16
8666 oa->write_character(to_char_type(0xCD));
8667 write_number(static_cast<uint16_t>(j.m_value.number_integer));
8668 }
8669 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8670 {
8671 // uint 32
8672 oa->write_character(to_char_type(0xCE));
8673 write_number(static_cast<uint32_t>(j.m_value.number_integer));
8674 }
8675 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
8676 {
8677 // uint 64
8678 oa->write_character(to_char_type(0xCF));
8679 write_number(static_cast<uint64_t>(j.m_value.number_integer));
8680 }
8681 }
8682 else
8683 {
8684 if (j.m_value.number_integer >= -32)
8685 {
8686 // negative fixnum
8687 write_number(static_cast<int8_t>(j.m_value.number_integer));
8688 }
8689 else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
8690 j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
8691 {
8692 // int 8
8693 oa->write_character(to_char_type(0xD0));
8694 write_number(static_cast<int8_t>(j.m_value.number_integer));
8695 }
8696 else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
8697 j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
8698 {
8699 // int 16
8700 oa->write_character(to_char_type(0xD1));
8701 write_number(static_cast<int16_t>(j.m_value.number_integer));
8702 }
8703 else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
8704 j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
8705 {
8706 // int 32
8707 oa->write_character(to_char_type(0xD2));
8708 write_number(static_cast<int32_t>(j.m_value.number_integer));
8709 }
8710 else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
8711 j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
8712 {
8713 // int 64
8714 oa->write_character(to_char_type(0xD3));
8715 write_number(static_cast<int64_t>(j.m_value.number_integer));
8716 }
8717 }
8718 break;
8719 }
8720
8721 case value_t::number_unsigned:
8722 {
8723 if (j.m_value.number_unsigned < 128)
8724 {
8725 // positive fixnum
8726 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8727 }
8728 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8729 {
8730 // uint 8
8731 oa->write_character(to_char_type(0xCC));
8732 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8733 }
8734 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8735 {
8736 // uint 16
8737 oa->write_character(to_char_type(0xCD));
8738 write_number(static_cast<uint16_t>(j.m_value.number_integer));
8739 }
8740 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8741 {
8742 // uint 32
8743 oa->write_character(to_char_type(0xCE));
8744 write_number(static_cast<uint32_t>(j.m_value.number_integer));
8745 }
8746 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
8747 {
8748 // uint 64
8749 oa->write_character(to_char_type(0xCF));
8750 write_number(static_cast<uint64_t>(j.m_value.number_integer));
8751 }
8752 break;
8753 }
8754
8755 case value_t::number_float:
8756 {
8757 oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
8758 write_number(j.m_value.number_float);
8759 break;
8760 }
8761
8762 case value_t::string:
8763 {
8764 // step 1: write control byte and the string length
8765 const auto N = j.m_value.string->size();
8766 if (N <= 31)
8767 {
8768 // fixstr
8769 write_number(static_cast<uint8_t>(0xA0 | N));
8770 }
8771 else if (N <= (std::numeric_limits<uint8_t>::max)())
8772 {
8773 // str 8
8774 oa->write_character(to_char_type(0xD9));
8775 write_number(static_cast<uint8_t>(N));
8776 }
8777 else if (N <= (std::numeric_limits<uint16_t>::max)())
8778 {
8779 // str 16
8780 oa->write_character(to_char_type(0xDA));
8781 write_number(static_cast<uint16_t>(N));
8782 }
8783 else if (N <= (std::numeric_limits<uint32_t>::max)())
8784 {
8785 // str 32
8786 oa->write_character(to_char_type(0xDB));
8787 write_number(static_cast<uint32_t>(N));
8788 }
8789
8790 // step 2: write the string
8791 oa->write_characters(
8792 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8793 j.m_value.string->size());
8794 break;
8795 }
8796
8797 case value_t::array:
8798 {
8799 // step 1: write control byte and the array size
8800 const auto N = j.m_value.array->size();
8801 if (N <= 15)
8802 {
8803 // fixarray
8804 write_number(static_cast<uint8_t>(0x90 | N));
8805 }
8806 else if (N <= (std::numeric_limits<uint16_t>::max)())
8807 {
8808 // array 16
8809 oa->write_character(to_char_type(0xDC));
8810 write_number(static_cast<uint16_t>(N));
8811 }
8812 else if (N <= (std::numeric_limits<uint32_t>::max)())
8813 {
8814 // array 32
8815 oa->write_character(to_char_type(0xDD));
8816 write_number(static_cast<uint32_t>(N));
8817 }
8818
8819 // step 2: write each element
8820 for (const auto& el : *j.m_value.array)
8821 {
8822 write_msgpack(el);
8823 }
8824 break;
8825 }
8826
8827 case value_t::object:
8828 {
8829 // step 1: write control byte and the object size
8830 const auto N = j.m_value.object->size();
8831 if (N <= 15)
8832 {
8833 // fixmap
8834 write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
8835 }
8836 else if (N <= (std::numeric_limits<uint16_t>::max)())
8837 {
8838 // map 16
8839 oa->write_character(to_char_type(0xDE));
8840 write_number(static_cast<uint16_t>(N));
8841 }
8842 else if (N <= (std::numeric_limits<uint32_t>::max)())
8843 {
8844 // map 32
8845 oa->write_character(to_char_type(0xDF));
8846 write_number(static_cast<uint32_t>(N));
8847 }
8848
8849 // step 2: write each element
8850 for (const auto& el : *j.m_value.object)
8851 {
8852 write_msgpack(el.first);
8853 write_msgpack(el.second);
8854 }
8855 break;
8856 }
8857
8858 default:
8859 break;
8860 }
8861 }
8862
8863 /*!
8864 @param[in] j JSON value to serialize
8865 @param[in] use_count whether to use '#' prefixes (optimized format)
8866 @param[in] use_type whether to use '$' prefixes (optimized format)
8867 @param[in] add_prefix whether prefixes need to be used for this value
8868 */
8869 void write_ubjson(const BasicJsonType& j, const bool use_count,
8870 const bool use_type, const bool add_prefix = true)
8871 {
8872 switch (j.type())
8873 {
8874 case value_t::null:
8875 {
8876 if (add_prefix)
8877 {
8878 oa->write_character(to_char_type('Z'));
8879 }
8880 break;
8881 }
8882
8883 case value_t::boolean:
8884 {
8885 if (add_prefix)
8886 {
8887 oa->write_character(j.m_value.boolean
8888 ? to_char_type('T')
8889 : to_char_type('F'));
8890 }
8891 break;
8892 }
8893
8894 case value_t::number_integer:
8895 {
8896 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
8897 break;
8898 }
8899
8900 case value_t::number_unsigned:
8901 {
8902 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
8903 break;
8904 }
8905
8906 case value_t::number_float:
8907 {
8908 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
8909 break;
8910 }
8911
8912 case value_t::string:
8913 {
8914 if (add_prefix)
8915 {
8916 oa->write_character(to_char_type('S'));
8917 }
8918 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
8919 oa->write_characters(
8920 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8921 j.m_value.string->size());
8922 break;
8923 }
8924
8925 case value_t::array:
8926 {
8927 if (add_prefix)
8928 {
8929 oa->write_character(to_char_type('['));
8930 }
8931
8932 bool prefix_required = true;
8933 if (use_type and not j.m_value.array->empty())
8934 {
8935 assert(use_count);
8936 const CharType first_prefix = ubjson_prefix(j.front());
8937 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
8938 [this, first_prefix](const BasicJsonType & v)
8939 {
8940 return ubjson_prefix(v) == first_prefix;
8941 });
8942
8943 if (same_prefix)
8944 {
8945 prefix_required = false;
8946 oa->write_character(to_char_type('$'));
8947 oa->write_character(first_prefix);
8948 }
8949 }
8950
8951 if (use_count)
8952 {
8953 oa->write_character(to_char_type('#'));
8954 write_number_with_ubjson_prefix(j.m_value.array->size(), true);
8955 }
8956
8957 for (const auto& el : *j.m_value.array)
8958 {
8959 write_ubjson(el, use_count, use_type, prefix_required);
8960 }
8961
8962 if (not use_count)
8963 {
8964 oa->write_character(to_char_type(']'));
8965 }
8966
8967 break;
8968 }
8969
8970 case value_t::object:
8971 {
8972 if (add_prefix)
8973 {
8974 oa->write_character(to_char_type('{'));
8975 }
8976
8977 bool prefix_required = true;
8978 if (use_type and not j.m_value.object->empty())
8979 {
8980 assert(use_count);
8981 const CharType first_prefix = ubjson_prefix(j.front());
8982 const bool same_prefix = std::all_of(j.begin(), j.end(),
8983 [this, first_prefix](const BasicJsonType & v)
8984 {
8985 return ubjson_prefix(v) == first_prefix;
8986 });
8987
8988 if (same_prefix)
8989 {
8990 prefix_required = false;
8991 oa->write_character(to_char_type('$'));
8992 oa->write_character(first_prefix);
8993 }
8994 }
8995
8996 if (use_count)
8997 {
8998 oa->write_character(to_char_type('#'));
8999 write_number_with_ubjson_prefix(j.m_value.object->size(), true);
9000 }
9001
9002 for (const auto& el : *j.m_value.object)
9003 {
9004 write_number_with_ubjson_prefix(el.first.size(), true);
9005 oa->write_characters(
9006 reinterpret_cast<const CharType*>(el.first.c_str()),
9007 el.first.size());
9008 write_ubjson(el.second, use_count, use_type, prefix_required);
9009 }
9010
9011 if (not use_count)
9012 {
9013 oa->write_character(to_char_type('}'));
9014 }
9015
9016 break;
9017 }
9018
9019 default:
9020 break;
9021 }
9022 }
9023
9024 private:
9025 //////////
9026 // BSON //
9027 //////////
9028
9029 /*!
9030 @return The size of a BSON document entry header, including the id marker
9031 and the entry name size (and its null-terminator).
9032 */
9033 static std::size_t calc_bson_entry_header_size(const string_t& name)
9034 {
9035 const auto it = name.find(static_cast<typename string_t::value_type>(0));
9036 if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos))
9037 {
9038 JSON_THROW(out_of_range::create(409,
9039 "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
9040 }
9041
9042 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
9043 }
9044
9045 /*!
9046 @brief Writes the given @a element_type and @a name to the output adapter
9047 */
9048 void write_bson_entry_header(const string_t& name,
9049 const std::uint8_t element_type)
9050 {
9051 oa->write_character(to_char_type(element_type)); // boolean
9052 oa->write_characters(
9053 reinterpret_cast<const CharType*>(name.c_str()),
9054 name.size() + 1u);
9055 }
9056
9057 /*!
9058 @brief Writes a BSON element with key @a name and boolean value @a value
9059 */
9060 void write_bson_boolean(const string_t& name,
9061 const bool value)
9062 {
9063 write_bson_entry_header(name, 0x08);
9064 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
9065 }
9066
9067 /*!
9068 @brief Writes a BSON element with key @a name and double value @a value
9069 */
9070 void write_bson_double(const string_t& name,
9071 const double value)
9072 {
9073 write_bson_entry_header(name, 0x01);
9074 write_number<double, true>(value);
9075 }
9076
9077 /*!
9078 @return The size of the BSON-encoded string in @a value
9079 */
9080 static std::size_t calc_bson_string_size(const string_t& value)
9081 {
9082 return sizeof(std::int32_t) + value.size() + 1ul;
9083 }
9084
9085 /*!
9086 @brief Writes a BSON element with key @a name and string value @a value
9087 */
9088 void write_bson_string(const string_t& name,
9089 const string_t& value)
9090 {
9091 write_bson_entry_header(name, 0x02);
9092
9093 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
9094 oa->write_characters(
9095 reinterpret_cast<const CharType*>(value.c_str()),
9096 value.size() + 1);
9097 }
9098
9099 /*!
9100 @brief Writes a BSON element with key @a name and null value
9101 */
9102 void write_bson_null(const string_t& name)
9103 {
9104 write_bson_entry_header(name, 0x0A);
9105 }
9106
9107 /*!
9108 @return The size of the BSON-encoded integer @a value
9109 */
9110 static std::size_t calc_bson_integer_size(const std::int64_t value)
9111 {
9112 if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
9113 {
9114 return sizeof(std::int32_t);
9115 }
9116 else
9117 {
9118 return sizeof(std::int64_t);
9119 }
9120 }
9121
9122 /*!
9123 @brief Writes a BSON element with key @a name and integer @a value
9124 */
9125 void write_bson_integer(const string_t& name,
9126 const std::int64_t value)
9127 {
9128 if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
9129 {
9130 write_bson_entry_header(name, 0x10); // int32
9131 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
9132 }
9133 else
9134 {
9135 write_bson_entry_header(name, 0x12); // int64
9136 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
9137 }
9138 }
9139
9140 /*!
9141 @return The size of the BSON-encoded unsigned integer in @a j
9142 */
9143 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
9144 {
9145 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
9146 ? sizeof(std::int32_t)
9147 : sizeof(std::int64_t);
9148 }
9149
9150 /*!
9151 @brief Writes a BSON element with key @a name and unsigned @a value
9152 */
9153 void write_bson_unsigned(const string_t& name,
9154 const std::uint64_t value)
9155 {
9156 if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
9157 {
9158 write_bson_entry_header(name, 0x10 /* int32 */);
9159 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
9160 }
9161 else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
9162 {
9163 write_bson_entry_header(name, 0x12 /* int64 */);
9164 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
9165 }
9166 else
9167 {
9168 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
9169 }
9170 }
9171
9172 /*!
9173 @brief Writes a BSON element with key @a name and object @a value
9174 */
9175 void write_bson_object_entry(const string_t& name,
9176 const typename BasicJsonType::object_t& value)
9177 {
9178 write_bson_entry_header(name, 0x03); // object
9179 write_bson_object(value);
9180 }
9181
9182 /*!
9183 @return The size of the BSON-encoded array @a value
9184 */
9185 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
9186 {
9187 std::size_t embedded_document_size = 0ul;
9188 std::size_t array_index = 0ul;
9189
9190 for (const auto& el : value)
9191 {
9192 embedded_document_size += calc_bson_element_size(std::to_string(array_index++), el);
9193 }
9194
9195 return sizeof(std::int32_t) + embedded_document_size + 1ul;
9196 }
9197
9198 /*!
9199 @brief Writes a BSON element with key @a name and array @a value
9200 */
9201 void write_bson_array(const string_t& name,
9202 const typename BasicJsonType::array_t& value)
9203 {
9204 write_bson_entry_header(name, 0x04); // array
9205 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
9206
9207 std::size_t array_index = 0ul;
9208
9209 for (const auto& el : value)
9210 {
9211 write_bson_element(std::to_string(array_index++), el);
9212 }
9213
9214 oa->write_character(to_char_type(0x00));
9215 }
9216
9217 /*!
9218 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
9219 @return The calculated size for the BSON document entry for @a j with the given @a name.
9220 */
9221 static std::size_t calc_bson_element_size(const string_t& name,
9222 const BasicJsonType& j)
9223 {
9224 const auto header_size = calc_bson_entry_header_size(name);
9225 switch (j.type())
9226 {
9227 case value_t::object:
9228 return header_size + calc_bson_object_size(*j.m_value.object);
9229
9230 case value_t::array:
9231 return header_size + calc_bson_array_size(*j.m_value.array);
9232
9233 case value_t::boolean:
9234 return header_size + 1ul;
9235
9236 case value_t::number_float:
9237 return header_size + 8ul;
9238
9239 case value_t::number_integer:
9240 return header_size + calc_bson_integer_size(j.m_value.number_integer);
9241
9242 case value_t::number_unsigned:
9243 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
9244
9245 case value_t::string:
9246 return header_size + calc_bson_string_size(*j.m_value.string);
9247
9248 case value_t::null:
9249 return header_size + 0ul;
9250
9251 // LCOV_EXCL_START
9252 default:
9253 assert(false);
9254 return 0ul;
9255 // LCOV_EXCL_STOP
9256 };
9257 }
9258
9259 /*!
9260 @brief Serializes the JSON value @a j to BSON and associates it with the
9261 key @a name.
9262 @param name The name to associate with the JSON entity @a j within the
9263 current BSON document
9264 @return The size of the BSON entry
9265 */
9266 void write_bson_element(const string_t& name,
9267 const BasicJsonType& j)
9268 {
9269 switch (j.type())
9270 {
9271 case value_t::object:
9272 return write_bson_object_entry(name, *j.m_value.object);
9273
9274 case value_t::array:
9275 return write_bson_array(name, *j.m_value.array);
9276
9277 case value_t::boolean:
9278 return write_bson_boolean(name, j.m_value.boolean);
9279
9280 case value_t::number_float:
9281 return write_bson_double(name, j.m_value.number_float);
9282
9283 case value_t::number_integer:
9284 return write_bson_integer(name, j.m_value.number_integer);
9285
9286 case value_t::number_unsigned:
9287 return write_bson_unsigned(name, j.m_value.number_unsigned);
9288
9289 case value_t::string:
9290 return write_bson_string(name, *j.m_value.string);
9291
9292 case value_t::null:
9293 return write_bson_null(name);
9294
9295 // LCOV_EXCL_START
9296 default:
9297 assert(false);
9298 return;
9299 // LCOV_EXCL_STOP
9300 };
9301 }
9302
9303 /*!
9304 @brief Calculates the size of the BSON serialization of the given
9305 JSON-object @a j.
9306 @param[in] j JSON value to serialize
9307 @pre j.type() == value_t::object
9308 */
9309 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
9310 {
9311 std::size_t document_size = std::accumulate(value.begin(), value.end(), 0ul,
9312 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
9313 {
9314 return result += calc_bson_element_size(el.first, el.second);
9315 });
9316
9317 return sizeof(std::int32_t) + document_size + 1ul;
9318 }
9319
9320 /*!
9321 @param[in] j JSON value to serialize
9322 @pre j.type() == value_t::object
9323 */
9324 void write_bson_object(const typename BasicJsonType::object_t& value)
9325 {
9326 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
9327
9328 for (const auto& el : value)
9329 {
9330 write_bson_element(el.first, el.second);
9331 }
9332
9333 oa->write_character(to_char_type(0x00));
9334 }
9335
9336 //////////
9337 // CBOR //
9338 //////////
9339
9340 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
9341 {
9342 return to_char_type(0xFA); // Single-Precision Float
9343 }
9344
9345 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
9346 {
9347 return to_char_type(0xFB); // Double-Precision Float
9348 }
9349
9350 /////////////
9351 // MsgPack //
9352 /////////////
9353
9354 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
9355 {
9356 return to_char_type(0xCA); // float 32
9357 }
9358
9359 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
9360 {
9361 return to_char_type(0xCB); // float 64
9362 }
9363
9364 ////////////
9365 // UBJSON //
9366 ////////////
9367
9368 // UBJSON: write number (floating point)
9369 template<typename NumberType, typename std::enable_if<
9370 std::is_floating_point<NumberType>::value, int>::type = 0>
9371 void write_number_with_ubjson_prefix(const NumberType n,
9372 const bool add_prefix)
9373 {
9374 if (add_prefix)
9375 {
9376 oa->write_character(get_ubjson_float_prefix(n));
9377 }
9378 write_number(n);
9379 }
9380
9381 // UBJSON: write number (unsigned integer)
9382 template<typename NumberType, typename std::enable_if<
9383 std::is_unsigned<NumberType>::value, int>::type = 0>
9384 void write_number_with_ubjson_prefix(const NumberType n,
9385 const bool add_prefix)
9386 {
9387 if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
9388 {
9389 if (add_prefix)
9390 {
9391 oa->write_character(to_char_type('i')); // int8
9392 }
9393 write_number(static_cast<uint8_t>(n));
9394 }
9395 else if (n <= (std::numeric_limits<uint8_t>::max)())
9396 {
9397 if (add_prefix)
9398 {
9399 oa->write_character(to_char_type('U')); // uint8
9400 }
9401 write_number(static_cast<uint8_t>(n));
9402 }
9403 else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
9404 {
9405 if (add_prefix)
9406 {
9407 oa->write_character(to_char_type('I')); // int16
9408 }
9409 write_number(static_cast<int16_t>(n));
9410 }
9411 else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
9412 {
9413 if (add_prefix)
9414 {
9415 oa->write_character(to_char_type('l')); // int32
9416 }
9417 write_number(static_cast<int32_t>(n));
9418 }
9419 else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
9420 {
9421 if (add_prefix)
9422 {
9423 oa->write_character(to_char_type('L')); // int64
9424 }
9425 write_number(static_cast<int64_t>(n));
9426 }
9427 else
9428 {
9429 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
9430 }
9431 }
9432
9433 // UBJSON: write number (signed integer)
9434 template<typename NumberType, typename std::enable_if<
9435 std::is_signed<NumberType>::value and
9436 not std::is_floating_point<NumberType>::value, int>::type = 0>
9437 void write_number_with_ubjson_prefix(const NumberType n,
9438 const bool add_prefix)
9439 {
9440 if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
9441 {
9442 if (add_prefix)
9443 {
9444 oa->write_character(to_char_type('i')); // int8
9445 }
9446 write_number(static_cast<int8_t>(n));
9447 }
9448 else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))
9449 {
9450 if (add_prefix)
9451 {
9452 oa->write_character(to_char_type('U')); // uint8
9453 }
9454 write_number(static_cast<uint8_t>(n));
9455 }
9456 else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
9457 {
9458 if (add_prefix)
9459 {
9460 oa->write_character(to_char_type('I')); // int16
9461 }
9462 write_number(static_cast<int16_t>(n));
9463 }
9464 else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
9465 {
9466 if (add_prefix)
9467 {
9468 oa->write_character(to_char_type('l')); // int32
9469 }
9470 write_number(static_cast<int32_t>(n));
9471 }
9472 else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
9473 {
9474 if (add_prefix)
9475 {
9476 oa->write_character(to_char_type('L')); // int64
9477 }
9478 write_number(static_cast<int64_t>(n));
9479 }
9480 // LCOV_EXCL_START
9481 else
9482 {
9483 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
9484 }
9485 // LCOV_EXCL_STOP
9486 }
9487
9488 /*!
9489 @brief determine the type prefix of container values
9490
9491 @note This function does not need to be 100% accurate when it comes to
9492 integer limits. In case a number exceeds the limits of int64_t,
9493 this will be detected by a later call to function
9494 write_number_with_ubjson_prefix. Therefore, we return 'L' for any
9495 value that does not fit the previous limits.
9496 */
9497 CharType ubjson_prefix(const BasicJsonType& j) const noexcept
9498 {
9499 switch (j.type())
9500 {
9501 case value_t::null:
9502 return 'Z';
9503
9504 case value_t::boolean:
9505 return j.m_value.boolean ? 'T' : 'F';
9506
9507 case value_t::number_integer:
9508 {
9509 if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
9510 {
9511 return 'i';
9512 }
9513 if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
9514 {
9515 return 'U';
9516 }
9517 if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
9518 {
9519 return 'I';
9520 }
9521 if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
9522 {
9523 return 'l';
9524 }
9525 // no check and assume int64_t (see note above)
9526 return 'L';
9527 }
9528
9529 case value_t::number_unsigned:
9530 {
9531 if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
9532 {
9533 return 'i';
9534 }
9535 if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
9536 {
9537 return 'U';
9538 }
9539 if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
9540 {
9541 return 'I';
9542 }
9543 if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
9544 {
9545 return 'l';
9546 }
9547 // no check and assume int64_t (see note above)
9548 return 'L';
9549 }
9550
9551 case value_t::number_float:
9552 return get_ubjson_float_prefix(j.m_value.number_float);
9553
9554 case value_t::string:
9555 return 'S';
9556
9557 case value_t::array:
9558 return '[';
9559
9560 case value_t::object:
9561 return '{';
9562
9563 default: // discarded values
9564 return 'N';
9565 }
9566 }
9567
9568 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
9569 {
9570 return 'd'; // float 32
9571 }
9572
9573 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
9574 {
9575 return 'D'; // float 64
9576 }
9577
9578 ///////////////////////
9579 // Utility functions //
9580 ///////////////////////
9581
9582 /*
9583 @brief write a number to output input
9584 @param[in] n number of type @a NumberType
9585 @tparam NumberType the type of the number
9586 @tparam OutputIsLittleEndian Set to true if output data is
9587 required to be little endian
9588
9589 @note This function needs to respect the system's endianess, because bytes
9590 in CBOR, MessagePack, and UBJSON are stored in network order (big
9591 endian) and therefore need reordering on little endian systems.
9592 */
9593 template<typename NumberType, bool OutputIsLittleEndian = false>
9594 void write_number(const NumberType n)
9595 {
9596 // step 1: write number to array of length NumberType
9597 std::array<CharType, sizeof(NumberType)> vec;
9598 std::memcpy(vec.data(), &n, sizeof(NumberType));
9599
9600 // step 2: write array to output (with possible reordering)
9601 if (is_little_endian and not OutputIsLittleEndian)
9602 {
9603 // reverse byte order prior to conversion if necessary
9604 std::reverse(vec.begin(), vec.end());
9605 }
9606
9607 oa->write_characters(vec.data(), sizeof(NumberType));
9608 }
9609
9610 public:
9611 // The following to_char_type functions are implement the conversion
9612 // between uint8_t and CharType. In case CharType is not unsigned,
9613 // such a conversion is required to allow values greater than 128.
9614 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
9615 template < typename C = CharType,
9616 enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
9617 static constexpr CharType to_char_type(std::uint8_t x) noexcept
9618 {
9619 return *reinterpret_cast<char*>(&x);
9620 }
9621
9622 template < typename C = CharType,
9623 enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
9624 static CharType to_char_type(std::uint8_t x) noexcept
9625 {
9626 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
9627 static_assert(std::is_pod<CharType>::value, "CharType must be POD");
9628 CharType result;
9629 std::memcpy(&result, &x, sizeof(x));
9630 return result;
9631 }
9632
9633 template<typename C = CharType,
9634 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
9635 static constexpr CharType to_char_type(std::uint8_t x) noexcept
9636 {
9637 return x;
9638 }
9639
9640 template < typename InputCharType, typename C = CharType,
9641 enable_if_t <
9642 std::is_signed<C>::value and
9643 std::is_signed<char>::value and
9644 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
9645 > * = nullptr >
9646 static constexpr CharType to_char_type(InputCharType x) noexcept
9647 {
9648 return x;
9649 }
9650
9651 private:
9652 /// whether we can assume little endianess
9653 const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
9654
9655 /// the output
9656 output_adapter_t<CharType> oa = nullptr;
9657};
9658} // namespace detail
9659} // namespace nlohmann
9660
9661// #include <nlohmann/detail/output/serializer.hpp>
9662
9663
9664#include <algorithm> // reverse, remove, fill, find, none_of
9665#include <array> // array
9666#include <cassert> // assert
9667#include <ciso646> // and, or
9668#include <clocale> // localeconv, lconv
9669#include <cmath> // labs, isfinite, isnan, signbit
9670#include <cstddef> // size_t, ptrdiff_t
9671#include <cstdint> // uint8_t
9672#include <cstdio> // snprintf
9673#include <limits> // numeric_limits
9674#include <string> // string
9675#include <type_traits> // is_same
9676
9677// #include <nlohmann/detail/exceptions.hpp>
9678
9679// #include <nlohmann/detail/conversions/to_chars.hpp>
9680
9681
9682#include <cassert> // assert
9683#include <ciso646> // or, and, not
9684#include <cmath> // signbit, isfinite
9685#include <cstdint> // intN_t, uintN_t
9686#include <cstring> // memcpy, memmove
9687
9688namespace nlohmann
9689{
9690namespace detail
9691{
9692
9693/*!
9694@brief implements the Grisu2 algorithm for binary to decimal floating-point
9695conversion.
9696
9697This implementation is a slightly modified version of the reference
9698implementation which may be obtained from
9699http://florian.loitsch.com/publications (bench.tar.gz).
9700
9701The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
9702
9703For a detailed description of the algorithm see:
9704
9705[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
9706 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
9707 Language Design and Implementation, PLDI 2010
9708[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
9709 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
9710 Design and Implementation, PLDI 1996
9711*/
9712namespace dtoa_impl
9713{
9714
9715template <typename Target, typename Source>
9716Target reinterpret_bits(const Source source)
9717{
9718 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
9719
9720 Target target;
9721 std::memcpy(&target, &source, sizeof(Source));
9722 return target;
9723}
9724
9725struct diyfp // f * 2^e
9726{
9727 static constexpr int kPrecision = 64; // = q
9728
9729 uint64_t f = 0;
9730 int e = 0;
9731
9732 constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
9733
9734 /*!
9735 @brief returns x - y
9736 @pre x.e == y.e and x.f >= y.f
9737 */
9738 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
9739 {
9740 assert(x.e == y.e);
9741 assert(x.f >= y.f);
9742
9743 return {x.f - y.f, x.e};
9744 }
9745
9746 /*!
9747 @brief returns x * y
9748 @note The result is rounded. (Only the upper q bits are returned.)
9749 */
9750 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
9751 {
9752 static_assert(kPrecision == 64, "internal error");
9753
9754 // Computes:
9755 // f = round((x.f * y.f) / 2^q)
9756 // e = x.e + y.e + q
9757
9758 // Emulate the 64-bit * 64-bit multiplication:
9759 //
9760 // p = u * v
9761 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
9762 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
9763 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
9764 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
9765 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
9766 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
9767 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
9768 //
9769 // (Since Q might be larger than 2^32 - 1)
9770 //
9771 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
9772 //
9773 // (Q_hi + H does not overflow a 64-bit int)
9774 //
9775 // = p_lo + 2^64 p_hi
9776
9777 const uint64_t u_lo = x.f & 0xFFFFFFFF;
9778 const uint64_t u_hi = x.f >> 32;
9779 const uint64_t v_lo = y.f & 0xFFFFFFFF;
9780 const uint64_t v_hi = y.f >> 32;
9781
9782 const uint64_t p0 = u_lo * v_lo;
9783 const uint64_t p1 = u_lo * v_hi;
9784 const uint64_t p2 = u_hi * v_lo;
9785 const uint64_t p3 = u_hi * v_hi;
9786
9787 const uint64_t p0_hi = p0 >> 32;
9788 const uint64_t p1_lo = p1 & 0xFFFFFFFF;
9789 const uint64_t p1_hi = p1 >> 32;
9790 const uint64_t p2_lo = p2 & 0xFFFFFFFF;
9791 const uint64_t p2_hi = p2 >> 32;
9792
9793 uint64_t Q = p0_hi + p1_lo + p2_lo;
9794
9795 // The full product might now be computed as
9796 //
9797 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
9798 // p_lo = p0_lo + (Q << 32)
9799 //
9800 // But in this particular case here, the full p_lo is not required.
9801 // Effectively we only need to add the highest bit in p_lo to p_hi (and
9802 // Q_hi + 1 does not overflow).
9803
9804 Q += uint64_t{1} << (64 - 32 - 1); // round, ties up
9805
9806 const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);
9807
9808 return {h, x.e + y.e + 64};
9809 }
9810
9811 /*!
9812 @brief normalize x such that the significand is >= 2^(q-1)
9813 @pre x.f != 0
9814 */
9815 static diyfp normalize(diyfp x) noexcept
9816 {
9817 assert(x.f != 0);
9818
9819 while ((x.f >> 63) == 0)
9820 {
9821 x.f <<= 1;
9822 x.e--;
9823 }
9824
9825 return x;
9826 }
9827
9828 /*!
9829 @brief normalize x such that the result has the exponent E
9830 @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
9831 */
9832 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
9833 {
9834 const int delta = x.e - target_exponent;
9835
9836 assert(delta >= 0);
9837 assert(((x.f << delta) >> delta) == x.f);
9838
9839 return {x.f << delta, target_exponent};
9840 }
9841};
9842
9843struct boundaries
9844{
9845 diyfp w;
9846 diyfp minus;
9847 diyfp plus;
9848};
9849
9850/*!
9851Compute the (normalized) diyfp representing the input number 'value' and its
9852boundaries.
9853
9854@pre value must be finite and positive
9855*/
9856template <typename FloatType>
9857boundaries compute_boundaries(FloatType value)
9858{
9859 assert(std::isfinite(value));
9860 assert(value > 0);
9861
9862 // Convert the IEEE representation into a diyfp.
9863 //
9864 // If v is denormal:
9865 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
9866 // If v is normalized:
9867 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
9868
9869 static_assert(std::numeric_limits<FloatType>::is_iec559,
9870 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
9871
9872 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
9873 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
9874 constexpr int kMinExp = 1 - kBias;
9875 constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
9876
9877 using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;
9878
9879 const uint64_t bits = reinterpret_bits<bits_type>(value);
9880 const uint64_t E = bits >> (kPrecision - 1);
9881 const uint64_t F = bits & (kHiddenBit - 1);
9882
9883 const bool is_denormal = (E == 0);
9884 const diyfp v = is_denormal
9885 ? diyfp(F, kMinExp)
9886 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
9887
9888 // Compute the boundaries m- and m+ of the floating-point value
9889 // v = f * 2^e.
9890 //
9891 // Determine v- and v+, the floating-point predecessor and successor if v,
9892 // respectively.
9893 //
9894 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
9895 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
9896 //
9897 // v+ = v + 2^e
9898 //
9899 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
9900 // between m- and m+ round to v, regardless of how the input rounding
9901 // algorithm breaks ties.
9902 //
9903 // ---+-------------+-------------+-------------+-------------+--- (A)
9904 // v- m- v m+ v+
9905 //
9906 // -----------------+------+------+-------------+-------------+--- (B)
9907 // v- m- v m+ v+
9908
9909 const bool lower_boundary_is_closer = (F == 0 and E > 1);
9910 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
9911 const diyfp m_minus = lower_boundary_is_closer
9912 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
9913 : diyfp(2 * v.f - 1, v.e - 1); // (A)
9914
9915 // Determine the normalized w+ = m+.
9916 const diyfp w_plus = diyfp::normalize(m_plus);
9917
9918 // Determine w- = m- such that e_(w-) = e_(w+).
9919 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
9920
9921 return {diyfp::normalize(v), w_minus, w_plus};
9922}
9923
9924// Given normalized diyfp w, Grisu needs to find a (normalized) cached
9925// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
9926// within a certain range [alpha, gamma] (Definition 3.2 from [1])
9927//
9928// alpha <= e = e_c + e_w + q <= gamma
9929//
9930// or
9931//
9932// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
9933// <= f_c * f_w * 2^gamma
9934//
9935// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
9936//
9937// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
9938//
9939// or
9940//
9941// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
9942//
9943// The choice of (alpha,gamma) determines the size of the table and the form of
9944// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
9945// in practice:
9946//
9947// The idea is to cut the number c * w = f * 2^e into two parts, which can be
9948// processed independently: An integral part p1, and a fractional part p2:
9949//
9950// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
9951// = (f div 2^-e) + (f mod 2^-e) * 2^e
9952// = p1 + p2 * 2^e
9953//
9954// The conversion of p1 into decimal form requires a series of divisions and
9955// modulos by (a power of) 10. These operations are faster for 32-bit than for
9956// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
9957// achieved by choosing
9958//
9959// -e >= 32 or e <= -32 := gamma
9960//
9961// In order to convert the fractional part
9962//
9963// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
9964//
9965// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
9966// d[-i] are extracted in order:
9967//
9968// (10 * p2) div 2^-e = d[-1]
9969// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
9970//
9971// The multiplication by 10 must not overflow. It is sufficient to choose
9972//
9973// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
9974//
9975// Since p2 = f mod 2^-e < 2^-e,
9976//
9977// -e <= 60 or e >= -60 := alpha
9978
9979constexpr int kAlpha = -60;
9980constexpr int kGamma = -32;
9981
9982struct cached_power // c = f * 2^e ~= 10^k
9983{
9984 uint64_t f;
9985 int e;
9986 int k;
9987};
9988
9989/*!
9990For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
9991power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
9992satisfies (Definition 3.2 from [1])
9993
9994 alpha <= e_c + e + q <= gamma.
9995*/
9996inline cached_power get_cached_power_for_binary_exponent(int e)
9997{
9998 // Now
9999 //
10000 // alpha <= e_c + e + q <= gamma (1)
10001 // ==> f_c * 2^alpha <= c * 2^e * 2^q
10002 //
10003 // and since the c's are normalized, 2^(q-1) <= f_c,
10004 //
10005 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
10006 // ==> 2^(alpha - e - 1) <= c
10007 //
10008 // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as
10009 //
10010 // k = ceil( log_10( 2^(alpha - e - 1) ) )
10011 // = ceil( (alpha - e - 1) * log_10(2) )
10012 //
10013 // From the paper:
10014 // "In theory the result of the procedure could be wrong since c is rounded,
10015 // and the computation itself is approximated [...]. In practice, however,
10016 // this simple function is sufficient."
10017 //
10018 // For IEEE double precision floating-point numbers converted into
10019 // normalized diyfp's w = f * 2^e, with q = 64,
10020 //
10021 // e >= -1022 (min IEEE exponent)
10022 // -52 (p - 1)
10023 // -52 (p - 1, possibly normalize denormal IEEE numbers)
10024 // -11 (normalize the diyfp)
10025 // = -1137
10026 //
10027 // and
10028 //
10029 // e <= +1023 (max IEEE exponent)
10030 // -52 (p - 1)
10031 // -11 (normalize the diyfp)
10032 // = 960
10033 //
10034 // This binary exponent range [-1137,960] results in a decimal exponent
10035 // range [-307,324]. One does not need to store a cached power for each
10036 // k in this range. For each such k it suffices to find a cached power
10037 // such that the exponent of the product lies in [alpha,gamma].
10038 // This implies that the difference of the decimal exponents of adjacent
10039 // table entries must be less than or equal to
10040 //
10041 // floor( (gamma - alpha) * log_10(2) ) = 8.
10042 //
10043 // (A smaller distance gamma-alpha would require a larger table.)
10044
10045 // NB:
10046 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
10047
10048 constexpr int kCachedPowersSize = 79;
10049 constexpr int kCachedPowersMinDecExp = -300;
10050 constexpr int kCachedPowersDecStep = 8;
10051
10052 static constexpr cached_power kCachedPowers[] =
10053 {
10054 { 0xAB70FE17C79AC6CA, -1060, -300 },
10055 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
10056 { 0xBE5691EF416BD60C, -1007, -284 },
10057 { 0x8DD01FAD907FFC3C, -980, -276 },
10058 { 0xD3515C2831559A83, -954, -268 },
10059 { 0x9D71AC8FADA6C9B5, -927, -260 },
10060 { 0xEA9C227723EE8BCB, -901, -252 },
10061 { 0xAECC49914078536D, -874, -244 },
10062 { 0x823C12795DB6CE57, -847, -236 },
10063 { 0xC21094364DFB5637, -821, -228 },
10064 { 0x9096EA6F3848984F, -794, -220 },
10065 { 0xD77485CB25823AC7, -768, -212 },
10066 { 0xA086CFCD97BF97F4, -741, -204 },
10067 { 0xEF340A98172AACE5, -715, -196 },
10068 { 0xB23867FB2A35B28E, -688, -188 },
10069 { 0x84C8D4DFD2C63F3B, -661, -180 },
10070 { 0xC5DD44271AD3CDBA, -635, -172 },
10071 { 0x936B9FCEBB25C996, -608, -164 },
10072 { 0xDBAC6C247D62A584, -582, -156 },
10073 { 0xA3AB66580D5FDAF6, -555, -148 },
10074 { 0xF3E2F893DEC3F126, -529, -140 },
10075 { 0xB5B5ADA8AAFF80B8, -502, -132 },
10076 { 0x87625F056C7C4A8B, -475, -124 },
10077 { 0xC9BCFF6034C13053, -449, -116 },
10078 { 0x964E858C91BA2655, -422, -108 },
10079 { 0xDFF9772470297EBD, -396, -100 },
10080 { 0xA6DFBD9FB8E5B88F, -369, -92 },
10081 { 0xF8A95FCF88747D94, -343, -84 },
10082 { 0xB94470938FA89BCF, -316, -76 },
10083 { 0x8A08F0F8BF0F156B, -289, -68 },
10084 { 0xCDB02555653131B6, -263, -60 },
10085 { 0x993FE2C6D07B7FAC, -236, -52 },
10086 { 0xE45C10C42A2B3B06, -210, -44 },
10087 { 0xAA242499697392D3, -183, -36 },
10088 { 0xFD87B5F28300CA0E, -157, -28 },
10089 { 0xBCE5086492111AEB, -130, -20 },
10090 { 0x8CBCCC096F5088CC, -103, -12 },
10091 { 0xD1B71758E219652C, -77, -4 },
10092 { 0x9C40000000000000, -50, 4 },
10093 { 0xE8D4A51000000000, -24, 12 },
10094 { 0xAD78EBC5AC620000, 3, 20 },
10095 { 0x813F3978F8940984, 30, 28 },
10096 { 0xC097CE7BC90715B3, 56, 36 },
10097 { 0x8F7E32CE7BEA5C70, 83, 44 },
10098 { 0xD5D238A4ABE98068, 109, 52 },
10099 { 0x9F4F2726179A2245, 136, 60 },
10100 { 0xED63A231D4C4FB27, 162, 68 },
10101 { 0xB0DE65388CC8ADA8, 189, 76 },
10102 { 0x83C7088E1AAB65DB, 216, 84 },
10103 { 0xC45D1DF942711D9A, 242, 92 },
10104 { 0x924D692CA61BE758, 269, 100 },
10105 { 0xDA01EE641A708DEA, 295, 108 },
10106 { 0xA26DA3999AEF774A, 322, 116 },
10107 { 0xF209787BB47D6B85, 348, 124 },
10108 { 0xB454E4A179DD1877, 375, 132 },
10109 { 0x865B86925B9BC5C2, 402, 140 },
10110 { 0xC83553C5C8965D3D, 428, 148 },
10111 { 0x952AB45CFA97A0B3, 455, 156 },
10112 { 0xDE469FBD99A05FE3, 481, 164 },
10113 { 0xA59BC234DB398C25, 508, 172 },
10114 { 0xF6C69A72A3989F5C, 534, 180 },
10115 { 0xB7DCBF5354E9BECE, 561, 188 },
10116 { 0x88FCF317F22241E2, 588, 196 },
10117 { 0xCC20CE9BD35C78A5, 614, 204 },
10118 { 0x98165AF37B2153DF, 641, 212 },
10119 { 0xE2A0B5DC971F303A, 667, 220 },
10120 { 0xA8D9D1535CE3B396, 694, 228 },
10121 { 0xFB9B7CD9A4A7443C, 720, 236 },
10122 { 0xBB764C4CA7A44410, 747, 244 },
10123 { 0x8BAB8EEFB6409C1A, 774, 252 },
10124 { 0xD01FEF10A657842C, 800, 260 },
10125 { 0x9B10A4E5E9913129, 827, 268 },
10126 { 0xE7109BFBA19C0C9D, 853, 276 },
10127 { 0xAC2820D9623BF429, 880, 284 },
10128 { 0x80444B5E7AA7CF85, 907, 292 },
10129 { 0xBF21E44003ACDD2D, 933, 300 },
10130 { 0x8E679C2F5E44FF8F, 960, 308 },
10131 { 0xD433179D9C8CB841, 986, 316 },
10132 { 0x9E19DB92B4E31BA9, 1013, 324 },
10133 };
10134
10135 // This computation gives exactly the same results for k as
10136 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
10137 // for |e| <= 1500, but doesn't require floating-point operations.
10138 // NB: log_10(2) ~= 78913 / 2^18
10139 assert(e >= -1500);
10140 assert(e <= 1500);
10141 const int f = kAlpha - e - 1;
10142 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
10143
10144 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
10145 assert(index >= 0);
10146 assert(index < kCachedPowersSize);
10147 static_cast<void>(kCachedPowersSize); // Fix warning.
10148
10149 const cached_power cached = kCachedPowers[index];
10150 assert(kAlpha <= cached.e + e + 64);
10151 assert(kGamma >= cached.e + e + 64);
10152
10153 return cached;
10154}
10155
10156/*!
10157For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
10158For n == 0, returns 1 and sets pow10 := 1.
10159*/
10160inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
10161{
10162 // LCOV_EXCL_START
10163 if (n >= 1000000000)
10164 {
10165 pow10 = 1000000000;
10166 return 10;
10167 }
10168 // LCOV_EXCL_STOP
10169 else if (n >= 100000000)
10170 {
10171 pow10 = 100000000;
10172 return 9;
10173 }
10174 else if (n >= 10000000)
10175 {
10176 pow10 = 10000000;
10177 return 8;
10178 }
10179 else if (n >= 1000000)
10180 {
10181 pow10 = 1000000;
10182 return 7;
10183 }
10184 else if (n >= 100000)
10185 {
10186 pow10 = 100000;
10187 return 6;
10188 }
10189 else if (n >= 10000)
10190 {
10191 pow10 = 10000;
10192 return 5;
10193 }
10194 else if (n >= 1000)
10195 {
10196 pow10 = 1000;
10197 return 4;
10198 }
10199 else if (n >= 100)
10200 {
10201 pow10 = 100;
10202 return 3;
10203 }
10204 else if (n >= 10)
10205 {
10206 pow10 = 10;
10207 return 2;
10208 }
10209 else
10210 {
10211 pow10 = 1;
10212 return 1;
10213 }
10214}
10215
10216inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta,
10217 uint64_t rest, uint64_t ten_k)
10218{
10219 assert(len >= 1);
10220 assert(dist <= delta);
10221 assert(rest <= delta);
10222 assert(ten_k > 0);
10223
10224 // <--------------------------- delta ---->
10225 // <---- dist --------->
10226 // --------------[------------------+-------------------]--------------
10227 // M- w M+
10228 //
10229 // ten_k
10230 // <------>
10231 // <---- rest ---->
10232 // --------------[------------------+----+--------------]--------------
10233 // w V
10234 // = buf * 10^k
10235 //
10236 // ten_k represents a unit-in-the-last-place in the decimal representation
10237 // stored in buf.
10238 // Decrement buf by ten_k while this takes buf closer to w.
10239
10240 // The tests are written in this order to avoid overflow in unsigned
10241 // integer arithmetic.
10242
10243 while (rest < dist
10244 and delta - rest >= ten_k
10245 and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
10246 {
10247 assert(buf[len - 1] != '0');
10248 buf[len - 1]--;
10249 rest += ten_k;
10250 }
10251}
10252
10253/*!
10254Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
10255M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
10256*/
10257inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
10258 diyfp M_minus, diyfp w, diyfp M_plus)
10259{
10260 static_assert(kAlpha >= -60, "internal error");
10261 static_assert(kGamma <= -32, "internal error");
10262
10263 // Generates the digits (and the exponent) of a decimal floating-point
10264 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
10265 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
10266 //
10267 // <--------------------------- delta ---->
10268 // <---- dist --------->
10269 // --------------[------------------+-------------------]--------------
10270 // M- w M+
10271 //
10272 // Grisu2 generates the digits of M+ from left to right and stops as soon as
10273 // V is in [M-,M+].
10274
10275 assert(M_plus.e >= kAlpha);
10276 assert(M_plus.e <= kGamma);
10277
10278 uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
10279 uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
10280
10281 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
10282 //
10283 // M+ = f * 2^e
10284 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
10285 // = ((p1 ) * 2^-e + (p2 )) * 2^e
10286 // = p1 + p2 * 2^e
10287
10288 const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
10289
10290 auto p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
10291 uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
10292
10293 // 1)
10294 //
10295 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
10296
10297 assert(p1 > 0);
10298
10299 uint32_t pow10;
10300 const int k = find_largest_pow10(p1, pow10);
10301
10302 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
10303 //
10304 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
10305 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
10306 //
10307 // M+ = p1 + p2 * 2^e
10308 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
10309 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
10310 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
10311 //
10312 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
10313 //
10314 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
10315 //
10316 // but stop as soon as
10317 //
10318 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
10319
10320 int n = k;
10321 while (n > 0)
10322 {
10323 // Invariants:
10324 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
10325 // pow10 = 10^(n-1) <= p1 < 10^n
10326 //
10327 const uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
10328 const uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
10329 //
10330 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
10331 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
10332 //
10333 assert(d <= 9);
10334 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
10335 //
10336 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
10337 //
10338 p1 = r;
10339 n--;
10340 //
10341 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
10342 // pow10 = 10^n
10343 //
10344
10345 // Now check if enough digits have been generated.
10346 // Compute
10347 //
10348 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
10349 //
10350 // Note:
10351 // Since rest and delta share the same exponent e, it suffices to
10352 // compare the significands.
10353 const uint64_t rest = (uint64_t{p1} << -one.e) + p2;
10354 if (rest <= delta)
10355 {
10356 // V = buffer * 10^n, with M- <= V <= M+.
10357
10358 decimal_exponent += n;
10359
10360 // We may now just stop. But instead look if the buffer could be
10361 // decremented to bring V closer to w.
10362 //
10363 // pow10 = 10^n is now 1 ulp in the decimal representation V.
10364 // The rounding procedure works with diyfp's with an implicit
10365 // exponent of e.
10366 //
10367 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
10368 //
10369 const uint64_t ten_n = uint64_t{pow10} << -one.e;
10370 grisu2_round(buffer, length, dist, delta, rest, ten_n);
10371
10372 return;
10373 }
10374
10375 pow10 /= 10;
10376 //
10377 // pow10 = 10^(n-1) <= p1 < 10^n
10378 // Invariants restored.
10379 }
10380
10381 // 2)
10382 //
10383 // The digits of the integral part have been generated:
10384 //
10385 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
10386 // = buffer + p2 * 2^e
10387 //
10388 // Now generate the digits of the fractional part p2 * 2^e.
10389 //
10390 // Note:
10391 // No decimal point is generated: the exponent is adjusted instead.
10392 //
10393 // p2 actually represents the fraction
10394 //
10395 // p2 * 2^e
10396 // = p2 / 2^-e
10397 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
10398 //
10399 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
10400 //
10401 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
10402 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
10403 //
10404 // using
10405 //
10406 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
10407 // = ( d) * 2^-e + ( r)
10408 //
10409 // or
10410 // 10^m * p2 * 2^e = d + r * 2^e
10411 //
10412 // i.e.
10413 //
10414 // M+ = buffer + p2 * 2^e
10415 // = buffer + 10^-m * (d + r * 2^e)
10416 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
10417 //
10418 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
10419
10420 assert(p2 > delta);
10421
10422 int m = 0;
10423 for (;;)
10424 {
10425 // Invariant:
10426 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
10427 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
10428 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
10429 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
10430 //
10431 assert(p2 <= UINT64_MAX / 10);
10432 p2 *= 10;
10433 const uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
10434 const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
10435 //
10436 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
10437 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
10438 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
10439 //
10440 assert(d <= 9);
10441 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
10442 //
10443 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
10444 //
10445 p2 = r;
10446 m++;
10447 //
10448 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
10449 // Invariant restored.
10450
10451 // Check if enough digits have been generated.
10452 //
10453 // 10^-m * p2 * 2^e <= delta * 2^e
10454 // p2 * 2^e <= 10^m * delta * 2^e
10455 // p2 <= 10^m * delta
10456 delta *= 10;
10457 dist *= 10;
10458 if (p2 <= delta)
10459 {
10460 break;
10461 }
10462 }
10463
10464 // V = buffer * 10^-m, with M- <= V <= M+.
10465
10466 decimal_exponent -= m;
10467
10468 // 1 ulp in the decimal representation is now 10^-m.
10469 // Since delta and dist are now scaled by 10^m, we need to do the
10470 // same with ulp in order to keep the units in sync.
10471 //
10472 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
10473 //
10474 const uint64_t ten_m = one.f;
10475 grisu2_round(buffer, length, dist, delta, p2, ten_m);
10476
10477 // By construction this algorithm generates the shortest possible decimal
10478 // number (Loitsch, Theorem 6.2) which rounds back to w.
10479 // For an input number of precision p, at least
10480 //
10481 // N = 1 + ceil(p * log_10(2))
10482 //
10483 // decimal digits are sufficient to identify all binary floating-point
10484 // numbers (Matula, "In-and-Out conversions").
10485 // This implies that the algorithm does not produce more than N decimal
10486 // digits.
10487 //
10488 // N = 17 for p = 53 (IEEE double precision)
10489 // N = 9 for p = 24 (IEEE single precision)
10490}
10491
10492/*!
10493v = buf * 10^decimal_exponent
10494len is the length of the buffer (number of decimal digits)
10495The buffer must be large enough, i.e. >= max_digits10.
10496*/
10497inline void grisu2(char* buf, int& len, int& decimal_exponent,
10498 diyfp m_minus, diyfp v, diyfp m_plus)
10499{
10500 assert(m_plus.e == m_minus.e);
10501 assert(m_plus.e == v.e);
10502
10503 // --------(-----------------------+-----------------------)-------- (A)
10504 // m- v m+
10505 //
10506 // --------------------(-----------+-----------------------)-------- (B)
10507 // m- v m+
10508 //
10509 // First scale v (and m- and m+) such that the exponent is in the range
10510 // [alpha, gamma].
10511
10512 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
10513
10514 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
10515
10516 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
10517 const diyfp w = diyfp::mul(v, c_minus_k);
10518 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
10519 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
10520
10521 // ----(---+---)---------------(---+---)---------------(---+---)----
10522 // w- w w+
10523 // = c*m- = c*v = c*m+
10524 //
10525 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
10526 // w+ are now off by a small amount.
10527 // In fact:
10528 //
10529 // w - v * 10^k < 1 ulp
10530 //
10531 // To account for this inaccuracy, add resp. subtract 1 ulp.
10532 //
10533 // --------+---[---------------(---+---)---------------]---+--------
10534 // w- M- w M+ w+
10535 //
10536 // Now any number in [M-, M+] (bounds included) will round to w when input,
10537 // regardless of how the input rounding algorithm breaks ties.
10538 //
10539 // And digit_gen generates the shortest possible such number in [M-, M+].
10540 // Note that this does not mean that Grisu2 always generates the shortest
10541 // possible number in the interval (m-, m+).
10542 const diyfp M_minus(w_minus.f + 1, w_minus.e);
10543 const diyfp M_plus (w_plus.f - 1, w_plus.e );
10544
10545 decimal_exponent = -cached.k; // = -(-k) = k
10546
10547 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
10548}
10549
10550/*!
10551v = buf * 10^decimal_exponent
10552len is the length of the buffer (number of decimal digits)
10553The buffer must be large enough, i.e. >= max_digits10.
10554*/
10555template <typename FloatType>
10556void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
10557{
10558 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
10559 "internal error: not enough precision");
10560
10561 assert(std::isfinite(value));
10562 assert(value > 0);
10563
10564 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
10565 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
10566 // decimal representations are not exactly "short".
10567 //
10568 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
10569 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
10570 // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
10571 // does.
10572 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
10573 // representation using the corresponding std::from_chars function recovers value exactly". That
10574 // indicates that single precision floating-point numbers should be recovered using
10575 // 'std::strtof'.
10576 //
10577 // NB: If the neighbors are computed for single-precision numbers, there is a single float
10578 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
10579 // value is off by 1 ulp.
10580#if 0
10581 const boundaries w = compute_boundaries(static_cast<double>(value));
10582#else
10583 const boundaries w = compute_boundaries(value);
10584#endif
10585
10586 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
10587}
10588
10589/*!
10590@brief appends a decimal representation of e to buf
10591@return a pointer to the element following the exponent.
10592@pre -1000 < e < 1000
10593*/
10594inline char* append_exponent(char* buf, int e)
10595{
10596 assert(e > -1000);
10597 assert(e < 1000);
10598
10599 if (e < 0)
10600 {
10601 e = -e;
10602 *buf++ = '-';
10603 }
10604 else
10605 {
10606 *buf++ = '+';
10607 }
10608
10609 auto k = static_cast<uint32_t>(e);
10610 if (k < 10)
10611 {
10612 // Always print at least two digits in the exponent.
10613 // This is for compatibility with printf("%g").
10614 *buf++ = '0';
10615 *buf++ = static_cast<char>('0' + k);
10616 }
10617 else if (k < 100)
10618 {
10619 *buf++ = static_cast<char>('0' + k / 10);
10620 k %= 10;
10621 *buf++ = static_cast<char>('0' + k);
10622 }
10623 else
10624 {
10625 *buf++ = static_cast<char>('0' + k / 100);
10626 k %= 100;
10627 *buf++ = static_cast<char>('0' + k / 10);
10628 k %= 10;
10629 *buf++ = static_cast<char>('0' + k);
10630 }
10631
10632 return buf;
10633}
10634
10635/*!
10636@brief prettify v = buf * 10^decimal_exponent
10637
10638If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
10639notation. Otherwise it will be printed in exponential notation.
10640
10641@pre min_exp < 0
10642@pre max_exp > 0
10643*/
10644inline char* format_buffer(char* buf, int len, int decimal_exponent,
10645 int min_exp, int max_exp)
10646{
10647 assert(min_exp < 0);
10648 assert(max_exp > 0);
10649
10650 const int k = len;
10651 const int n = len + decimal_exponent;
10652
10653 // v = buf * 10^(n-k)
10654 // k is the length of the buffer (number of decimal digits)
10655 // n is the position of the decimal point relative to the start of the buffer.
10656
10657 if (k <= n and n <= max_exp)
10658 {
10659 // digits[000]
10660 // len <= max_exp + 2
10661
10662 std::memset(buf + k, '0', static_cast<size_t>(n - k));
10663 // Make it look like a floating-point number (#362, #378)
10664 buf[n + 0] = '.';
10665 buf[n + 1] = '0';
10666 return buf + (n + 2);
10667 }
10668
10669 if (0 < n and n <= max_exp)
10670 {
10671 // dig.its
10672 // len <= max_digits10 + 1
10673
10674 assert(k > n);
10675
10676 std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
10677 buf[n] = '.';
10678 return buf + (k + 1);
10679 }
10680
10681 if (min_exp < n and n <= 0)
10682 {
10683 // 0.[000]digits
10684 // len <= 2 + (-min_exp - 1) + max_digits10
10685
10686 std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
10687 buf[0] = '0';
10688 buf[1] = '.';
10689 std::memset(buf + 2, '0', static_cast<size_t>(-n));
10690 return buf + (2 + (-n) + k);
10691 }
10692
10693 if (k == 1)
10694 {
10695 // dE+123
10696 // len <= 1 + 5
10697
10698 buf += 1;
10699 }
10700 else
10701 {
10702 // d.igitsE+123
10703 // len <= max_digits10 + 1 + 5
10704
10705 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
10706 buf[1] = '.';
10707 buf += 1 + k;
10708 }
10709
10710 *buf++ = 'e';
10711 return append_exponent(buf, n - 1);
10712}
10713
10714} // namespace dtoa_impl
10715
10716/*!
10717@brief generates a decimal representation of the floating-point number value in [first, last).
10718
10719The format of the resulting decimal representation is similar to printf's %g
10720format. Returns an iterator pointing past-the-end of the decimal representation.
10721
10722@note The input number must be finite, i.e. NaN's and Inf's are not supported.
10723@note The buffer must be large enough.
10724@note The result is NOT null-terminated.
10725*/
10726template <typename FloatType>
10727char* to_chars(char* first, const char* last, FloatType value)
10728{
10729 static_cast<void>(last); // maybe unused - fix warning
10730 assert(std::isfinite(value));
10731
10732 // Use signbit(value) instead of (value < 0) since signbit works for -0.
10733 if (std::signbit(value))
10734 {
10735 value = -value;
10736 *first++ = '-';
10737 }
10738
10739 if (value == 0) // +-0
10740 {
10741 *first++ = '0';
10742 // Make it look like a floating-point number (#362, #378)
10743 *first++ = '.';
10744 *first++ = '0';
10745 return first;
10746 }
10747
10748 assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
10749
10750 // Compute v = buffer * 10^decimal_exponent.
10751 // The decimal digits are stored in the buffer, which needs to be interpreted
10752 // as an unsigned decimal integer.
10753 // len is the length of the buffer, i.e. the number of decimal digits.
10754 int len = 0;
10755 int decimal_exponent = 0;
10756 dtoa_impl::grisu2(first, len, decimal_exponent, value);
10757
10758 assert(len <= std::numeric_limits<FloatType>::max_digits10);
10759
10760 // Format the buffer like printf("%.*g", prec, value)
10761 constexpr int kMinExp = -4;
10762 // Use digits10 here to increase compatibility with version 2.
10763 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
10764
10765 assert(last - first >= kMaxExp + 2);
10766 assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
10767 assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
10768
10769 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
10770}
10771
10772} // namespace detail
10773} // namespace nlohmann
10774
10775// #include <nlohmann/detail/macro_scope.hpp>
10776
10777// #include <nlohmann/detail/meta/cpp_future.hpp>
10778
10779// #include <nlohmann/detail/output/binary_writer.hpp>
10780
10781// #include <nlohmann/detail/output/output_adapters.hpp>
10782
10783// #include <nlohmann/detail/value_t.hpp>
10784
10785
10786namespace nlohmann
10787{
10788namespace detail
10789{
10790///////////////////
10791// serialization //
10792///////////////////
10793
10794/// how to treat decoding errors
10795enum class error_handler_t
10796{
10797 strict, ///< throw a type_error exception in case of invalid UTF-8
10798 replace, ///< replace invalid UTF-8 sequences with U+FFFD
10799 ignore ///< ignore invalid UTF-8 sequences
10800};
10801
10802template<typename BasicJsonType>
10803class serializer
10804{
10805 using string_t = typename BasicJsonType::string_t;
10806 using number_float_t = typename BasicJsonType::number_float_t;
10807 using number_integer_t = typename BasicJsonType::number_integer_t;
10808 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10809 static constexpr uint8_t UTF8_ACCEPT = 0;
10810 static constexpr uint8_t UTF8_REJECT = 1;
10811
10812 public:
10813 /*!
10814 @param[in] s output stream to serialize to
10815 @param[in] ichar indentation character to use
10816 @param[in] error_handler_ how to react on decoding errors
10817 */
10818 serializer(output_adapter_t<char> s, const char ichar,
10819 error_handler_t error_handler_ = error_handler_t::strict)
10820 : o(std::move(s))
10821 , loc(std::localeconv())
10822 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep))
10823 , decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point))
10824 , indent_char(ichar)
10825 , indent_string(512, indent_char)
10826 , error_handler(error_handler_)
10827 {}
10828
10829 // delete because of pointer members
10830 serializer(const serializer&) = delete;
10831 serializer& operator=(const serializer&) = delete;
10832 serializer(serializer&&) = delete;
10833 serializer& operator=(serializer&&) = delete;
10834 ~serializer() = default;
10835
10836 /*!
10837 @brief internal implementation of the serialization function
10838
10839 This function is called by the public member function dump and organizes
10840 the serialization internally. The indentation level is propagated as
10841 additional parameter. In case of arrays and objects, the function is
10842 called recursively.
10843
10844 - strings and object keys are escaped using `escape_string()`
10845 - integer numbers are converted implicitly via `operator<<`
10846 - floating-point numbers are converted to a string using `"%g"` format
10847
10848 @param[in] val value to serialize
10849 @param[in] pretty_print whether the output shall be pretty-printed
10850 @param[in] indent_step the indent level
10851 @param[in] current_indent the current indent level (only used internally)
10852 */
10853 void dump(const BasicJsonType& val, const bool pretty_print,
10854 const bool ensure_ascii,
10855 const unsigned int indent_step,
10856 const unsigned int current_indent = 0)
10857 {
10858 switch (val.m_type)
10859 {
10860 case value_t::object:
10861 {
10862 if (val.m_value.object->empty())
10863 {
10864 o->write_characters("{}", 2);
10865 return;
10866 }
10867
10868 if (pretty_print)
10869 {
10870 o->write_characters("{\n", 2);
10871
10872 // variable to hold indentation for recursive calls
10873 const auto new_indent = current_indent + indent_step;
10874 if (JSON_UNLIKELY(indent_string.size() < new_indent))
10875 {
10876 indent_string.resize(indent_string.size() * 2, ' ');
10877 }
10878
10879 // first n-1 elements
10880 auto i = val.m_value.object->cbegin();
10881 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
10882 {
10883 o->write_characters(indent_string.c_str(), new_indent);
10884 o->write_character('\"');
10885 dump_escaped(i->first, ensure_ascii);
10886 o->write_characters("\": ", 3);
10887 dump(i->second, true, ensure_ascii, indent_step, new_indent);
10888 o->write_characters(",\n", 2);
10889 }
10890
10891 // last element
10892 assert(i != val.m_value.object->cend());
10893 assert(std::next(i) == val.m_value.object->cend());
10894 o->write_characters(indent_string.c_str(), new_indent);
10895 o->write_character('\"');
10896 dump_escaped(i->first, ensure_ascii);
10897 o->write_characters("\": ", 3);
10898 dump(i->second, true, ensure_ascii, indent_step, new_indent);
10899
10900 o->write_character('\n');
10901 o->write_characters(indent_string.c_str(), current_indent);
10902 o->write_character('}');
10903 }
10904 else
10905 {
10906 o->write_character('{');
10907
10908 // first n-1 elements
10909 auto i = val.m_value.object->cbegin();
10910 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
10911 {
10912 o->write_character('\"');
10913 dump_escaped(i->first, ensure_ascii);
10914 o->write_characters("\":", 2);
10915 dump(i->second, false, ensure_ascii, indent_step, current_indent);
10916 o->write_character(',');
10917 }
10918
10919 // last element
10920 assert(i != val.m_value.object->cend());
10921 assert(std::next(i) == val.m_value.object->cend());
10922 o->write_character('\"');
10923 dump_escaped(i->first, ensure_ascii);
10924 o->write_characters("\":", 2);
10925 dump(i->second, false, ensure_ascii, indent_step, current_indent);
10926
10927 o->write_character('}');
10928 }
10929
10930 return;
10931 }
10932
10933 case value_t::array:
10934 {
10935 if (val.m_value.array->empty())
10936 {
10937 o->write_characters("[]", 2);
10938 return;
10939 }
10940
10941 if (pretty_print)
10942 {
10943 o->write_characters("[\n", 2);
10944
10945 // variable to hold indentation for recursive calls
10946 const auto new_indent = current_indent + indent_step;
10947 if (JSON_UNLIKELY(indent_string.size() < new_indent))
10948 {
10949 indent_string.resize(indent_string.size() * 2, ' ');
10950 }
10951
10952 // first n-1 elements
10953 for (auto i = val.m_value.array->cbegin();
10954 i != val.m_value.array->cend() - 1; ++i)
10955 {
10956 o->write_characters(indent_string.c_str(), new_indent);
10957 dump(*i, true, ensure_ascii, indent_step, new_indent);
10958 o->write_characters(",\n", 2);
10959 }
10960
10961 // last element
10962 assert(not val.m_value.array->empty());
10963 o->write_characters(indent_string.c_str(), new_indent);
10964 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
10965
10966 o->write_character('\n');
10967 o->write_characters(indent_string.c_str(), current_indent);
10968 o->write_character(']');
10969 }
10970 else
10971 {
10972 o->write_character('[');
10973
10974 // first n-1 elements
10975 for (auto i = val.m_value.array->cbegin();
10976 i != val.m_value.array->cend() - 1; ++i)
10977 {
10978 dump(*i, false, ensure_ascii, indent_step, current_indent);
10979 o->write_character(',');
10980 }
10981
10982 // last element
10983 assert(not val.m_value.array->empty());
10984 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
10985
10986 o->write_character(']');
10987 }
10988
10989 return;
10990 }
10991
10992 case value_t::string:
10993 {
10994 o->write_character('\"');
10995 dump_escaped(*val.m_value.string, ensure_ascii);
10996 o->write_character('\"');
10997 return;
10998 }
10999
11000 case value_t::boolean:
11001 {
11002 if (val.m_value.boolean)
11003 {
11004 o->write_characters("true", 4);
11005 }
11006 else
11007 {
11008 o->write_characters("false", 5);
11009 }
11010 return;
11011 }
11012
11013 case value_t::number_integer:
11014 {
11015 dump_integer(val.m_value.number_integer);
11016 return;
11017 }
11018
11019 case value_t::number_unsigned:
11020 {
11021 dump_integer(val.m_value.number_unsigned);
11022 return;
11023 }
11024
11025 case value_t::number_float:
11026 {
11027 dump_float(val.m_value.number_float);
11028 return;
11029 }
11030
11031 case value_t::discarded:
11032 {
11033 o->write_characters("<discarded>", 11);
11034 return;
11035 }
11036
11037 case value_t::null:
11038 {
11039 o->write_characters("null", 4);
11040 return;
11041 }
11042 }
11043 }
11044
11045 private:
11046 /*!
11047 @brief dump escaped string
11048
11049 Escape a string by replacing certain special characters by a sequence of an
11050 escape character (backslash) and another character and other control
11051 characters by a sequence of "\u" followed by a four-digit hex
11052 representation. The escaped string is written to output stream @a o.
11053
11054 @param[in] s the string to escape
11055 @param[in] ensure_ascii whether to escape non-ASCII characters with
11056 \uXXXX sequences
11057
11058 @complexity Linear in the length of string @a s.
11059 */
11060 void dump_escaped(const string_t& s, const bool ensure_ascii)
11061 {
11062 uint32_t codepoint;
11063 uint8_t state = UTF8_ACCEPT;
11064 std::size_t bytes = 0; // number of bytes written to string_buffer
11065
11066 // number of bytes written at the point of the last valid byte
11067 std::size_t bytes_after_last_accept = 0;
11068 std::size_t undumped_chars = 0;
11069
11070 for (std::size_t i = 0; i < s.size(); ++i)
11071 {
11072 const auto byte = static_cast<uint8_t>(s[i]);
11073
11074 switch (decode(state, codepoint, byte))
11075 {
11076 case UTF8_ACCEPT: // decode found a new code point
11077 {
11078 switch (codepoint)
11079 {
11080 case 0x08: // backspace
11081 {
11082 string_buffer[bytes++] = '\\';
11083 string_buffer[bytes++] = 'b';
11084 break;
11085 }
11086
11087 case 0x09: // horizontal tab
11088 {
11089 string_buffer[bytes++] = '\\';
11090 string_buffer[bytes++] = 't';
11091 break;
11092 }
11093
11094 case 0x0A: // newline
11095 {
11096 string_buffer[bytes++] = '\\';
11097 string_buffer[bytes++] = 'n';
11098 break;
11099 }
11100
11101 case 0x0C: // formfeed
11102 {
11103 string_buffer[bytes++] = '\\';
11104 string_buffer[bytes++] = 'f';
11105 break;
11106 }
11107
11108 case 0x0D: // carriage return
11109 {
11110 string_buffer[bytes++] = '\\';
11111 string_buffer[bytes++] = 'r';
11112 break;
11113 }
11114
11115 case 0x22: // quotation mark
11116 {
11117 string_buffer[bytes++] = '\\';
11118 string_buffer[bytes++] = '\"';
11119 break;
11120 }
11121
11122 case 0x5C: // reverse solidus
11123 {
11124 string_buffer[bytes++] = '\\';
11125 string_buffer[bytes++] = '\\';
11126 break;
11127 }
11128
11129 default:
11130 {
11131 // escape control characters (0x00..0x1F) or, if
11132 // ensure_ascii parameter is used, non-ASCII characters
11133 if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
11134 {
11135 if (codepoint <= 0xFFFF)
11136 {
11137 std::snprintf(string_buffer.data() + bytes, 7, "\\u%04x",
11138 static_cast<uint16_t>(codepoint));
11139 bytes += 6;
11140 }
11141 else
11142 {
11143 std::snprintf(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
11144 static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
11145 static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
11146 bytes += 12;
11147 }
11148 }
11149 else
11150 {
11151 // copy byte to buffer (all previous bytes
11152 // been copied have in default case above)
11153 string_buffer[bytes++] = s[i];
11154 }
11155 break;
11156 }
11157 }
11158
11159 // write buffer and reset index; there must be 13 bytes
11160 // left, as this is the maximal number of bytes to be
11161 // written ("\uxxxx\uxxxx\0") for one code point
11162 if (string_buffer.size() - bytes < 13)
11163 {
11164 o->write_characters(string_buffer.data(), bytes);
11165 bytes = 0;
11166 }
11167
11168 // remember the byte position of this accept
11169 bytes_after_last_accept = bytes;
11170 undumped_chars = 0;
11171 break;
11172 }
11173
11174 case UTF8_REJECT: // decode found invalid UTF-8 byte
11175 {
11176 switch (error_handler)
11177 {
11178 case error_handler_t::strict:
11179 {
11180 std::string sn(3, '\0');
11181 snprintf(&sn[0], sn.size(), "%.2X", byte);
11182 JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
11183 }
11184
11185 case error_handler_t::ignore:
11186 case error_handler_t::replace:
11187 {
11188 // in case we saw this character the first time, we
11189 // would like to read it again, because the byte
11190 // may be OK for itself, but just not OK for the
11191 // previous sequence
11192 if (undumped_chars > 0)
11193 {
11194 --i;
11195 }
11196
11197 // reset length buffer to the last accepted index;
11198 // thus removing/ignoring the invalid characters
11199 bytes = bytes_after_last_accept;
11200
11201 if (error_handler == error_handler_t::replace)
11202 {
11203 // add a replacement character
11204 if (ensure_ascii)
11205 {
11206 string_buffer[bytes++] = '\\';
11207 string_buffer[bytes++] = 'u';
11208 string_buffer[bytes++] = 'f';
11209 string_buffer[bytes++] = 'f';
11210 string_buffer[bytes++] = 'f';
11211 string_buffer[bytes++] = 'd';
11212 }
11213 else
11214 {
11215 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
11216 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
11217 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
11218 }
11219 bytes_after_last_accept = bytes;
11220 }
11221
11222 undumped_chars = 0;
11223
11224 // continue processing the string
11225 state = UTF8_ACCEPT;
11226 break;
11227 }
11228 }
11229 break;
11230 }
11231
11232 default: // decode found yet incomplete multi-byte code point
11233 {
11234 if (not ensure_ascii)
11235 {
11236 // code point will not be escaped - copy byte to buffer
11237 string_buffer[bytes++] = s[i];
11238 }
11239 ++undumped_chars;
11240 break;
11241 }
11242 }
11243 }
11244
11245 // we finished processing the string
11246 if (JSON_LIKELY(state == UTF8_ACCEPT))
11247 {
11248 // write buffer
11249 if (bytes > 0)
11250 {
11251 o->write_characters(string_buffer.data(), bytes);
11252 }
11253 }
11254 else
11255 {
11256 // we finish reading, but do not accept: string was incomplete
11257 switch (error_handler)
11258 {
11259 case error_handler_t::strict:
11260 {
11261 std::string sn(3, '\0');
11262 snprintf(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
11263 JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
11264 }
11265
11266 case error_handler_t::ignore:
11267 {
11268 // write all accepted bytes
11269 o->write_characters(string_buffer.data(), bytes_after_last_accept);
11270 break;
11271 }
11272
11273 case error_handler_t::replace:
11274 {
11275 // write all accepted bytes
11276 o->write_characters(string_buffer.data(), bytes_after_last_accept);
11277 // add a replacement character
11278 if (ensure_ascii)
11279 {
11280 o->write_characters("\\ufffd", 6);
11281 }
11282 else
11283 {
11284 o->write_characters("\xEF\xBF\xBD", 3);
11285 }
11286 break;
11287 }
11288 }
11289 }
11290 }
11291
11292 /*!
11293 @brief dump an integer
11294
11295 Dump a given integer to output stream @a o. Works internally with
11296 @a number_buffer.
11297
11298 @param[in] x integer number (signed or unsigned) to dump
11299 @tparam NumberType either @a number_integer_t or @a number_unsigned_t
11300 */
11301 template<typename NumberType, detail::enable_if_t<
11302 std::is_same<NumberType, number_unsigned_t>::value or
11303 std::is_same<NumberType, number_integer_t>::value,
11304 int> = 0>
11305 void dump_integer(NumberType x)
11306 {
11307 // special case for "0"
11308 if (x == 0)
11309 {
11310 o->write_character('0');
11311 return;
11312 }
11313
11314 const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not (x >= 0); // see issue #755
11315 std::size_t i = 0;
11316
11317 while (x != 0)
11318 {
11319 // spare 1 byte for '\0'
11320 assert(i < number_buffer.size() - 1);
11321
11322 const auto digit = std::labs(static_cast<long>(x % 10));
11323 number_buffer[i++] = static_cast<char>('0' + digit);
11324 x /= 10;
11325 }
11326
11327 if (is_negative)
11328 {
11329 // make sure there is capacity for the '-'
11330 assert(i < number_buffer.size() - 2);
11331 number_buffer[i++] = '-';
11332 }
11333
11334 std::reverse(number_buffer.begin(), number_buffer.begin() + i);
11335 o->write_characters(number_buffer.data(), i);
11336 }
11337
11338 /*!
11339 @brief dump a floating-point number
11340
11341 Dump a given floating-point number to output stream @a o. Works internally
11342 with @a number_buffer.
11343
11344 @param[in] x floating-point number to dump
11345 */
11346 void dump_float(number_float_t x)
11347 {
11348 // NaN / inf
11349 if (not std::isfinite(x))
11350 {
11351 o->write_characters("null", 4);
11352 return;
11353 }
11354
11355 // If number_float_t is an IEEE-754 single or double precision number,
11356 // use the Grisu2 algorithm to produce short numbers which are
11357 // guaranteed to round-trip, using strtof and strtod, resp.
11358 //
11359 // NB: The test below works if <long double> == <double>.
11360 static constexpr bool is_ieee_single_or_double
11361 = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
11362 (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
11363
11364 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
11365 }
11366
11367 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
11368 {
11369 char* begin = number_buffer.data();
11370 char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
11371
11372 o->write_characters(begin, static_cast<size_t>(end - begin));
11373 }
11374
11375 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
11376 {
11377 // get number of digits for a float -> text -> float round-trip
11378 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
11379
11380 // the actual conversion
11381 std::ptrdiff_t len = snprintf(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
11382
11383 // negative value indicates an error
11384 assert(len > 0);
11385 // check if buffer was large enough
11386 assert(static_cast<std::size_t>(len) < number_buffer.size());
11387
11388 // erase thousands separator
11389 if (thousands_sep != '\0')
11390 {
11391 const auto end = std::remove(number_buffer.begin(),
11392 number_buffer.begin() + len, thousands_sep);
11393 std::fill(end, number_buffer.end(), '\0');
11394 assert((end - number_buffer.begin()) <= len);
11395 len = (end - number_buffer.begin());
11396 }
11397
11398 // convert decimal point to '.'
11399 if (decimal_point != '\0' and decimal_point != '.')
11400 {
11401 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
11402 if (dec_pos != number_buffer.end())
11403 {
11404 *dec_pos = '.';
11405 }
11406 }
11407
11408 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
11409
11410 // determine if need to append ".0"
11411 const bool value_is_int_like =
11412 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
11413 [](char c)
11414 {
11415 return (c == '.' or c == 'e');
11416 });
11417
11418 if (value_is_int_like)
11419 {
11420 o->write_characters(".0", 2);
11421 }
11422 }
11423
11424 /*!
11425 @brief check whether a string is UTF-8 encoded
11426
11427 The function checks each byte of a string whether it is UTF-8 encoded. The
11428 result of the check is stored in the @a state parameter. The function must
11429 be called initially with state 0 (accept). State 1 means the string must
11430 be rejected, because the current byte is not allowed. If the string is
11431 completely processed, but the state is non-zero, the string ended
11432 prematurely; that is, the last byte indicated more bytes should have
11433 followed.
11434
11435 @param[in,out] state the state of the decoding
11436 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
11437 @param[in] byte next byte to decode
11438 @return new state
11439
11440 @note The function has been edited: a std::array is used.
11441
11442 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
11443 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
11444 */
11445 static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept
11446 {
11447 static const std::array<uint8_t, 400> utf8d =
11448 {
11449 {
11450 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, // 00..1F
11451 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, // 20..3F
11452 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, // 40..5F
11453 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, // 60..7F
11454 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
11455 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
11456 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
11457 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
11458 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
11459 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
11460 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
11461 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
11462 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
11463 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
11464 }
11465 };
11466
11467 const uint8_t type = utf8d[byte];
11468
11469 codep = (state != UTF8_ACCEPT)
11470 ? (byte & 0x3fu) | (codep << 6)
11471 : static_cast<uint32_t>(0xff >> type) & (byte);
11472
11473 state = utf8d[256u + state * 16u + type];
11474 return state;
11475 }
11476
11477 private:
11478 /// the output of the serializer
11479 output_adapter_t<char> o = nullptr;
11480
11481 /// a (hopefully) large enough character buffer
11482 std::array<char, 64> number_buffer{{}};
11483
11484 /// the locale
11485 const std::lconv* loc = nullptr;
11486 /// the locale's thousand separator character
11487 const char thousands_sep = '\0';
11488 /// the locale's decimal point character
11489 const char decimal_point = '\0';
11490
11491 /// string buffer
11492 std::array<char, 512> string_buffer{{}};
11493
11494 /// the indentation character
11495 const char indent_char;
11496 /// the indentation string
11497 string_t indent_string;
11498
11499 /// error_handler how to react on decoding errors
11500 const error_handler_t error_handler;
11501};
11502} // namespace detail
11503} // namespace nlohmann
11504
11505// #include <nlohmann/detail/json_ref.hpp>
11506
11507
11508#include <initializer_list>
11509#include <utility>
11510
11511// #include <nlohmann/detail/meta/type_traits.hpp>
11512
11513
11514namespace nlohmann
11515{
11516namespace detail
11517{
11518template<typename BasicJsonType>
11519class json_ref
11520{
11521 public:
11522 using value_type = BasicJsonType;
11523
11524 json_ref(value_type&& value)
11525 : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
11526 {}
11527
11528 json_ref(const value_type& value)
11529 : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
11530 {}
11531
11532 json_ref(std::initializer_list<json_ref> init)
11533 : owned_value(init), value_ref(&owned_value), is_rvalue(true)
11534 {}
11535
11536 template <
11537 class... Args,
11538 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
11539 json_ref(Args && ... args)
11540 : owned_value(std::forward<Args>(args)...), value_ref(&owned_value),
11541 is_rvalue(true) {}
11542
11543 // class should be movable only
11544 json_ref(json_ref&&) = default;
11545 json_ref(const json_ref&) = delete;
11546 json_ref& operator=(const json_ref&) = delete;
11547 json_ref& operator=(json_ref&&) = delete;
11548 ~json_ref() = default;
11549
11550 value_type moved_or_copied() const
11551 {
11552 if (is_rvalue)
11553 {
11554 return std::move(*value_ref);
11555 }
11556 return *value_ref;
11557 }
11558
11559 value_type const& operator*() const
11560 {
11561 return *static_cast<value_type const*>(value_ref);
11562 }
11563
11564 value_type const* operator->() const
11565 {
11566 return static_cast<value_type const*>(value_ref);
11567 }
11568
11569 private:
11570 mutable value_type owned_value = nullptr;
11571 value_type* value_ref = nullptr;
11572 const bool is_rvalue;
11573};
11574} // namespace detail
11575} // namespace nlohmann
11576
11577// #include <nlohmann/detail/json_pointer.hpp>
11578
11579
11580#include <cassert> // assert
11581#include <numeric> // accumulate
11582#include <string> // string
11583#include <vector> // vector
11584
11585// #include <nlohmann/detail/macro_scope.hpp>
11586
11587// #include <nlohmann/detail/exceptions.hpp>
11588
11589// #include <nlohmann/detail/value_t.hpp>
11590
11591
11592namespace nlohmann
11593{
11594template<typename BasicJsonType>
11595class json_pointer
11596{
11597 // allow basic_json to access private members
11598 NLOHMANN_BASIC_JSON_TPL_DECLARATION
11599 friend class basic_json;
11600
11601 public:
11602 /*!
11603 @brief create JSON pointer
11604
11605 Create a JSON pointer according to the syntax described in
11606 [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
11607
11608 @param[in] s string representing the JSON pointer; if omitted, the empty
11609 string is assumed which references the whole JSON value
11610
11611 @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
11612 not begin with a slash (`/`); see example below
11613
11614 @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
11615 not followed by `0` (representing `~`) or `1` (representing `/`); see
11616 example below
11617
11618 @liveexample{The example shows the construction several valid JSON pointers
11619 as well as the exceptional behavior.,json_pointer}
11620
11621 @since version 2.0.0
11622 */
11623 explicit json_pointer(const std::string& s = "")
11624 : reference_tokens(split(s))
11625 {}
11626
11627 /*!
11628 @brief return a string representation of the JSON pointer
11629
11630 @invariant For each JSON pointer `ptr`, it holds:
11631 @code {.cpp}
11632 ptr == json_pointer(ptr.to_string());
11633 @endcode
11634
11635 @return a string representation of the JSON pointer
11636
11637 @liveexample{The example shows the result of `to_string`.,
11638 json_pointer__to_string}
11639
11640 @since version 2.0.0
11641 */
11642 std::string to_string() const
11643 {
11644 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
11645 std::string{},
11646 [](const std::string & a, const std::string & b)
11647 {
11648 return a + "/" + escape(b);
11649 });
11650 }
11651
11652 /// @copydoc to_string()
11653 operator std::string() const
11654 {
11655 return to_string();
11656 }
11657
11658 /*!
11659 @param[in] s reference token to be converted into an array index
11660
11661 @return integer representation of @a s
11662
11663 @throw out_of_range.404 if string @a s could not be converted to an integer
11664 */
11665 static int array_index(const std::string& s)
11666 {
11667 std::size_t processed_chars = 0;
11668 const int res = std::stoi(s, &processed_chars);
11669
11670 // check if the string was completely read
11671 if (JSON_UNLIKELY(processed_chars != s.size()))
11672 {
11673 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
11674 }
11675
11676 return res;
11677 }
11678
11679 private:
11680 /*!
11681 @brief remove and return last reference pointer
11682 @throw out_of_range.405 if JSON pointer has no parent
11683 */
11684 std::string pop_back()
11685 {
11686 if (JSON_UNLIKELY(is_root()))
11687 {
11688 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11689 }
11690
11691 auto last = reference_tokens.back();
11692 reference_tokens.pop_back();
11693 return last;
11694 }
11695
11696 /// return whether pointer points to the root document
11697 bool is_root() const noexcept
11698 {
11699 return reference_tokens.empty();
11700 }
11701
11702 json_pointer top() const
11703 {
11704 if (JSON_UNLIKELY(is_root()))
11705 {
11706 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11707 }
11708
11709 json_pointer result = *this;
11710 result.reference_tokens = {reference_tokens[0]};
11711 return result;
11712 }
11713
11714 /*!
11715 @brief create and return a reference to the pointed to value
11716
11717 @complexity Linear in the number of reference tokens.
11718
11719 @throw parse_error.109 if array index is not a number
11720 @throw type_error.313 if value cannot be unflattened
11721 */
11722 BasicJsonType& get_and_create(BasicJsonType& j) const
11723 {
11724 using size_type = typename BasicJsonType::size_type;
11725 auto result = &j;
11726
11727 // in case no reference tokens exist, return a reference to the JSON value
11728 // j which will be overwritten by a primitive value
11729 for (const auto& reference_token : reference_tokens)
11730 {
11731 switch (result->m_type)
11732 {
11733 case detail::value_t::null:
11734 {
11735 if (reference_token == "0")
11736 {
11737 // start a new array if reference token is 0
11738 result = &result->operator[](0);
11739 }
11740 else
11741 {
11742 // start a new object otherwise
11743 result = &result->operator[](reference_token);
11744 }
11745 break;
11746 }
11747
11748 case detail::value_t::object:
11749 {
11750 // create an entry in the object
11751 result = &result->operator[](reference_token);
11752 break;
11753 }
11754
11755 case detail::value_t::array:
11756 {
11757 // create an entry in the array
11758 JSON_TRY
11759 {
11760 result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
11761 }
11762 JSON_CATCH(std::invalid_argument&)
11763 {
11764 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
11765 }
11766 break;
11767 }
11768
11769 /*
11770 The following code is only reached if there exists a reference
11771 token _and_ the current value is primitive. In this case, we have
11772 an error situation, because primitive values may only occur as
11773 single value; that is, with an empty list of reference tokens.
11774 */
11775 default:
11776 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
11777 }
11778 }
11779
11780 return *result;
11781 }
11782
11783 /*!
11784 @brief return a reference to the pointed to value
11785
11786 @note This version does not throw if a value is not present, but tries to
11787 create nested values instead. For instance, calling this function
11788 with pointer `"/this/that"` on a null value is equivalent to calling
11789 `operator[]("this").operator[]("that")` on that value, effectively
11790 changing the null value to an object.
11791
11792 @param[in] ptr a JSON value
11793
11794 @return reference to the JSON value pointed to by the JSON pointer
11795
11796 @complexity Linear in the length of the JSON pointer.
11797
11798 @throw parse_error.106 if an array index begins with '0'
11799 @throw parse_error.109 if an array index was not a number
11800 @throw out_of_range.404 if the JSON pointer can not be resolved
11801 */
11802 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
11803 {
11804 using size_type = typename BasicJsonType::size_type;
11805 for (const auto& reference_token : reference_tokens)
11806 {
11807 // convert null values to arrays or objects before continuing
11808 if (ptr->m_type == detail::value_t::null)
11809 {
11810 // check if reference token is a number
11811 const bool nums =
11812 std::all_of(reference_token.begin(), reference_token.end(),
11813 [](const char x)
11814 {
11815 return (x >= '0' and x <= '9');
11816 });
11817
11818 // change value to array for numbers or "-" or to object otherwise
11819 *ptr = (nums or reference_token == "-")
11820 ? detail::value_t::array
11821 : detail::value_t::object;
11822 }
11823
11824 switch (ptr->m_type)
11825 {
11826 case detail::value_t::object:
11827 {
11828 // use unchecked object access
11829 ptr = &ptr->operator[](reference_token);
11830 break;
11831 }
11832
11833 case detail::value_t::array:
11834 {
11835 // error condition (cf. RFC 6901, Sect. 4)
11836 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
11837 {
11838 JSON_THROW(detail::parse_error::create(106, 0,
11839 "array index '" + reference_token +
11840 "' must not begin with '0'"));
11841 }
11842
11843 if (reference_token == "-")
11844 {
11845 // explicitly treat "-" as index beyond the end
11846 ptr = &ptr->operator[](ptr->m_value.array->size());
11847 }
11848 else
11849 {
11850 // convert array index to number; unchecked access
11851 JSON_TRY
11852 {
11853 ptr = &ptr->operator[](
11854 static_cast<size_type>(array_index(reference_token)));
11855 }
11856 JSON_CATCH(std::invalid_argument&)
11857 {
11858 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
11859 }
11860 }
11861 break;
11862 }
11863
11864 default:
11865 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
11866 }
11867 }
11868
11869 return *ptr;
11870 }
11871
11872 /*!
11873 @throw parse_error.106 if an array index begins with '0'
11874 @throw parse_error.109 if an array index was not a number
11875 @throw out_of_range.402 if the array index '-' is used
11876 @throw out_of_range.404 if the JSON pointer can not be resolved
11877 */
11878 BasicJsonType& get_checked(BasicJsonType* ptr) const
11879 {
11880 using size_type = typename BasicJsonType::size_type;
11881 for (const auto& reference_token : reference_tokens)
11882 {
11883 switch (ptr->m_type)
11884 {
11885 case detail::value_t::object:
11886 {
11887 // note: at performs range check
11888 ptr = &ptr->at(reference_token);
11889 break;
11890 }
11891
11892 case detail::value_t::array:
11893 {
11894 if (JSON_UNLIKELY(reference_token == "-"))
11895 {
11896 // "-" always fails the range check
11897 JSON_THROW(detail::out_of_range::create(402,
11898 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
11899 ") is out of range"));
11900 }
11901
11902 // error condition (cf. RFC 6901, Sect. 4)
11903 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
11904 {
11905 JSON_THROW(detail::parse_error::create(106, 0,
11906 "array index '" + reference_token +
11907 "' must not begin with '0'"));
11908 }
11909
11910 // note: at performs range check
11911 JSON_TRY
11912 {
11913 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
11914 }
11915 JSON_CATCH(std::invalid_argument&)
11916 {
11917 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
11918 }
11919 break;
11920 }
11921
11922 default:
11923 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
11924 }
11925 }
11926
11927 return *ptr;
11928 }
11929
11930 /*!
11931 @brief return a const reference to the pointed to value
11932
11933 @param[in] ptr a JSON value
11934
11935 @return const reference to the JSON value pointed to by the JSON
11936 pointer
11937
11938 @throw parse_error.106 if an array index begins with '0'
11939 @throw parse_error.109 if an array index was not a number
11940 @throw out_of_range.402 if the array index '-' is used
11941 @throw out_of_range.404 if the JSON pointer can not be resolved
11942 */
11943 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
11944 {
11945 using size_type = typename BasicJsonType::size_type;
11946 for (const auto& reference_token : reference_tokens)
11947 {
11948 switch (ptr->m_type)
11949 {
11950 case detail::value_t::object:
11951 {
11952 // use unchecked object access
11953 ptr = &ptr->operator[](reference_token);
11954 break;
11955 }
11956
11957 case detail::value_t::array:
11958 {
11959 if (JSON_UNLIKELY(reference_token == "-"))
11960 {
11961 // "-" cannot be used for const access
11962 JSON_THROW(detail::out_of_range::create(402,
11963 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
11964 ") is out of range"));
11965 }
11966
11967 // error condition (cf. RFC 6901, Sect. 4)
11968 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
11969 {
11970 JSON_THROW(detail::parse_error::create(106, 0,
11971 "array index '" + reference_token +
11972 "' must not begin with '0'"));
11973 }
11974
11975 // use unchecked array access
11976 JSON_TRY
11977 {
11978 ptr = &ptr->operator[](
11979 static_cast<size_type>(array_index(reference_token)));
11980 }
11981 JSON_CATCH(std::invalid_argument&)
11982 {
11983 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
11984 }
11985 break;
11986 }
11987
11988 default:
11989 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
11990 }
11991 }
11992
11993 return *ptr;
11994 }
11995
11996 /*!
11997 @throw parse_error.106 if an array index begins with '0'
11998 @throw parse_error.109 if an array index was not a number
11999 @throw out_of_range.402 if the array index '-' is used
12000 @throw out_of_range.404 if the JSON pointer can not be resolved
12001 */
12002 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12003 {
12004 using size_type = typename BasicJsonType::size_type;
12005 for (const auto& reference_token : reference_tokens)
12006 {
12007 switch (ptr->m_type)
12008 {
12009 case detail::value_t::object:
12010 {
12011 // note: at performs range check
12012 ptr = &ptr->at(reference_token);
12013 break;
12014 }
12015
12016 case detail::value_t::array:
12017 {
12018 if (JSON_UNLIKELY(reference_token == "-"))
12019 {
12020 // "-" always fails the range check
12021 JSON_THROW(detail::out_of_range::create(402,
12022 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12023 ") is out of range"));
12024 }
12025
12026 // error condition (cf. RFC 6901, Sect. 4)
12027 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
12028 {
12029 JSON_THROW(detail::parse_error::create(106, 0,
12030 "array index '" + reference_token +
12031 "' must not begin with '0'"));
12032 }
12033
12034 // note: at performs range check
12035 JSON_TRY
12036 {
12037 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
12038 }
12039 JSON_CATCH(std::invalid_argument&)
12040 {
12041 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12042 }
12043 break;
12044 }
12045
12046 default:
12047 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12048 }
12049 }
12050
12051 return *ptr;
12052 }
12053
12054 /*!
12055 @brief split the string input to reference tokens
12056
12057 @note This function is only called by the json_pointer constructor.
12058 All exceptions below are documented there.
12059
12060 @throw parse_error.107 if the pointer is not empty or begins with '/'
12061 @throw parse_error.108 if character '~' is not followed by '0' or '1'
12062 */
12063 static std::vector<std::string> split(const std::string& reference_string)
12064 {
12065 std::vector<std::string> result;
12066
12067 // special case: empty reference string -> no reference tokens
12068 if (reference_string.empty())
12069 {
12070 return result;
12071 }
12072
12073 // check if nonempty reference string begins with slash
12074 if (JSON_UNLIKELY(reference_string[0] != '/'))
12075 {
12076 JSON_THROW(detail::parse_error::create(107, 1,
12077 "JSON pointer must be empty or begin with '/' - was: '" +
12078 reference_string + "'"));
12079 }
12080
12081 // extract the reference tokens:
12082 // - slash: position of the last read slash (or end of string)
12083 // - start: position after the previous slash
12084 for (
12085 // search for the first slash after the first character
12086 std::size_t slash = reference_string.find_first_of('/', 1),
12087 // set the beginning of the first reference token
12088 start = 1;
12089 // we can stop if start == 0 (if slash == std::string::npos)
12090 start != 0;
12091 // set the beginning of the next reference token
12092 // (will eventually be 0 if slash == std::string::npos)
12093 start = (slash == std::string::npos) ? 0 : slash + 1,
12094 // find next slash
12095 slash = reference_string.find_first_of('/', start))
12096 {
12097 // use the text between the beginning of the reference token
12098 // (start) and the last slash (slash).
12099 auto reference_token = reference_string.substr(start, slash - start);
12100
12101 // check reference tokens are properly escaped
12102 for (std::size_t pos = reference_token.find_first_of('~');
12103 pos != std::string::npos;
12104 pos = reference_token.find_first_of('~', pos + 1))
12105 {
12106 assert(reference_token[pos] == '~');
12107
12108 // ~ must be followed by 0 or 1
12109 if (JSON_UNLIKELY(pos == reference_token.size() - 1 or
12110 (reference_token[pos + 1] != '0' and
12111 reference_token[pos + 1] != '1')))
12112 {
12113 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
12114 }
12115 }
12116
12117 // finally, store the reference token
12118 unescape(reference_token);
12119 result.push_back(reference_token);
12120 }
12121
12122 return result;
12123 }
12124
12125 /*!
12126 @brief replace all occurrences of a substring by another string
12127
12128 @param[in,out] s the string to manipulate; changed so that all
12129 occurrences of @a f are replaced with @a t
12130 @param[in] f the substring to replace with @a t
12131 @param[in] t the string to replace @a f
12132
12133 @pre The search string @a f must not be empty. **This precondition is
12134 enforced with an assertion.**
12135
12136 @since version 2.0.0
12137 */
12138 static void replace_substring(std::string& s, const std::string& f,
12139 const std::string& t)
12140 {
12141 assert(not f.empty());
12142 for (auto pos = s.find(f); // find first occurrence of f
12143 pos != std::string::npos; // make sure f was found
12144 s.replace(pos, f.size(), t), // replace with t, and
12145 pos = s.find(f, pos + t.size())) // find next occurrence of f
12146 {}
12147 }
12148
12149 /// escape "~" to "~0" and "/" to "~1"
12150 static std::string escape(std::string s)
12151 {
12152 replace_substring(s, "~", "~0");
12153 replace_substring(s, "/", "~1");
12154 return s;
12155 }
12156
12157 /// unescape "~1" to tilde and "~0" to slash (order is important!)
12158 static void unescape(std::string& s)
12159 {
12160 replace_substring(s, "~1", "/");
12161 replace_substring(s, "~0", "~");
12162 }
12163
12164 /*!
12165 @param[in] reference_string the reference string to the current value
12166 @param[in] value the value to consider
12167 @param[in,out] result the result object to insert values to
12168
12169 @note Empty objects or arrays are flattened to `null`.
12170 */
12171 static void flatten(const std::string& reference_string,
12172 const BasicJsonType& value,
12173 BasicJsonType& result)
12174 {
12175 switch (value.m_type)
12176 {
12177 case detail::value_t::array:
12178 {
12179 if (value.m_value.array->empty())
12180 {
12181 // flatten empty array as null
12182 result[reference_string] = nullptr;
12183 }
12184 else
12185 {
12186 // iterate array and use index as reference string
12187 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
12188 {
12189 flatten(reference_string + "/" + std::to_string(i),
12190 value.m_value.array->operator[](i), result);
12191 }
12192 }
12193 break;
12194 }
12195
12196 case detail::value_t::object:
12197 {
12198 if (value.m_value.object->empty())
12199 {
12200 // flatten empty object as null
12201 result[reference_string] = nullptr;
12202 }
12203 else
12204 {
12205 // iterate object and use keys as reference string
12206 for (const auto& element : *value.m_value.object)
12207 {
12208 flatten(reference_string + "/" + escape(element.first), element.second, result);
12209 }
12210 }
12211 break;
12212 }
12213
12214 default:
12215 {
12216 // add primitive value with its reference string
12217 result[reference_string] = value;
12218 break;
12219 }
12220 }
12221 }
12222
12223 /*!
12224 @param[in] value flattened JSON
12225
12226 @return unflattened JSON
12227
12228 @throw parse_error.109 if array index is not a number
12229 @throw type_error.314 if value is not an object
12230 @throw type_error.315 if object values are not primitive
12231 @throw type_error.313 if value cannot be unflattened
12232 */
12233 static BasicJsonType
12234 unflatten(const BasicJsonType& value)
12235 {
12236 if (JSON_UNLIKELY(not value.is_object()))
12237 {
12238 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
12239 }
12240
12241 BasicJsonType result;
12242
12243 // iterate the JSON object values
12244 for (const auto& element : *value.m_value.object)
12245 {
12246 if (JSON_UNLIKELY(not element.second.is_primitive()))
12247 {
12248 JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
12249 }
12250
12251 // assign value to reference pointed to by JSON pointer; Note that if
12252 // the JSON pointer is "" (i.e., points to the whole value), function
12253 // get_and_create returns a reference to result itself. An assignment
12254 // will then create a primitive value.
12255 json_pointer(element.first).get_and_create(result) = element.second;
12256 }
12257
12258 return result;
12259 }
12260
12261 friend bool operator==(json_pointer const& lhs,
12262 json_pointer const& rhs) noexcept
12263 {
12264 return (lhs.reference_tokens == rhs.reference_tokens);
12265 }
12266
12267 friend bool operator!=(json_pointer const& lhs,
12268 json_pointer const& rhs) noexcept
12269 {
12270 return not (lhs == rhs);
12271 }
12272
12273 /// the reference tokens
12274 std::vector<std::string> reference_tokens;
12275};
12276} // namespace nlohmann
12277
12278// #include <nlohmann/adl_serializer.hpp>
12279
12280
12281#include <utility>
12282
12283// #include <nlohmann/detail/conversions/from_json.hpp>
12284
12285// #include <nlohmann/detail/conversions/to_json.hpp>
12286
12287
12288namespace nlohmann
12289{
12290
12291template<typename, typename>
12292struct adl_serializer
12293{
12294 /*!
12295 @brief convert a JSON value to any value type
12296
12297 This function is usually called by the `get()` function of the
12298 @ref basic_json class (either explicit or via conversion operators).
12299
12300 @param[in] j JSON value to read from
12301 @param[in,out] val value to write to
12302 */
12303 template<typename BasicJsonType, typename ValueType>
12304 static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
12305 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
12306 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
12307 {
12308 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
12309 }
12310
12311 /*!
12312 @brief convert any value type to a JSON value
12313
12314 This function is usually called by the constructors of the @ref basic_json
12315 class.
12316
12317 @param[in,out] j JSON value to write to
12318 @param[in] val value to read from
12319 */
12320 template <typename BasicJsonType, typename ValueType>
12321 static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
12322 noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
12323 -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
12324 {
12325 ::nlohmann::to_json(j, std::forward<ValueType>(val));
12326 }
12327};
12328
12329} // namespace nlohmann
12330
12331
12332/*!
12333@brief namespace for Niels Lohmann
12334@see https://github.com/nlohmann
12335@since version 1.0.0
12336*/
12337namespace nlohmann
12338{
12339
12340/*!
12341@brief a class to store JSON values
12342
12343@tparam ObjectType type for JSON objects (`std::map` by default; will be used
12344in @ref object_t)
12345@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
12346in @ref array_t)
12347@tparam StringType type for JSON strings and object keys (`std::string` by
12348default; will be used in @ref string_t)
12349@tparam BooleanType type for JSON booleans (`bool` by default; will be used
12350in @ref boolean_t)
12351@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
12352default; will be used in @ref number_integer_t)
12353@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
12354`uint64_t` by default; will be used in @ref number_unsigned_t)
12355@tparam NumberFloatType type for JSON floating-point numbers (`double` by
12356default; will be used in @ref number_float_t)
12357@tparam AllocatorType type of the allocator to use (`std::allocator` by
12358default)
12359@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
12360and `from_json()` (@ref adl_serializer by default)
12361
12362@requirement The class satisfies the following concept requirements:
12363- Basic
12364 - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
12365 JSON values can be default constructed. The result will be a JSON null
12366 value.
12367 - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
12368 A JSON value can be constructed from an rvalue argument.
12369 - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
12370 A JSON value can be copy-constructed from an lvalue expression.
12371 - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
12372 A JSON value van be assigned from an rvalue argument.
12373 - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
12374 A JSON value can be copy-assigned from an lvalue expression.
12375 - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
12376 JSON values can be destructed.
12377- Layout
12378 - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
12379 JSON values have
12380 [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
12381 All non-static data members are private and standard layout types, the
12382 class has no virtual functions or (virtual) base classes.
12383- Library-wide
12384 - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
12385 JSON values can be compared with `==`, see @ref
12386 operator==(const_reference,const_reference).
12387 - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
12388 JSON values can be compared with `<`, see @ref
12389 operator<(const_reference,const_reference).
12390 - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
12391 Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
12392 other compatible types, using unqualified function call @ref swap().
12393 - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
12394 JSON values can be compared against `std::nullptr_t` objects which are used
12395 to model the `null` value.
12396- Container
12397 - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
12398 JSON values can be used like STL containers and provide iterator access.
12399 - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
12400 JSON values can be used like STL containers and provide reverse iterator
12401 access.
12402
12403@invariant The member variables @a m_value and @a m_type have the following
12404relationship:
12405- If `m_type == value_t::object`, then `m_value.object != nullptr`.
12406- If `m_type == value_t::array`, then `m_value.array != nullptr`.
12407- If `m_type == value_t::string`, then `m_value.string != nullptr`.
12408The invariants are checked by member function assert_invariant().
12409
12410@internal
12411@note ObjectType trick from http://stackoverflow.com/a/9860911
12412@endinternal
12413
12414@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange
12415Format](http://rfc7159.net/rfc7159)
12416
12417@since version 1.0.0
12418
12419@nosubgrouping
12420*/
12421NLOHMANN_BASIC_JSON_TPL_DECLARATION
12422class basic_json
12423{
12424 private:
12425 template<detail::value_t> friend struct detail::external_constructor;
12426 friend ::nlohmann::json_pointer<basic_json>;
12427 friend ::nlohmann::detail::parser<basic_json>;
12428 friend ::nlohmann::detail::serializer<basic_json>;
12429 template<typename BasicJsonType>
12430 friend class ::nlohmann::detail::iter_impl;
12431 template<typename BasicJsonType, typename CharType>
12432 friend class ::nlohmann::detail::binary_writer;
12433 template<typename BasicJsonType, typename SAX>
12434 friend class ::nlohmann::detail::binary_reader;
12435 template<typename BasicJsonType>
12436 friend class ::nlohmann::detail::json_sax_dom_parser;
12437 template<typename BasicJsonType>
12438 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
12439
12440 /// workaround type for MSVC
12441 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
12442
12443 // convenience aliases for types residing in namespace detail;
12444 using lexer = ::nlohmann::detail::lexer<basic_json>;
12445 using parser = ::nlohmann::detail::parser<basic_json>;
12446
12447 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
12448 template<typename BasicJsonType>
12449 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
12450 template<typename BasicJsonType>
12451 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
12452 template<typename Iterator>
12453 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
12454 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
12455
12456 template<typename CharType>
12457 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
12458
12459 using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
12460 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
12461
12462 using serializer = ::nlohmann::detail::serializer<basic_json>;
12463
12464 public:
12465 using value_t = detail::value_t;
12466 /// JSON Pointer, see @ref nlohmann::json_pointer
12467 using json_pointer = ::nlohmann::json_pointer<basic_json>;
12468 template<typename T, typename SFINAE>
12469 using json_serializer = JSONSerializer<T, SFINAE>;
12470 /// how to treat decoding errors
12471 using error_handler_t = detail::error_handler_t;
12472 /// helper type for initializer lists of basic_json values
12473 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
12474
12475 using input_format_t = detail::input_format_t;
12476 /// SAX interface type, see @ref nlohmann::json_sax
12477 using json_sax_t = json_sax<basic_json>;
12478
12479 ////////////////
12480 // exceptions //
12481 ////////////////
12482
12483 /// @name exceptions
12484 /// Classes to implement user-defined exceptions.
12485 /// @{
12486
12487 /// @copydoc detail::exception
12488 using exception = detail::exception;
12489 /// @copydoc detail::parse_error
12490 using parse_error = detail::parse_error;
12491 /// @copydoc detail::invalid_iterator
12492 using invalid_iterator = detail::invalid_iterator;
12493 /// @copydoc detail::type_error
12494 using type_error = detail::type_error;
12495 /// @copydoc detail::out_of_range
12496 using out_of_range = detail::out_of_range;
12497 /// @copydoc detail::other_error
12498 using other_error = detail::other_error;
12499
12500 /// @}
12501
12502
12503 /////////////////////
12504 // container types //
12505 /////////////////////
12506
12507 /// @name container types
12508 /// The canonic container types to use @ref basic_json like any other STL
12509 /// container.
12510 /// @{
12511
12512 /// the type of elements in a basic_json container
12513 using value_type = basic_json;
12514
12515 /// the type of an element reference
12516 using reference = value_type&;
12517 /// the type of an element const reference
12518 using const_reference = const value_type&;
12519
12520 /// a type to represent differences between iterators
12521 using difference_type = std::ptrdiff_t;
12522 /// a type to represent container sizes
12523 using size_type = std::size_t;
12524
12525 /// the allocator type
12526 using allocator_type = AllocatorType<basic_json>;
12527
12528 /// the type of an element pointer
12529 using pointer = typename std::allocator_traits<allocator_type>::pointer;
12530 /// the type of an element const pointer
12531 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
12532
12533 /// an iterator for a basic_json container
12534 using iterator = iter_impl<basic_json>;
12535 /// a const iterator for a basic_json container
12536 using const_iterator = iter_impl<const basic_json>;
12537 /// a reverse iterator for a basic_json container
12538 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
12539 /// a const reverse iterator for a basic_json container
12540 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
12541
12542 /// @}
12543
12544
12545 /*!
12546 @brief returns the allocator associated with the container
12547 */
12548 static allocator_type get_allocator()
12549 {
12550 return allocator_type();
12551 }
12552
12553 /*!
12554 @brief returns version information on the library
12555
12556 This function returns a JSON object with information about the library,
12557 including the version number and information on the platform and compiler.
12558
12559 @return JSON object holding version information
12560 key | description
12561 ----------- | ---------------
12562 `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
12563 `copyright` | The copyright line for the library as string.
12564 `name` | The name of the library as string.
12565 `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
12566 `url` | The URL of the project as string.
12567 `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
12568
12569 @liveexample{The following code shows an example output of the `meta()`
12570 function.,meta}
12571
12572 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
12573 changes to any JSON value.
12574
12575 @complexity Constant.
12576
12577 @since 2.1.0
12578 */
12579 static basic_json meta()
12580 {
12581 basic_json result;
12582
12583 result["copyright"] = "(C) 2013-2017 Niels Lohmann";
12584 result["name"] = "JSON for Modern C++";
12585 result["url"] = "https://github.com/nlohmann/json";
12586 result["version"]["string"] =
12587 std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
12588 std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
12589 std::to_string(NLOHMANN_JSON_VERSION_PATCH);
12590 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
12591 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
12592 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
12593
12594#ifdef _WIN32
12595 result["platform"] = "win32";
12596#elif defined __linux__
12597 result["platform"] = "linux";
12598#elif defined __APPLE__
12599 result["platform"] = "apple";
12600#elif defined __unix__
12601 result["platform"] = "unix";
12602#else
12603 result["platform"] = "unknown";
12604#endif
12605
12606#if defined(__ICC) || defined(__INTEL_COMPILER)
12607 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
12608#elif defined(__clang__)
12609 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
12610#elif defined(__GNUC__) || defined(__GNUG__)
12611 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
12612#elif defined(__HP_cc) || defined(__HP_aCC)
12613 result["compiler"] = "hp"
12614#elif defined(__IBMCPP__)
12615 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
12616#elif defined(_MSC_VER)
12617 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
12618#elif defined(__PGI)
12619 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
12620#elif defined(__SUNPRO_CC)
12621 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
12622#else
12623 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
12624#endif
12625
12626#ifdef __cplusplus
12627 result["compiler"]["c++"] = std::to_string(__cplusplus);
12628#else
12629 result["compiler"]["c++"] = "unknown";
12630#endif
12631 return result;
12632 }
12633
12634
12635 ///////////////////////////
12636 // JSON value data types //
12637 ///////////////////////////
12638
12639 /// @name JSON value data types
12640 /// The data types to store a JSON value. These types are derived from
12641 /// the template arguments passed to class @ref basic_json.
12642 /// @{
12643
12644#if defined(JSON_HAS_CPP_14)
12645 // Use transparent comparator if possible, combined with perfect forwarding
12646 // on find() and count() calls prevents unnecessary string construction.
12647 using object_comparator_t = std::less<>;
12648#else
12649 using object_comparator_t = std::less<StringType>;
12650#endif
12651
12652 /*!
12653 @brief a type for an object
12654
12655 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
12656 > An object is an unordered collection of zero or more name/value pairs,
12657 > where a name is a string and a value is a string, number, boolean, null,
12658 > object, or array.
12659
12660 To store objects in C++, a type is defined by the template parameters
12661 described below.
12662
12663 @tparam ObjectType the container to store objects (e.g., `std::map` or
12664 `std::unordered_map`)
12665 @tparam StringType the type of the keys or names (e.g., `std::string`).
12666 The comparison function `std::less<StringType>` is used to order elements
12667 inside the container.
12668 @tparam AllocatorType the allocator to use for objects (e.g.,
12669 `std::allocator`)
12670
12671 #### Default type
12672
12673 With the default values for @a ObjectType (`std::map`), @a StringType
12674 (`std::string`), and @a AllocatorType (`std::allocator`), the default
12675 value for @a object_t is:
12676
12677 @code {.cpp}
12678 std::map<
12679 std::string, // key_type
12680 basic_json, // value_type
12681 std::less<std::string>, // key_compare
12682 std::allocator<std::pair<const std::string, basic_json>> // allocator_type
12683 >
12684 @endcode
12685
12686 #### Behavior
12687
12688 The choice of @a object_t influences the behavior of the JSON class. With
12689 the default type, objects have the following behavior:
12690
12691 - When all names are unique, objects will be interoperable in the sense
12692 that all software implementations receiving that object will agree on
12693 the name-value mappings.
12694 - When the names within an object are not unique, it is unspecified which
12695 one of the values for a given key will be chosen. For instance,
12696 `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or
12697 `{"key": 2}`.
12698 - Internally, name/value pairs are stored in lexicographical order of the
12699 names. Objects will also be serialized (see @ref dump) in this order.
12700 For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
12701 and serialized as `{"a": 2, "b": 1}`.
12702 - When comparing objects, the order of the name/value pairs is irrelevant.
12703 This makes objects interoperable in the sense that they will not be
12704 affected by these differences. For instance, `{"b": 1, "a": 2}` and
12705 `{"a": 2, "b": 1}` will be treated as equal.
12706
12707 #### Limits
12708
12709 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
12710 > An implementation may set limits on the maximum depth of nesting.
12711
12712 In this class, the object's limit of nesting is not explicitly constrained.
12713 However, a maximum depth of nesting may be introduced by the compiler or
12714 runtime environment. A theoretical limit can be queried by calling the
12715 @ref max_size function of a JSON object.
12716
12717 #### Storage
12718
12719 Objects are stored as pointers in a @ref basic_json type. That is, for any
12720 access to object values, a pointer of type `object_t*` must be
12721 dereferenced.
12722
12723 @sa @ref array_t -- type for an array value
12724
12725 @since version 1.0.0
12726
12727 @note The order name/value pairs are added to the object is *not*
12728 preserved by the library. Therefore, iterating an object may return
12729 name/value pairs in a different order than they were originally stored. In
12730 fact, keys will be traversed in alphabetical order as `std::map` with
12731 `std::less` is used by default. Please note this behavior conforms to [RFC
12732 7159](http://rfc7159.net/rfc7159), because any order implements the
12733 specified "unordered" nature of JSON objects.
12734 */
12735 using object_t = ObjectType<StringType,
12736 basic_json,
12737 object_comparator_t,
12738 AllocatorType<std::pair<const StringType,
12739 basic_json>>>;
12740
12741 /*!
12742 @brief a type for an array
12743
12744 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
12745 > An array is an ordered sequence of zero or more values.
12746
12747 To store objects in C++, a type is defined by the template parameters
12748 explained below.
12749
12750 @tparam ArrayType container type to store arrays (e.g., `std::vector` or
12751 `std::list`)
12752 @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
12753
12754 #### Default type
12755
12756 With the default values for @a ArrayType (`std::vector`) and @a
12757 AllocatorType (`std::allocator`), the default value for @a array_t is:
12758
12759 @code {.cpp}
12760 std::vector<
12761 basic_json, // value_type
12762 std::allocator<basic_json> // allocator_type
12763 >
12764 @endcode
12765
12766 #### Limits
12767
12768 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
12769 > An implementation may set limits on the maximum depth of nesting.
12770
12771 In this class, the array's limit of nesting is not explicitly constrained.
12772 However, a maximum depth of nesting may be introduced by the compiler or
12773 runtime environment. A theoretical limit can be queried by calling the
12774 @ref max_size function of a JSON array.
12775
12776 #### Storage
12777
12778 Arrays are stored as pointers in a @ref basic_json type. That is, for any
12779 access to array values, a pointer of type `array_t*` must be dereferenced.
12780
12781 @sa @ref object_t -- type for an object value
12782
12783 @since version 1.0.0
12784 */
12785 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
12786
12787 /*!
12788 @brief a type for a string
12789
12790 [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
12791 > A string is a sequence of zero or more Unicode characters.
12792
12793 To store objects in C++, a type is defined by the template parameter
12794 described below. Unicode values are split by the JSON class into
12795 byte-sized characters during deserialization.
12796
12797 @tparam StringType the container to store strings (e.g., `std::string`).
12798 Note this container is used for keys/names in objects, see @ref object_t.
12799
12800 #### Default type
12801
12802 With the default values for @a StringType (`std::string`), the default
12803 value for @a string_t is:
12804
12805 @code {.cpp}
12806 std::string
12807 @endcode
12808
12809 #### Encoding
12810
12811 Strings are stored in UTF-8 encoding. Therefore, functions like
12812 `std::string::size()` or `std::string::length()` return the number of
12813 bytes in the string rather than the number of characters or glyphs.
12814
12815 #### String comparison
12816
12817 [RFC 7159](http://rfc7159.net/rfc7159) states:
12818 > Software implementations are typically required to test names of object
12819 > members for equality. Implementations that transform the textual
12820 > representation into sequences of Unicode code units and then perform the
12821 > comparison numerically, code unit by code unit, are interoperable in the
12822 > sense that implementations will agree in all cases on equality or
12823 > inequality of two strings. For example, implementations that compare
12824 > strings with escaped characters unconverted may incorrectly find that
12825 > `"a\\b"` and `"a\u005Cb"` are not equal.
12826
12827 This implementation is interoperable as it does compare strings code unit
12828 by code unit.
12829
12830 #### Storage
12831
12832 String values are stored as pointers in a @ref basic_json type. That is,
12833 for any access to string values, a pointer of type `string_t*` must be
12834 dereferenced.
12835
12836 @since version 1.0.0
12837 */
12838 using string_t = StringType;
12839
12840 /*!
12841 @brief a type for a boolean
12842
12843 [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
12844 type which differentiates the two literals `true` and `false`.
12845
12846 To store objects in C++, a type is defined by the template parameter @a
12847 BooleanType which chooses the type to use.
12848
12849 #### Default type
12850
12851 With the default values for @a BooleanType (`bool`), the default value for
12852 @a boolean_t is:
12853
12854 @code {.cpp}
12855 bool
12856 @endcode
12857
12858 #### Storage
12859
12860 Boolean values are stored directly inside a @ref basic_json type.
12861
12862 @since version 1.0.0
12863 */
12864 using boolean_t = BooleanType;
12865
12866 /*!
12867 @brief a type for a number (integer)
12868
12869 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
12870 > The representation of numbers is similar to that used in most
12871 > programming languages. A number is represented in base 10 using decimal
12872 > digits. It contains an integer component that may be prefixed with an
12873 > optional minus sign, which may be followed by a fraction part and/or an
12874 > exponent part. Leading zeros are not allowed. (...) Numeric values that
12875 > cannot be represented in the grammar below (such as Infinity and NaN)
12876 > are not permitted.
12877
12878 This description includes both integer and floating-point numbers.
12879 However, C++ allows more precise storage if it is known whether the number
12880 is a signed integer, an unsigned integer or a floating-point number.
12881 Therefore, three different types, @ref number_integer_t, @ref
12882 number_unsigned_t and @ref number_float_t are used.
12883
12884 To store integer numbers in C++, a type is defined by the template
12885 parameter @a NumberIntegerType which chooses the type to use.
12886
12887 #### Default type
12888
12889 With the default values for @a NumberIntegerType (`int64_t`), the default
12890 value for @a number_integer_t is:
12891
12892 @code {.cpp}
12893 int64_t
12894 @endcode
12895
12896 #### Default behavior
12897
12898 - The restrictions about leading zeros is not enforced in C++. Instead,
12899 leading zeros in integer literals lead to an interpretation as octal
12900 number. Internally, the value will be stored as decimal number. For
12901 instance, the C++ integer literal `010` will be serialized to `8`.
12902 During deserialization, leading zeros yield an error.
12903 - Not-a-number (NaN) values will be serialized to `null`.
12904
12905 #### Limits
12906
12907 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
12908 > An implementation may set limits on the range and precision of numbers.
12909
12910 When the default type is used, the maximal integer number that can be
12911 stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
12912 that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
12913 that are out of range will yield over/underflow when used in a
12914 constructor. During deserialization, too large or small integer numbers
12915 will be automatically be stored as @ref number_unsigned_t or @ref
12916 number_float_t.
12917
12918 [RFC 7159](http://rfc7159.net/rfc7159) further states:
12919 > Note that when such software is used, numbers that are integers and are
12920 > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
12921 > that implementations will agree exactly on their numeric values.
12922
12923 As this range is a subrange of the exactly supported range [INT64_MIN,
12924 INT64_MAX], this class's integer type is interoperable.
12925
12926 #### Storage
12927
12928 Integer number values are stored directly inside a @ref basic_json type.
12929
12930 @sa @ref number_float_t -- type for number values (floating-point)
12931
12932 @sa @ref number_unsigned_t -- type for number values (unsigned integer)
12933
12934 @since version 1.0.0
12935 */
12936 using number_integer_t = NumberIntegerType;
12937
12938 /*!
12939 @brief a type for a number (unsigned)
12940
12941 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
12942 > The representation of numbers is similar to that used in most
12943 > programming languages. A number is represented in base 10 using decimal
12944 > digits. It contains an integer component that may be prefixed with an
12945 > optional minus sign, which may be followed by a fraction part and/or an
12946 > exponent part. Leading zeros are not allowed. (...) Numeric values that
12947 > cannot be represented in the grammar below (such as Infinity and NaN)
12948 > are not permitted.
12949
12950 This description includes both integer and floating-point numbers.
12951 However, C++ allows more precise storage if it is known whether the number
12952 is a signed integer, an unsigned integer or a floating-point number.
12953 Therefore, three different types, @ref number_integer_t, @ref
12954 number_unsigned_t and @ref number_float_t are used.
12955
12956 To store unsigned integer numbers in C++, a type is defined by the
12957 template parameter @a NumberUnsignedType which chooses the type to use.
12958
12959 #### Default type
12960
12961 With the default values for @a NumberUnsignedType (`uint64_t`), the
12962 default value for @a number_unsigned_t is:
12963
12964 @code {.cpp}
12965 uint64_t
12966 @endcode
12967
12968 #### Default behavior
12969
12970 - The restrictions about leading zeros is not enforced in C++. Instead,
12971 leading zeros in integer literals lead to an interpretation as octal
12972 number. Internally, the value will be stored as decimal number. For
12973 instance, the C++ integer literal `010` will be serialized to `8`.
12974 During deserialization, leading zeros yield an error.
12975 - Not-a-number (NaN) values will be serialized to `null`.
12976
12977 #### Limits
12978
12979 [RFC 7159](http://rfc7159.net/rfc7159) specifies:
12980 > An implementation may set limits on the range and precision of numbers.
12981
12982 When the default type is used, the maximal integer number that can be
12983 stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
12984 number that can be stored is `0`. Integer numbers that are out of range
12985 will yield over/underflow when used in a constructor. During
12986 deserialization, too large or small integer numbers will be automatically
12987 be stored as @ref number_integer_t or @ref number_float_t.
12988
12989 [RFC 7159](http://rfc7159.net/rfc7159) further states:
12990 > Note that when such software is used, numbers that are integers and are
12991 > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
12992 > that implementations will agree exactly on their numeric values.
12993
12994 As this range is a subrange (when considered in conjunction with the
12995 number_integer_t type) of the exactly supported range [0, UINT64_MAX],
12996 this class's integer type is interoperable.
12997
12998 #### Storage
12999
13000 Integer number values are stored directly inside a @ref basic_json type.
13001
13002 @sa @ref number_float_t -- type for number values (floating-point)
13003 @sa @ref number_integer_t -- type for number values (integer)
13004
13005 @since version 2.0.0
13006 */
13007 using number_unsigned_t = NumberUnsignedType;
13008
13009 /*!
13010 @brief a type for a number (floating-point)
13011
13012 [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
13013 > The representation of numbers is similar to that used in most
13014 > programming languages. A number is represented in base 10 using decimal
13015 > digits. It contains an integer component that may be prefixed with an
13016 > optional minus sign, which may be followed by a fraction part and/or an
13017 > exponent part. Leading zeros are not allowed. (...) Numeric values that
13018 > cannot be represented in the grammar below (such as Infinity and NaN)
13019 > are not permitted.
13020
13021 This description includes both integer and floating-point numbers.
13022 However, C++ allows more precise storage if it is known whether the number
13023 is a signed integer, an unsigned integer or a floating-point number.
13024 Therefore, three different types, @ref number_integer_t, @ref
13025 number_unsigned_t and @ref number_float_t are used.
13026
13027 To store floating-point numbers in C++, a type is defined by the template
13028 parameter @a NumberFloatType which chooses the type to use.
13029
13030 #### Default type
13031
13032 With the default values for @a NumberFloatType (`double`), the default
13033 value for @a number_float_t is:
13034
13035 @code {.cpp}
13036 double
13037 @endcode
13038
13039 #### Default behavior
13040
13041 - The restrictions about leading zeros is not enforced in C++. Instead,
13042 leading zeros in floating-point literals will be ignored. Internally,
13043 the value will be stored as decimal number. For instance, the C++
13044 floating-point literal `01.2` will be serialized to `1.2`. During
13045 deserialization, leading zeros yield an error.
13046 - Not-a-number (NaN) values will be serialized to `null`.
13047
13048 #### Limits
13049
13050 [RFC 7159](http://rfc7159.net/rfc7159) states:
13051 > This specification allows implementations to set limits on the range and
13052 > precision of numbers accepted. Since software that implements IEEE
13053 > 754-2008 binary64 (double precision) numbers is generally available and
13054 > widely used, good interoperability can be achieved by implementations
13055 > that expect no more precision or range than these provide, in the sense
13056 > that implementations will approximate JSON numbers within the expected
13057 > precision.
13058
13059 This implementation does exactly follow this approach, as it uses double
13060 precision floating-point numbers. Note values smaller than
13061 `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
13062 will be stored as NaN internally and be serialized to `null`.
13063
13064 #### Storage
13065
13066 Floating-point number values are stored directly inside a @ref basic_json
13067 type.
13068
13069 @sa @ref number_integer_t -- type for number values (integer)
13070
13071 @sa @ref number_unsigned_t -- type for number values (unsigned integer)
13072
13073 @since version 1.0.0
13074 */
13075 using number_float_t = NumberFloatType;
13076
13077 /// @}
13078
13079 private:
13080
13081 /// helper for exception-safe object creation
13082 template<typename T, typename... Args>
13083 static T* create(Args&& ... args)
13084 {
13085 AllocatorType<T> alloc;
13086 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
13087
13088 auto deleter = [&](T * object)
13089 {
13090 AllocatorTraits::deallocate(alloc, object, 1);
13091 };
13092 std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
13093 AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
13094 assert(object != nullptr);
13095 return object.release();
13096 }
13097
13098 ////////////////////////
13099 // JSON value storage //
13100 ////////////////////////
13101
13102 /*!
13103 @brief a JSON value
13104
13105 The actual storage for a JSON value of the @ref basic_json class. This
13106 union combines the different storage types for the JSON value types
13107 defined in @ref value_t.
13108
13109 JSON type | value_t type | used type
13110 --------- | --------------- | ------------------------
13111 object | object | pointer to @ref object_t
13112 array | array | pointer to @ref array_t
13113 string | string | pointer to @ref string_t
13114 boolean | boolean | @ref boolean_t
13115 number | number_integer | @ref number_integer_t
13116 number | number_unsigned | @ref number_unsigned_t
13117 number | number_float | @ref number_float_t
13118 null | null | *no value is stored*
13119
13120 @note Variable-length types (objects, arrays, and strings) are stored as
13121 pointers. The size of the union should not exceed 64 bits if the default
13122 value types are used.
13123
13124 @since version 1.0.0
13125 */
13126 union json_value
13127 {
13128 /// object (stored with pointer to save storage)
13129 object_t* object;
13130 /// array (stored with pointer to save storage)
13131 array_t* array;
13132 /// string (stored with pointer to save storage)
13133 string_t* string;
13134 /// boolean
13135 boolean_t boolean;
13136 /// number (integer)
13137 number_integer_t number_integer;
13138 /// number (unsigned integer)
13139 number_unsigned_t number_unsigned;
13140 /// number (floating-point)
13141 number_float_t number_float;
13142
13143 /// default constructor (for null values)
13144 json_value() = default;
13145 /// constructor for booleans
13146 json_value(boolean_t v) noexcept : boolean(v) {}
13147 /// constructor for numbers (integer)
13148 json_value(number_integer_t v) noexcept : number_integer(v) {}
13149 /// constructor for numbers (unsigned)
13150 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
13151 /// constructor for numbers (floating-point)
13152 json_value(number_float_t v) noexcept : number_float(v) {}
13153 /// constructor for empty values of a given type
13154 json_value(value_t t)
13155 {
13156 switch (t)
13157 {
13158 case value_t::object:
13159 {
13160 object = create<object_t>();
13161 break;
13162 }
13163
13164 case value_t::array:
13165 {
13166 array = create<array_t>();
13167 break;
13168 }
13169
13170 case value_t::string:
13171 {
13172 string = create<string_t>("");
13173 break;
13174 }
13175
13176 case value_t::boolean:
13177 {
13178 boolean = boolean_t(false);
13179 break;
13180 }
13181
13182 case value_t::number_integer:
13183 {
13184 number_integer = number_integer_t(0);
13185 break;
13186 }
13187
13188 case value_t::number_unsigned:
13189 {
13190 number_unsigned = number_unsigned_t(0);
13191 break;
13192 }
13193
13194 case value_t::number_float:
13195 {
13196 number_float = number_float_t(0.0);
13197 break;
13198 }
13199
13200 case value_t::null:
13201 {
13202 object = nullptr; // silence warning, see #821
13203 break;
13204 }
13205
13206 default:
13207 {
13208 object = nullptr; // silence warning, see #821
13209 if (JSON_UNLIKELY(t == value_t::null))
13210 {
13211 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.4.0")); // LCOV_EXCL_LINE
13212 }
13213 break;
13214 }
13215 }
13216 }
13217
13218 /// constructor for strings
13219 json_value(const string_t& value)
13220 {
13221 string = create<string_t>(value);
13222 }
13223
13224 /// constructor for rvalue strings
13225 json_value(string_t&& value)
13226 {
13227 string = create<string_t>(std::move(value));
13228 }
13229
13230 /// constructor for objects
13231 json_value(const object_t& value)
13232 {
13233 object = create<object_t>(value);
13234 }
13235
13236 /// constructor for rvalue objects
13237 json_value(object_t&& value)
13238 {
13239 object = create<object_t>(std::move(value));
13240 }
13241
13242 /// constructor for arrays
13243 json_value(const array_t& value)
13244 {
13245 array = create<array_t>(value);
13246 }
13247
13248 /// constructor for rvalue arrays
13249 json_value(array_t&& value)
13250 {
13251 array = create<array_t>(std::move(value));
13252 }
13253
13254 void destroy(value_t t) noexcept
13255 {
13256 switch (t)
13257 {
13258 case value_t::object:
13259 {
13260 AllocatorType<object_t> alloc;
13261 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
13262 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
13263 break;
13264 }
13265
13266 case value_t::array:
13267 {
13268 AllocatorType<array_t> alloc;
13269 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
13270 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
13271 break;
13272 }
13273
13274 case value_t::string:
13275 {
13276 AllocatorType<string_t> alloc;
13277 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
13278 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
13279 break;
13280 }
13281
13282 default:
13283 {
13284 break;
13285 }
13286 }
13287 }
13288 };
13289
13290 /*!
13291 @brief checks the class invariants
13292
13293 This function asserts the class invariants. It needs to be called at the
13294 end of every constructor to make sure that created objects respect the
13295 invariant. Furthermore, it has to be called each time the type of a JSON
13296 value is changed, because the invariant expresses a relationship between
13297 @a m_type and @a m_value.
13298 */
13299 void assert_invariant() const noexcept
13300 {
13301 assert(m_type != value_t::object or m_value.object != nullptr);
13302 assert(m_type != value_t::array or m_value.array != nullptr);
13303 assert(m_type != value_t::string or m_value.string != nullptr);
13304 }
13305
13306 public:
13307 //////////////////////////
13308 // JSON parser callback //
13309 //////////////////////////
13310
13311 /*!
13312 @brief parser event types
13313
13314 The parser callback distinguishes the following events:
13315 - `object_start`: the parser read `{` and started to process a JSON object
13316 - `key`: the parser read a key of a value in an object
13317 - `object_end`: the parser read `}` and finished processing a JSON object
13318 - `array_start`: the parser read `[` and started to process a JSON array
13319 - `array_end`: the parser read `]` and finished processing a JSON array
13320 - `value`: the parser finished reading a JSON value
13321
13322 @image html callback_events.png "Example when certain parse events are triggered"
13323
13324 @sa @ref parser_callback_t for more information and examples
13325 */
13326 using parse_event_t = typename parser::parse_event_t;
13327
13328 /*!
13329 @brief per-element parser callback type
13330
13331 With a parser callback function, the result of parsing a JSON text can be
13332 influenced. When passed to @ref parse, it is called on certain events
13333 (passed as @ref parse_event_t via parameter @a event) with a set recursion
13334 depth @a depth and context JSON value @a parsed. The return value of the
13335 callback function is a boolean indicating whether the element that emitted
13336 the callback shall be kept or not.
13337
13338 We distinguish six scenarios (determined by the event type) in which the
13339 callback function can be called. The following table describes the values
13340 of the parameters @a depth, @a event, and @a parsed.
13341
13342 parameter @a event | description | parameter @a depth | parameter @a parsed
13343 ------------------ | ----------- | ------------------ | -------------------
13344 parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
13345 parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
13346 parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
13347 parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
13348 parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
13349 parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
13350
13351 @image html callback_events.png "Example when certain parse events are triggered"
13352
13353 Discarding a value (i.e., returning `false`) has different effects
13354 depending on the context in which function was called:
13355
13356 - Discarded values in structured types are skipped. That is, the parser
13357 will behave as if the discarded value was never read.
13358 - In case a value outside a structured type is skipped, it is replaced
13359 with `null`. This case happens if the top-level element is skipped.
13360
13361 @param[in] depth the depth of the recursion during parsing
13362
13363 @param[in] event an event of type parse_event_t indicating the context in
13364 the callback function has been called
13365
13366 @param[in,out] parsed the current intermediate parse result; note that
13367 writing to this value has no effect for parse_event_t::key events
13368
13369 @return Whether the JSON value which called the function during parsing
13370 should be kept (`true`) or not (`false`). In the latter case, it is either
13371 skipped completely or replaced by an empty discarded object.
13372
13373 @sa @ref parse for examples
13374
13375 @since version 1.0.0
13376 */
13377 using parser_callback_t = typename parser::parser_callback_t;
13378
13379 //////////////////
13380 // constructors //
13381 //////////////////
13382
13383 /// @name constructors and destructors
13384 /// Constructors of class @ref basic_json, copy/move constructor, copy
13385 /// assignment, static functions creating objects, and the destructor.
13386 /// @{
13387
13388 /*!
13389 @brief create an empty value with a given type
13390
13391 Create an empty JSON value with a given type. The value will be default
13392 initialized with an empty value which depends on the type:
13393
13394 Value type | initial value
13395 ----------- | -------------
13396 null | `null`
13397 boolean | `false`
13398 string | `""`
13399 number | `0`
13400 object | `{}`
13401 array | `[]`
13402
13403 @param[in] v the type of the value to create
13404
13405 @complexity Constant.
13406
13407 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13408 changes to any JSON value.
13409
13410 @liveexample{The following code shows the constructor for different @ref
13411 value_t values,basic_json__value_t}
13412
13413 @sa @ref clear() -- restores the postcondition of this constructor
13414
13415 @since version 1.0.0
13416 */
13417 basic_json(const value_t v)
13418 : m_type(v), m_value(v)
13419 {
13420 assert_invariant();
13421 }
13422
13423 /*!
13424 @brief create a null object
13425
13426 Create a `null` JSON value. It either takes a null pointer as parameter
13427 (explicitly creating `null`) or no parameter (implicitly creating `null`).
13428 The passed null pointer itself is not read -- it is only used to choose
13429 the right constructor.
13430
13431 @complexity Constant.
13432
13433 @exceptionsafety No-throw guarantee: this constructor never throws
13434 exceptions.
13435
13436 @liveexample{The following code shows the constructor with and without a
13437 null pointer parameter.,basic_json__nullptr_t}
13438
13439 @since version 1.0.0
13440 */
13441 basic_json(std::nullptr_t = nullptr) noexcept
13442 : basic_json(value_t::null)
13443 {
13444 assert_invariant();
13445 }
13446
13447 /*!
13448 @brief create a JSON value
13449
13450 This is a "catch all" constructor for all compatible JSON types; that is,
13451 types for which a `to_json()` method exists. The constructor forwards the
13452 parameter @a val to that method (to `json_serializer<U>::to_json` method
13453 with `U = uncvref_t<CompatibleType>`, to be exact).
13454
13455 Template type @a CompatibleType includes, but is not limited to, the
13456 following types:
13457 - **arrays**: @ref array_t and all kinds of compatible containers such as
13458 `std::vector`, `std::deque`, `std::list`, `std::forward_list`,
13459 `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
13460 `std::multiset`, and `std::unordered_multiset` with a `value_type` from
13461 which a @ref basic_json value can be constructed.
13462 - **objects**: @ref object_t and all kinds of compatible associative
13463 containers such as `std::map`, `std::unordered_map`, `std::multimap`,
13464 and `std::unordered_multimap` with a `key_type` compatible to
13465 @ref string_t and a `value_type` from which a @ref basic_json value can
13466 be constructed.
13467 - **strings**: @ref string_t, string literals, and all compatible string
13468 containers can be used.
13469 - **numbers**: @ref number_integer_t, @ref number_unsigned_t,
13470 @ref number_float_t, and all convertible number types such as `int`,
13471 `size_t`, `int64_t`, `float` or `double` can be used.
13472 - **boolean**: @ref boolean_t / `bool` can be used.
13473
13474 See the examples below.
13475
13476 @tparam CompatibleType a type such that:
13477 - @a CompatibleType is not derived from `std::istream`,
13478 - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
13479 constructors),
13480 - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)
13481 - @a CompatibleType is not a @ref basic_json nested type (e.g.,
13482 @ref json_pointer, @ref iterator, etc ...)
13483 - @ref @ref json_serializer<U> has a
13484 `to_json(basic_json_t&, CompatibleType&&)` method
13485
13486 @tparam U = `uncvref_t<CompatibleType>`
13487
13488 @param[in] val the value to be forwarded to the respective constructor
13489
13490 @complexity Usually linear in the size of the passed @a val, also
13491 depending on the implementation of the called `to_json()`
13492 method.
13493
13494 @exceptionsafety Depends on the called constructor. For types directly
13495 supported by the library (i.e., all types for which no `to_json()` function
13496 was provided), strong guarantee holds: if an exception is thrown, there are
13497 no changes to any JSON value.
13498
13499 @liveexample{The following code shows the constructor with several
13500 compatible types.,basic_json__CompatibleType}
13501
13502 @since version 2.1.0
13503 */
13504 template <typename CompatibleType,
13505 typename U = detail::uncvref_t<CompatibleType>,
13506 detail::enable_if_t<
13507 not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0>
13508 basic_json(CompatibleType && val) noexcept(noexcept(
13509 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
13510 std::forward<CompatibleType>(val))))
13511 {
13512 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
13513 assert_invariant();
13514 }
13515
13516 /*!
13517 @brief create a JSON value from an existing one
13518
13519 This is a constructor for existing @ref basic_json types.
13520 It does not hijack copy/move constructors, since the parameter has different
13521 template arguments than the current ones.
13522
13523 The constructor tries to convert the internal @ref m_value of the parameter.
13524
13525 @tparam BasicJsonType a type such that:
13526 - @a BasicJsonType is a @ref basic_json type.
13527 - @a BasicJsonType has different template arguments than @ref basic_json_t.
13528
13529 @param[in] val the @ref basic_json value to be converted.
13530
13531 @complexity Usually linear in the size of the passed @a val, also
13532 depending on the implementation of the called `to_json()`
13533 method.
13534
13535 @exceptionsafety Depends on the called constructor. For types directly
13536 supported by the library (i.e., all types for which no `to_json()` function
13537 was provided), strong guarantee holds: if an exception is thrown, there are
13538 no changes to any JSON value.
13539
13540 @since version 3.2.0
13541 */
13542 template <typename BasicJsonType,
13543 detail::enable_if_t<
13544 detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
13545 basic_json(const BasicJsonType& val)
13546 {
13547 using other_boolean_t = typename BasicJsonType::boolean_t;
13548 using other_number_float_t = typename BasicJsonType::number_float_t;
13549 using other_number_integer_t = typename BasicJsonType::number_integer_t;
13550 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
13551 using other_string_t = typename BasicJsonType::string_t;
13552 using other_object_t = typename BasicJsonType::object_t;
13553 using other_array_t = typename BasicJsonType::array_t;
13554
13555 switch (val.type())
13556 {
13557 case value_t::boolean:
13558 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
13559 break;
13560 case value_t::number_float:
13561 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
13562 break;
13563 case value_t::number_integer:
13564 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
13565 break;
13566 case value_t::number_unsigned:
13567 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
13568 break;
13569 case value_t::string:
13570 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
13571 break;
13572 case value_t::object:
13573 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
13574 break;
13575 case value_t::array:
13576 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
13577 break;
13578 case value_t::null:
13579 *this = nullptr;
13580 break;
13581 case value_t::discarded:
13582 m_type = value_t::discarded;
13583 break;
13584 }
13585 assert_invariant();
13586 }
13587
13588 /*!
13589 @brief create a container (array or object) from an initializer list
13590
13591 Creates a JSON value of type array or object from the passed initializer
13592 list @a init. In case @a type_deduction is `true` (default), the type of
13593 the JSON value to be created is deducted from the initializer list @a init
13594 according to the following rules:
13595
13596 1. If the list is empty, an empty JSON object value `{}` is created.
13597 2. If the list consists of pairs whose first element is a string, a JSON
13598 object value is created where the first elements of the pairs are
13599 treated as keys and the second elements are as values.
13600 3. In all other cases, an array is created.
13601
13602 The rules aim to create the best fit between a C++ initializer list and
13603 JSON values. The rationale is as follows:
13604
13605 1. The empty initializer list is written as `{}` which is exactly an empty
13606 JSON object.
13607 2. C++ has no way of describing mapped types other than to list a list of
13608 pairs. As JSON requires that keys must be of type string, rule 2 is the
13609 weakest constraint one can pose on initializer lists to interpret them
13610 as an object.
13611 3. In all other cases, the initializer list could not be interpreted as
13612 JSON object type, so interpreting it as JSON array type is safe.
13613
13614 With the rules described above, the following JSON values cannot be
13615 expressed by an initializer list:
13616
13617 - the empty array (`[]`): use @ref array(initializer_list_t)
13618 with an empty initializer list in this case
13619 - arrays whose elements satisfy rule 2: use @ref
13620 array(initializer_list_t) with the same initializer list
13621 in this case
13622
13623 @note When used without parentheses around an empty initializer list, @ref
13624 basic_json() is called instead of this function, yielding the JSON null
13625 value.
13626
13627 @param[in] init initializer list with JSON values
13628
13629 @param[in] type_deduction internal parameter; when set to `true`, the type
13630 of the JSON value is deducted from the initializer list @a init; when set
13631 to `false`, the type provided via @a manual_type is forced. This mode is
13632 used by the functions @ref array(initializer_list_t) and
13633 @ref object(initializer_list_t).
13634
13635 @param[in] manual_type internal parameter; when @a type_deduction is set
13636 to `false`, the created JSON value will use the provided type (only @ref
13637 value_t::array and @ref value_t::object are valid); when @a type_deduction
13638 is set to `true`, this parameter has no effect
13639
13640 @throw type_error.301 if @a type_deduction is `false`, @a manual_type is
13641 `value_t::object`, but @a init contains an element which is not a pair
13642 whose first element is a string. In this case, the constructor could not
13643 create an object. If @a type_deduction would have be `true`, an array
13644 would have been created. See @ref object(initializer_list_t)
13645 for an example.
13646
13647 @complexity Linear in the size of the initializer list @a init.
13648
13649 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13650 changes to any JSON value.
13651
13652 @liveexample{The example below shows how JSON values are created from
13653 initializer lists.,basic_json__list_init_t}
13654
13655 @sa @ref array(initializer_list_t) -- create a JSON array
13656 value from an initializer list
13657 @sa @ref object(initializer_list_t) -- create a JSON object
13658 value from an initializer list
13659
13660 @since version 1.0.0
13661 */
13662 basic_json(initializer_list_t init,
13663 bool type_deduction = true,
13664 value_t manual_type = value_t::array)
13665 {
13666 // check if each element is an array with two elements whose first
13667 // element is a string
13668 bool is_an_object = std::all_of(init.begin(), init.end(),
13669 [](const detail::json_ref<basic_json>& element_ref)
13670 {
13671 return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
13672 });
13673
13674 // adjust type if type deduction is not wanted
13675 if (not type_deduction)
13676 {
13677 // if array is wanted, do not create an object though possible
13678 if (manual_type == value_t::array)
13679 {
13680 is_an_object = false;
13681 }
13682
13683 // if object is wanted but impossible, throw an exception
13684 if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
13685 {
13686 JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
13687 }
13688 }
13689
13690 if (is_an_object)
13691 {
13692 // the initializer list is a list of pairs -> create object
13693 m_type = value_t::object;
13694 m_value = value_t::object;
13695
13696 std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
13697 {
13698 auto element = element_ref.moved_or_copied();
13699 m_value.object->emplace(
13700 std::move(*((*element.m_value.array)[0].m_value.string)),
13701 std::move((*element.m_value.array)[1]));
13702 });
13703 }
13704 else
13705 {
13706 // the initializer list describes an array -> create array
13707 m_type = value_t::array;
13708 m_value.array = create<array_t>(init.begin(), init.end());
13709 }
13710
13711 assert_invariant();
13712 }
13713
13714 /*!
13715 @brief explicitly create an array from an initializer list
13716
13717 Creates a JSON array value from a given initializer list. That is, given a
13718 list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
13719 initializer list is empty, the empty array `[]` is created.
13720
13721 @note This function is only needed to express two edge cases that cannot
13722 be realized with the initializer list constructor (@ref
13723 basic_json(initializer_list_t, bool, value_t)). These cases
13724 are:
13725 1. creating an array whose elements are all pairs whose first element is a
13726 string -- in this case, the initializer list constructor would create an
13727 object, taking the first elements as keys
13728 2. creating an empty array -- passing the empty initializer list to the
13729 initializer list constructor yields an empty object
13730
13731 @param[in] init initializer list with JSON values to create an array from
13732 (optional)
13733
13734 @return JSON array value
13735
13736 @complexity Linear in the size of @a init.
13737
13738 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13739 changes to any JSON value.
13740
13741 @liveexample{The following code shows an example for the `array`
13742 function.,array}
13743
13744 @sa @ref basic_json(initializer_list_t, bool, value_t) --
13745 create a JSON value from an initializer list
13746 @sa @ref object(initializer_list_t) -- create a JSON object
13747 value from an initializer list
13748
13749 @since version 1.0.0
13750 */
13751 static basic_json array(initializer_list_t init = {})
13752 {
13753 return basic_json(init, false, value_t::array);
13754 }
13755
13756 /*!
13757 @brief explicitly create an object from an initializer list
13758
13759 Creates a JSON object value from a given initializer list. The initializer
13760 lists elements must be pairs, and their first elements must be strings. If
13761 the initializer list is empty, the empty object `{}` is created.
13762
13763 @note This function is only added for symmetry reasons. In contrast to the
13764 related function @ref array(initializer_list_t), there are
13765 no cases which can only be expressed by this function. That is, any
13766 initializer list @a init can also be passed to the initializer list
13767 constructor @ref basic_json(initializer_list_t, bool, value_t).
13768
13769 @param[in] init initializer list to create an object from (optional)
13770
13771 @return JSON object value
13772
13773 @throw type_error.301 if @a init is not a list of pairs whose first
13774 elements are strings. In this case, no object can be created. When such a
13775 value is passed to @ref basic_json(initializer_list_t, bool, value_t),
13776 an array would have been created from the passed initializer list @a init.
13777 See example below.
13778
13779 @complexity Linear in the size of @a init.
13780
13781 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13782 changes to any JSON value.
13783
13784 @liveexample{The following code shows an example for the `object`
13785 function.,object}
13786
13787 @sa @ref basic_json(initializer_list_t, bool, value_t) --
13788 create a JSON value from an initializer list
13789 @sa @ref array(initializer_list_t) -- create a JSON array
13790 value from an initializer list
13791
13792 @since version 1.0.0
13793 */
13794 static basic_json object(initializer_list_t init = {})
13795 {
13796 return basic_json(init, false, value_t::object);
13797 }
13798
13799 /*!
13800 @brief construct an array with count copies of given value
13801
13802 Constructs a JSON array value by creating @a cnt copies of a passed value.
13803 In case @a cnt is `0`, an empty array is created.
13804
13805 @param[in] cnt the number of JSON copies of @a val to create
13806 @param[in] val the JSON value to copy
13807
13808 @post `std::distance(begin(),end()) == cnt` holds.
13809
13810 @complexity Linear in @a cnt.
13811
13812 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13813 changes to any JSON value.
13814
13815 @liveexample{The following code shows examples for the @ref
13816 basic_json(size_type\, const basic_json&)
13817 constructor.,basic_json__size_type_basic_json}
13818
13819 @since version 1.0.0
13820 */
13821 basic_json(size_type cnt, const basic_json& val)
13822 : m_type(value_t::array)
13823 {
13824 m_value.array = create<array_t>(cnt, val);
13825 assert_invariant();
13826 }
13827
13828 /*!
13829 @brief construct a JSON container given an iterator range
13830
13831 Constructs the JSON value with the contents of the range `[first, last)`.
13832 The semantics depends on the different types a JSON value can have:
13833 - In case of a null type, invalid_iterator.206 is thrown.
13834 - In case of other primitive types (number, boolean, or string), @a first
13835 must be `begin()` and @a last must be `end()`. In this case, the value is
13836 copied. Otherwise, invalid_iterator.204 is thrown.
13837 - In case of structured types (array, object), the constructor behaves as
13838 similar versions for `std::vector` or `std::map`; that is, a JSON array
13839 or object is constructed from the values in the range.
13840
13841 @tparam InputIT an input iterator type (@ref iterator or @ref
13842 const_iterator)
13843
13844 @param[in] first begin of the range to copy from (included)
13845 @param[in] last end of the range to copy from (excluded)
13846
13847 @pre Iterators @a first and @a last must be initialized. **This
13848 precondition is enforced with an assertion (see warning).** If
13849 assertions are switched off, a violation of this precondition yields
13850 undefined behavior.
13851
13852 @pre Range `[first, last)` is valid. Usually, this precondition cannot be
13853 checked efficiently. Only certain edge cases are detected; see the
13854 description of the exceptions below. A violation of this precondition
13855 yields undefined behavior.
13856
13857 @warning A precondition is enforced with a runtime assertion that will
13858 result in calling `std::abort` if this precondition is not met.
13859 Assertions can be disabled by defining `NDEBUG` at compile time.
13860 See https://en.cppreference.com/w/cpp/error/assert for more
13861 information.
13862
13863 @throw invalid_iterator.201 if iterators @a first and @a last are not
13864 compatible (i.e., do not belong to the same JSON value). In this case,
13865 the range `[first, last)` is undefined.
13866 @throw invalid_iterator.204 if iterators @a first and @a last belong to a
13867 primitive type (number, boolean, or string), but @a first does not point
13868 to the first element any more. In this case, the range `[first, last)` is
13869 undefined. See example code below.
13870 @throw invalid_iterator.206 if iterators @a first and @a last belong to a
13871 null value. In this case, the range `[first, last)` is undefined.
13872
13873 @complexity Linear in distance between @a first and @a last.
13874
13875 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13876 changes to any JSON value.
13877
13878 @liveexample{The example below shows several ways to create JSON values by
13879 specifying a subrange with iterators.,basic_json__InputIt_InputIt}
13880
13881 @since version 1.0.0
13882 */
13883 template<class InputIT, typename std::enable_if<
13884 std::is_same<InputIT, typename basic_json_t::iterator>::value or
13885 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
13886 basic_json(InputIT first, InputIT last)
13887 {
13888 assert(first.m_object != nullptr);
13889 assert(last.m_object != nullptr);
13890
13891 // make sure iterator fits the current value
13892 if (JSON_UNLIKELY(first.m_object != last.m_object))
13893 {
13894 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
13895 }
13896
13897 // copy type from first iterator
13898 m_type = first.m_object->m_type;
13899
13900 // check if iterator range is complete for primitive values
13901 switch (m_type)
13902 {
13903 case value_t::boolean:
13904 case value_t::number_float:
13905 case value_t::number_integer:
13906 case value_t::number_unsigned:
13907 case value_t::string:
13908 {
13909 if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
13910 or not last.m_it.primitive_iterator.is_end()))
13911 {
13912 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
13913 }
13914 break;
13915 }
13916
13917 default:
13918 break;
13919 }
13920
13921 switch (m_type)
13922 {
13923 case value_t::number_integer:
13924 {
13925 m_value.number_integer = first.m_object->m_value.number_integer;
13926 break;
13927 }
13928
13929 case value_t::number_unsigned:
13930 {
13931 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
13932 break;
13933 }
13934
13935 case value_t::number_float:
13936 {
13937 m_value.number_float = first.m_object->m_value.number_float;
13938 break;
13939 }
13940
13941 case value_t::boolean:
13942 {
13943 m_value.boolean = first.m_object->m_value.boolean;
13944 break;
13945 }
13946
13947 case value_t::string:
13948 {
13949 m_value = *first.m_object->m_value.string;
13950 break;
13951 }
13952
13953 case value_t::object:
13954 {
13955 m_value.object = create<object_t>(first.m_it.object_iterator,
13956 last.m_it.object_iterator);
13957 break;
13958 }
13959
13960 case value_t::array:
13961 {
13962 m_value.array = create<array_t>(first.m_it.array_iterator,
13963 last.m_it.array_iterator);
13964 break;
13965 }
13966
13967 default:
13968 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
13969 std::string(first.m_object->type_name())));
13970 }
13971
13972 assert_invariant();
13973 }
13974
13975
13976 ///////////////////////////////////////
13977 // other constructors and destructor //
13978 ///////////////////////////////////////
13979
13980 /// @private
13981 basic_json(const detail::json_ref<basic_json>& ref)
13982 : basic_json(ref.moved_or_copied())
13983 {}
13984
13985 /*!
13986 @brief copy constructor
13987
13988 Creates a copy of a given JSON value.
13989
13990 @param[in] other the JSON value to copy
13991
13992 @post `*this == other`
13993
13994 @complexity Linear in the size of @a other.
13995
13996 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
13997 changes to any JSON value.
13998
13999 @requirement This function helps `basic_json` satisfying the
14000 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
14001 requirements:
14002 - The complexity is linear.
14003 - As postcondition, it holds: `other == basic_json(other)`.
14004
14005 @liveexample{The following code shows an example for the copy
14006 constructor.,basic_json__basic_json}
14007
14008 @since version 1.0.0
14009 */
14010 basic_json(const basic_json& other)
14011 : m_type(other.m_type)
14012 {
14013 // check of passed value is valid
14014 other.assert_invariant();
14015
14016 switch (m_type)
14017 {
14018 case value_t::object:
14019 {
14020 m_value = *other.m_value.object;
14021 break;
14022 }
14023
14024 case value_t::array:
14025 {
14026 m_value = *other.m_value.array;
14027 break;
14028 }
14029
14030 case value_t::string:
14031 {
14032 m_value = *other.m_value.string;
14033 break;
14034 }
14035
14036 case value_t::boolean:
14037 {
14038 m_value = other.m_value.boolean;
14039 break;
14040 }
14041
14042 case value_t::number_integer:
14043 {
14044 m_value = other.m_value.number_integer;
14045 break;
14046 }
14047
14048 case value_t::number_unsigned:
14049 {
14050 m_value = other.m_value.number_unsigned;
14051 break;
14052 }
14053
14054 case value_t::number_float:
14055 {
14056 m_value = other.m_value.number_float;
14057 break;
14058 }
14059
14060 default:
14061 break;
14062 }
14063
14064 assert_invariant();
14065 }
14066
14067 /*!
14068 @brief move constructor
14069
14070 Move constructor. Constructs a JSON value with the contents of the given
14071 value @a other using move semantics. It "steals" the resources from @a
14072 other and leaves it as JSON null value.
14073
14074 @param[in,out] other value to move to this object
14075
14076 @post `*this` has the same value as @a other before the call.
14077 @post @a other is a JSON null value.
14078
14079 @complexity Constant.
14080
14081 @exceptionsafety No-throw guarantee: this constructor never throws
14082 exceptions.
14083
14084 @requirement This function helps `basic_json` satisfying the
14085 [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
14086 requirements.
14087
14088 @liveexample{The code below shows the move constructor explicitly called
14089 via std::move.,basic_json__moveconstructor}
14090
14091 @since version 1.0.0
14092 */
14093 basic_json(basic_json&& other) noexcept
14094 : m_type(std::move(other.m_type)),
14095 m_value(std::move(other.m_value))
14096 {
14097 // check that passed value is valid
14098 other.assert_invariant();
14099
14100 // invalidate payload
14101 other.m_type = value_t::null;
14102 other.m_value = {};
14103
14104 assert_invariant();
14105 }
14106
14107 /*!
14108 @brief copy assignment
14109
14110 Copy assignment operator. Copies a JSON value via the "copy and swap"
14111 strategy: It is expressed in terms of the copy constructor, destructor,
14112 and the `swap()` member function.
14113
14114 @param[in] other value to copy from
14115
14116 @complexity Linear.
14117
14118 @requirement This function helps `basic_json` satisfying the
14119 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
14120 requirements:
14121 - The complexity is linear.
14122
14123 @liveexample{The code below shows and example for the copy assignment. It
14124 creates a copy of value `a` which is then swapped with `b`. Finally\, the
14125 copy of `a` (which is the null value after the swap) is
14126 destroyed.,basic_json__copyassignment}
14127
14128 @since version 1.0.0
14129 */
14130 basic_json& operator=(basic_json other) noexcept (
14131 std::is_nothrow_move_constructible<value_t>::value and
14132 std::is_nothrow_move_assignable<value_t>::value and
14133 std::is_nothrow_move_constructible<json_value>::value and
14134 std::is_nothrow_move_assignable<json_value>::value
14135 )
14136 {
14137 // check that passed value is valid
14138 other.assert_invariant();
14139
14140 using std::swap;
14141 swap(m_type, other.m_type);
14142 swap(m_value, other.m_value);
14143
14144 assert_invariant();
14145 return *this;
14146 }
14147
14148 /*!
14149 @brief destructor
14150
14151 Destroys the JSON value and frees all allocated memory.
14152
14153 @complexity Linear.
14154
14155 @requirement This function helps `basic_json` satisfying the
14156 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
14157 requirements:
14158 - The complexity is linear.
14159 - All stored elements are destroyed and all memory is freed.
14160
14161 @since version 1.0.0
14162 */
14163 ~basic_json() noexcept
14164 {
14165 assert_invariant();
14166 m_value.destroy(m_type);
14167 }
14168
14169 /// @}
14170
14171 public:
14172 ///////////////////////
14173 // object inspection //
14174 ///////////////////////
14175
14176 /// @name object inspection
14177 /// Functions to inspect the type of a JSON value.
14178 /// @{
14179
14180 /*!
14181 @brief serialization
14182
14183 Serialization function for JSON values. The function tries to mimic
14184 Python's `json.dumps()` function, and currently supports its @a indent
14185 and @a ensure_ascii parameters.
14186
14187 @param[in] indent If indent is nonnegative, then array elements and object
14188 members will be pretty-printed with that indent level. An indent level of
14189 `0` will only insert newlines. `-1` (the default) selects the most compact
14190 representation.
14191 @param[in] indent_char The character to use for indentation if @a indent is
14192 greater than `0`. The default is ` ` (space).
14193 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
14194 in the output are escaped with `\uXXXX` sequences, and the result consists
14195 of ASCII characters only.
14196 @param[in] error_handler how to react on decoding errors; there are three
14197 possible values: `strict` (throws and exception in case a decoding error
14198 occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
14199 and `ignore` (ignore invalid UTF-8 sequences during serialization).
14200
14201 @return string containing the serialization of the JSON value
14202
14203 @throw type_error.316 if a string stored inside the JSON value is not
14204 UTF-8 encoded
14205
14206 @complexity Linear.
14207
14208 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
14209 changes in the JSON value.
14210
14211 @liveexample{The following example shows the effect of different @a indent\,
14212 @a indent_char\, and @a ensure_ascii parameters to the result of the
14213 serialization.,dump}
14214
14215 @see https://docs.python.org/2/library/json.html#json.dump
14216
14217 @since version 1.0.0; indentation character @a indent_char, option
14218 @a ensure_ascii and exceptions added in version 3.0.0; error
14219 handlers added in version 3.4.0.
14220 */
14221 string_t dump(const int indent = -1,
14222 const char indent_char = ' ',
14223 const bool ensure_ascii = false,
14224 const error_handler_t error_handler = error_handler_t::strict) const
14225 {
14226 string_t result;
14227 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
14228
14229 if (indent >= 0)
14230 {
14231 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
14232 }
14233 else
14234 {
14235 s.dump(*this, false, ensure_ascii, 0);
14236 }
14237
14238 return result;
14239 }
14240
14241 /*!
14242 @brief return the type of the JSON value (explicit)
14243
14244 Return the type of the JSON value as a value from the @ref value_t
14245 enumeration.
14246
14247 @return the type of the JSON value
14248 Value type | return value
14249 ------------------------- | -------------------------
14250 null | value_t::null
14251 boolean | value_t::boolean
14252 string | value_t::string
14253 number (integer) | value_t::number_integer
14254 number (unsigned integer) | value_t::number_unsigned
14255 number (floating-point) | value_t::number_float
14256 object | value_t::object
14257 array | value_t::array
14258 discarded | value_t::discarded
14259
14260 @complexity Constant.
14261
14262 @exceptionsafety No-throw guarantee: this member function never throws
14263 exceptions.
14264
14265 @liveexample{The following code exemplifies `type()` for all JSON
14266 types.,type}
14267
14268 @sa @ref operator value_t() -- return the type of the JSON value (implicit)
14269 @sa @ref type_name() -- return the type as string
14270
14271 @since version 1.0.0
14272 */
14273 constexpr value_t type() const noexcept
14274 {
14275 return m_type;
14276 }
14277
14278 /*!
14279 @brief return whether type is primitive
14280
14281 This function returns true if and only if the JSON type is primitive
14282 (string, number, boolean, or null).
14283
14284 @return `true` if type is primitive (string, number, boolean, or null),
14285 `false` otherwise.
14286
14287 @complexity Constant.
14288
14289 @exceptionsafety No-throw guarantee: this member function never throws
14290 exceptions.
14291
14292 @liveexample{The following code exemplifies `is_primitive()` for all JSON
14293 types.,is_primitive}
14294
14295 @sa @ref is_structured() -- returns whether JSON value is structured
14296 @sa @ref is_null() -- returns whether JSON value is `null`
14297 @sa @ref is_string() -- returns whether JSON value is a string
14298 @sa @ref is_boolean() -- returns whether JSON value is a boolean
14299 @sa @ref is_number() -- returns whether JSON value is a number
14300
14301 @since version 1.0.0
14302 */
14303 constexpr bool is_primitive() const noexcept
14304 {
14305 return is_null() or is_string() or is_boolean() or is_number();
14306 }
14307
14308 /*!
14309 @brief return whether type is structured
14310
14311 This function returns true if and only if the JSON type is structured
14312 (array or object).
14313
14314 @return `true` if type is structured (array or object), `false` otherwise.
14315
14316 @complexity Constant.
14317
14318 @exceptionsafety No-throw guarantee: this member function never throws
14319 exceptions.
14320
14321 @liveexample{The following code exemplifies `is_structured()` for all JSON
14322 types.,is_structured}
14323
14324 @sa @ref is_primitive() -- returns whether value is primitive
14325 @sa @ref is_array() -- returns whether value is an array
14326 @sa @ref is_object() -- returns whether value is an object
14327
14328 @since version 1.0.0
14329 */
14330 constexpr bool is_structured() const noexcept
14331 {
14332 return is_array() or is_object();
14333 }
14334
14335 /*!
14336 @brief return whether value is null
14337
14338 This function returns true if and only if the JSON value is null.
14339
14340 @return `true` if type is null, `false` otherwise.
14341
14342 @complexity Constant.
14343
14344 @exceptionsafety No-throw guarantee: this member function never throws
14345 exceptions.
14346
14347 @liveexample{The following code exemplifies `is_null()` for all JSON
14348 types.,is_null}
14349
14350 @since version 1.0.0
14351 */
14352 constexpr bool is_null() const noexcept
14353 {
14354 return (m_type == value_t::null);
14355 }
14356
14357 /*!
14358 @brief return whether value is a boolean
14359
14360 This function returns true if and only if the JSON value is a boolean.
14361
14362 @return `true` if type is boolean, `false` otherwise.
14363
14364 @complexity Constant.
14365
14366 @exceptionsafety No-throw guarantee: this member function never throws
14367 exceptions.
14368
14369 @liveexample{The following code exemplifies `is_boolean()` for all JSON
14370 types.,is_boolean}
14371
14372 @since version 1.0.0
14373 */
14374 constexpr bool is_boolean() const noexcept
14375 {
14376 return (m_type == value_t::boolean);
14377 }
14378
14379 /*!
14380 @brief return whether value is a number
14381
14382 This function returns true if and only if the JSON value is a number. This
14383 includes both integer (signed and unsigned) and floating-point values.
14384
14385 @return `true` if type is number (regardless whether integer, unsigned
14386 integer or floating-type), `false` otherwise.
14387
14388 @complexity Constant.
14389
14390 @exceptionsafety No-throw guarantee: this member function never throws
14391 exceptions.
14392
14393 @liveexample{The following code exemplifies `is_number()` for all JSON
14394 types.,is_number}
14395
14396 @sa @ref is_number_integer() -- check if value is an integer or unsigned
14397 integer number
14398 @sa @ref is_number_unsigned() -- check if value is an unsigned integer
14399 number
14400 @sa @ref is_number_float() -- check if value is a floating-point number
14401
14402 @since version 1.0.0
14403 */
14404 constexpr bool is_number() const noexcept
14405 {
14406 return is_number_integer() or is_number_float();
14407 }
14408
14409 /*!
14410 @brief return whether value is an integer number
14411
14412 This function returns true if and only if the JSON value is a signed or
14413 unsigned integer number. This excludes floating-point values.
14414
14415 @return `true` if type is an integer or unsigned integer number, `false`
14416 otherwise.
14417
14418 @complexity Constant.
14419
14420 @exceptionsafety No-throw guarantee: this member function never throws
14421 exceptions.
14422
14423 @liveexample{The following code exemplifies `is_number_integer()` for all
14424 JSON types.,is_number_integer}
14425
14426 @sa @ref is_number() -- check if value is a number
14427 @sa @ref is_number_unsigned() -- check if value is an unsigned integer
14428 number
14429 @sa @ref is_number_float() -- check if value is a floating-point number
14430
14431 @since version 1.0.0
14432 */
14433 constexpr bool is_number_integer() const noexcept
14434 {
14435 return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
14436 }
14437
14438 /*!
14439 @brief return whether value is an unsigned integer number
14440
14441 This function returns true if and only if the JSON value is an unsigned
14442 integer number. This excludes floating-point and signed integer values.
14443
14444 @return `true` if type is an unsigned integer number, `false` otherwise.
14445
14446 @complexity Constant.
14447
14448 @exceptionsafety No-throw guarantee: this member function never throws
14449 exceptions.
14450
14451 @liveexample{The following code exemplifies `is_number_unsigned()` for all
14452 JSON types.,is_number_unsigned}
14453
14454 @sa @ref is_number() -- check if value is a number
14455 @sa @ref is_number_integer() -- check if value is an integer or unsigned
14456 integer number
14457 @sa @ref is_number_float() -- check if value is a floating-point number
14458
14459 @since version 2.0.0
14460 */
14461 constexpr bool is_number_unsigned() const noexcept
14462 {
14463 return (m_type == value_t::number_unsigned);
14464 }
14465
14466 /*!
14467 @brief return whether value is a floating-point number
14468
14469 This function returns true if and only if the JSON value is a
14470 floating-point number. This excludes signed and unsigned integer values.
14471
14472 @return `true` if type is a floating-point number, `false` otherwise.
14473
14474 @complexity Constant.
14475
14476 @exceptionsafety No-throw guarantee: this member function never throws
14477 exceptions.
14478
14479 @liveexample{The following code exemplifies `is_number_float()` for all
14480 JSON types.,is_number_float}
14481
14482 @sa @ref is_number() -- check if value is number
14483 @sa @ref is_number_integer() -- check if value is an integer number
14484 @sa @ref is_number_unsigned() -- check if value is an unsigned integer
14485 number
14486
14487 @since version 1.0.0
14488 */
14489 constexpr bool is_number_float() const noexcept
14490 {
14491 return (m_type == value_t::number_float);
14492 }
14493
14494 /*!
14495 @brief return whether value is an object
14496
14497 This function returns true if and only if the JSON value is an object.
14498
14499 @return `true` if type is object, `false` otherwise.
14500
14501 @complexity Constant.
14502
14503 @exceptionsafety No-throw guarantee: this member function never throws
14504 exceptions.
14505
14506 @liveexample{The following code exemplifies `is_object()` for all JSON
14507 types.,is_object}
14508
14509 @since version 1.0.0
14510 */
14511 constexpr bool is_object() const noexcept
14512 {
14513 return (m_type == value_t::object);
14514 }
14515
14516 /*!
14517 @brief return whether value is an array
14518
14519 This function returns true if and only if the JSON value is an array.
14520
14521 @return `true` if type is array, `false` otherwise.
14522
14523 @complexity Constant.
14524
14525 @exceptionsafety No-throw guarantee: this member function never throws
14526 exceptions.
14527
14528 @liveexample{The following code exemplifies `is_array()` for all JSON
14529 types.,is_array}
14530
14531 @since version 1.0.0
14532 */
14533 constexpr bool is_array() const noexcept
14534 {
14535 return (m_type == value_t::array);
14536 }
14537
14538 /*!
14539 @brief return whether value is a string
14540
14541 This function returns true if and only if the JSON value is a string.
14542
14543 @return `true` if type is string, `false` otherwise.
14544
14545 @complexity Constant.
14546
14547 @exceptionsafety No-throw guarantee: this member function never throws
14548 exceptions.
14549
14550 @liveexample{The following code exemplifies `is_string()` for all JSON
14551 types.,is_string}
14552
14553 @since version 1.0.0
14554 */
14555 constexpr bool is_string() const noexcept
14556 {
14557 return (m_type == value_t::string);
14558 }
14559
14560 /*!
14561 @brief return whether value is discarded
14562
14563 This function returns true if and only if the JSON value was discarded
14564 during parsing with a callback function (see @ref parser_callback_t).
14565
14566 @note This function will always be `false` for JSON values after parsing.
14567 That is, discarded values can only occur during parsing, but will be
14568 removed when inside a structured value or replaced by null in other cases.
14569
14570 @return `true` if type is discarded, `false` otherwise.
14571
14572 @complexity Constant.
14573
14574 @exceptionsafety No-throw guarantee: this member function never throws
14575 exceptions.
14576
14577 @liveexample{The following code exemplifies `is_discarded()` for all JSON
14578 types.,is_discarded}
14579
14580 @since version 1.0.0
14581 */
14582 constexpr bool is_discarded() const noexcept
14583 {
14584 return (m_type == value_t::discarded);
14585 }
14586
14587 /*!
14588 @brief return the type of the JSON value (implicit)
14589
14590 Implicitly return the type of the JSON value as a value from the @ref
14591 value_t enumeration.
14592
14593 @return the type of the JSON value
14594
14595 @complexity Constant.
14596
14597 @exceptionsafety No-throw guarantee: this member function never throws
14598 exceptions.
14599
14600 @liveexample{The following code exemplifies the @ref value_t operator for
14601 all JSON types.,operator__value_t}
14602
14603 @sa @ref type() -- return the type of the JSON value (explicit)
14604 @sa @ref type_name() -- return the type as string
14605
14606 @since version 1.0.0
14607 */
14608 constexpr operator value_t() const noexcept
14609 {
14610 return m_type;
14611 }
14612
14613 /// @}
14614
14615 private:
14616 //////////////////
14617 // value access //
14618 //////////////////
14619
14620 /// get a boolean (explicit)
14621 boolean_t get_impl(boolean_t* /*unused*/) const
14622 {
14623 if (JSON_LIKELY(is_boolean()))
14624 {
14625 return m_value.boolean;
14626 }
14627
14628 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
14629 }
14630
14631 /// get a pointer to the value (object)
14632 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
14633 {
14634 return is_object() ? m_value.object : nullptr;
14635 }
14636
14637 /// get a pointer to the value (object)
14638 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
14639 {
14640 return is_object() ? m_value.object : nullptr;
14641 }
14642
14643 /// get a pointer to the value (array)
14644 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
14645 {
14646 return is_array() ? m_value.array : nullptr;
14647 }
14648
14649 /// get a pointer to the value (array)
14650 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
14651 {
14652 return is_array() ? m_value.array : nullptr;
14653 }
14654
14655 /// get a pointer to the value (string)
14656 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
14657 {
14658 return is_string() ? m_value.string : nullptr;
14659 }
14660
14661 /// get a pointer to the value (string)
14662 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
14663 {
14664 return is_string() ? m_value.string : nullptr;
14665 }
14666
14667 /// get a pointer to the value (boolean)
14668 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
14669 {
14670 return is_boolean() ? &m_value.boolean : nullptr;
14671 }
14672
14673 /// get a pointer to the value (boolean)
14674 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
14675 {
14676 return is_boolean() ? &m_value.boolean : nullptr;
14677 }
14678
14679 /// get a pointer to the value (integer number)
14680 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
14681 {
14682 return is_number_integer() ? &m_value.number_integer : nullptr;
14683 }
14684
14685 /// get a pointer to the value (integer number)
14686 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
14687 {
14688 return is_number_integer() ? &m_value.number_integer : nullptr;
14689 }
14690
14691 /// get a pointer to the value (unsigned number)
14692 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
14693 {
14694 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
14695 }
14696
14697 /// get a pointer to the value (unsigned number)
14698 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
14699 {
14700 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
14701 }
14702
14703 /// get a pointer to the value (floating-point number)
14704 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
14705 {
14706 return is_number_float() ? &m_value.number_float : nullptr;
14707 }
14708
14709 /// get a pointer to the value (floating-point number)
14710 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
14711 {
14712 return is_number_float() ? &m_value.number_float : nullptr;
14713 }
14714
14715 /*!
14716 @brief helper function to implement get_ref()
14717
14718 This function helps to implement get_ref() without code duplication for
14719 const and non-const overloads
14720
14721 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
14722
14723 @throw type_error.303 if ReferenceType does not match underlying value
14724 type of the current JSON
14725 */
14726 template<typename ReferenceType, typename ThisType>
14727 static ReferenceType get_ref_impl(ThisType& obj)
14728 {
14729 // delegate the call to get_ptr<>()
14730 auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
14731
14732 if (JSON_LIKELY(ptr != nullptr))
14733 {
14734 return *ptr;
14735 }
14736
14737 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
14738 }
14739
14740 public:
14741 /// @name value access
14742 /// Direct access to the stored value of a JSON value.
14743 /// @{
14744
14745 /*!
14746 @brief get special-case overload
14747
14748 This overloads avoids a lot of template boilerplate, it can be seen as the
14749 identity method
14750
14751 @tparam BasicJsonType == @ref basic_json
14752
14753 @return a copy of *this
14754
14755 @complexity Constant.
14756
14757 @since version 2.1.0
14758 */
14759 template<typename BasicJsonType, detail::enable_if_t<
14760 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
14761 int> = 0>
14762 basic_json get() const
14763 {
14764 return *this;
14765 }
14766
14767 /*!
14768 @brief get special-case overload
14769
14770 This overloads converts the current @ref basic_json in a different
14771 @ref basic_json type
14772
14773 @tparam BasicJsonType == @ref basic_json
14774
14775 @return a copy of *this, converted into @tparam BasicJsonType
14776
14777 @complexity Depending on the implementation of the called `from_json()`
14778 method.
14779
14780 @since version 3.2.0
14781 */
14782 template<typename BasicJsonType, detail::enable_if_t<
14783 not std::is_same<BasicJsonType, basic_json>::value and
14784 detail::is_basic_json<BasicJsonType>::value, int> = 0>
14785 BasicJsonType get() const
14786 {
14787 return *this;
14788 }
14789
14790 /*!
14791 @brief get a value (explicit)
14792
14793 Explicit type conversion between the JSON value and a compatible value
14794 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
14795 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
14796 The value is converted by calling the @ref json_serializer<ValueType>
14797 `from_json()` method.
14798
14799 The function is equivalent to executing
14800 @code {.cpp}
14801 ValueType ret;
14802 JSONSerializer<ValueType>::from_json(*this, ret);
14803 return ret;
14804 @endcode
14805
14806 This overloads is chosen if:
14807 - @a ValueType is not @ref basic_json,
14808 - @ref json_serializer<ValueType> has a `from_json()` method of the form
14809 `void from_json(const basic_json&, ValueType&)`, and
14810 - @ref json_serializer<ValueType> does not have a `from_json()` method of
14811 the form `ValueType from_json(const basic_json&)`
14812
14813 @tparam ValueTypeCV the provided value type
14814 @tparam ValueType the returned value type
14815
14816 @return copy of the JSON value, converted to @a ValueType
14817
14818 @throw what @ref json_serializer<ValueType> `from_json()` method throws
14819
14820 @liveexample{The example below shows several conversions from JSON values
14821 to other types. There a few things to note: (1) Floating-point numbers can
14822 be converted to integers\, (2) A JSON array can be converted to a standard
14823 `std::vector<short>`\, (3) A JSON object can be converted to C++
14824 associative containers such as `std::unordered_map<std::string\,
14825 json>`.,get__ValueType_const}
14826
14827 @since version 2.1.0
14828 */
14829 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
14830 detail::enable_if_t <
14831 not detail::is_basic_json<ValueType>::value and
14832 detail::has_from_json<basic_json_t, ValueType>::value and
14833 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
14834 int> = 0>
14835 ValueType get() const noexcept(noexcept(
14836 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
14837 {
14838 // we cannot static_assert on ValueTypeCV being non-const, because
14839 // there is support for get<const basic_json_t>(), which is why we
14840 // still need the uncvref
14841 static_assert(not std::is_reference<ValueTypeCV>::value,
14842 "get() cannot be used with reference types, you might want to use get_ref()");
14843 static_assert(std::is_default_constructible<ValueType>::value,
14844 "types must be DefaultConstructible when used with get()");
14845
14846 ValueType ret;
14847 JSONSerializer<ValueType>::from_json(*this, ret);
14848 return ret;
14849 }
14850
14851 /*!
14852 @brief get a value (explicit); special case
14853
14854 Explicit type conversion between the JSON value and a compatible value
14855 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
14856 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
14857 The value is converted by calling the @ref json_serializer<ValueType>
14858 `from_json()` method.
14859
14860 The function is equivalent to executing
14861 @code {.cpp}
14862 return JSONSerializer<ValueTypeCV>::from_json(*this);
14863 @endcode
14864
14865 This overloads is chosen if:
14866 - @a ValueType is not @ref basic_json and
14867 - @ref json_serializer<ValueType> has a `from_json()` method of the form
14868 `ValueType from_json(const basic_json&)`
14869
14870 @note If @ref json_serializer<ValueType> has both overloads of
14871 `from_json()`, this one is chosen.
14872
14873 @tparam ValueTypeCV the provided value type
14874 @tparam ValueType the returned value type
14875
14876 @return copy of the JSON value, converted to @a ValueType
14877
14878 @throw what @ref json_serializer<ValueType> `from_json()` method throws
14879
14880 @since version 2.1.0
14881 */
14882 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
14883 detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
14884 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
14885 int> = 0>
14886 ValueType get() const noexcept(noexcept(
14887 JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
14888 {
14889 static_assert(not std::is_reference<ValueTypeCV>::value,
14890 "get() cannot be used with reference types, you might want to use get_ref()");
14891 return JSONSerializer<ValueTypeCV>::from_json(*this);
14892 }
14893
14894 /*!
14895 @brief get a value (explicit)
14896
14897 Explicit type conversion between the JSON value and a compatible value.
14898 The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
14899 `from_json()` method.
14900
14901 The function is equivalent to executing
14902 @code {.cpp}
14903 ValueType v;
14904 JSONSerializer<ValueType>::from_json(*this, v);
14905 @endcode
14906
14907 This overloads is chosen if:
14908 - @a ValueType is not @ref basic_json,
14909 - @ref json_serializer<ValueType> has a `from_json()` method of the form
14910 `void from_json(const basic_json&, ValueType&)`, and
14911
14912 @tparam ValueType the input parameter type.
14913
14914 @return the input parameter, allowing chaining calls.
14915
14916 @throw what @ref json_serializer<ValueType> `from_json()` method throws
14917
14918 @liveexample{The example below shows several conversions from JSON values
14919 to other types. There a few things to note: (1) Floating-point numbers can
14920 be converted to integers\, (2) A JSON array can be converted to a standard
14921 `std::vector<short>`\, (3) A JSON object can be converted to C++
14922 associative containers such as `std::unordered_map<std::string\,
14923 json>`.,get_to}
14924
14925 @since version 3.3.0
14926 */
14927 template<typename ValueType,
14928 detail::enable_if_t <
14929 not detail::is_basic_json<ValueType>::value and
14930 detail::has_from_json<basic_json_t, ValueType>::value,
14931 int> = 0>
14932 ValueType & get_to(ValueType& v) const noexcept(noexcept(
14933 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
14934 {
14935 JSONSerializer<ValueType>::from_json(*this, v);
14936 return v;
14937 }
14938
14939
14940 /*!
14941 @brief get a pointer value (implicit)
14942
14943 Implicit pointer access to the internally stored JSON value. No copies are
14944 made.
14945
14946 @warning Writing data to the pointee of the result yields an undefined
14947 state.
14948
14949 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
14950 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
14951 @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
14952 assertion.
14953
14954 @return pointer to the internally stored JSON value if the requested
14955 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
14956
14957 @complexity Constant.
14958
14959 @liveexample{The example below shows how pointers to internal values of a
14960 JSON value can be requested. Note that no type conversions are made and a
14961 `nullptr` is returned if the value and the requested pointer type does not
14962 match.,get_ptr}
14963
14964 @since version 1.0.0
14965 */
14966 template<typename PointerType, typename std::enable_if<
14967 std::is_pointer<PointerType>::value, int>::type = 0>
14968 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
14969 {
14970 // delegate the call to get_impl_ptr<>()
14971 return get_impl_ptr(static_cast<PointerType>(nullptr));
14972 }
14973
14974 /*!
14975 @brief get a pointer value (implicit)
14976 @copydoc get_ptr()
14977 */
14978 template<typename PointerType, typename std::enable_if<
14979 std::is_pointer<PointerType>::value and
14980 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
14981 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
14982 {
14983 // delegate the call to get_impl_ptr<>() const
14984 return get_impl_ptr(static_cast<PointerType>(nullptr));
14985 }
14986
14987 /*!
14988 @brief get a pointer value (explicit)
14989
14990 Explicit pointer access to the internally stored JSON value. No copies are
14991 made.
14992
14993 @warning The pointer becomes invalid if the underlying JSON object
14994 changes.
14995
14996 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
14997 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
14998 @ref number_unsigned_t, or @ref number_float_t.
14999
15000 @return pointer to the internally stored JSON value if the requested
15001 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
15002
15003 @complexity Constant.
15004
15005 @liveexample{The example below shows how pointers to internal values of a
15006 JSON value can be requested. Note that no type conversions are made and a
15007 `nullptr` is returned if the value and the requested pointer type does not
15008 match.,get__PointerType}
15009
15010 @sa @ref get_ptr() for explicit pointer-member access
15011
15012 @since version 1.0.0
15013 */
15014 template<typename PointerType, typename std::enable_if<
15015 std::is_pointer<PointerType>::value, int>::type = 0>
15016 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
15017 {
15018 // delegate the call to get_ptr
15019 return get_ptr<PointerType>();
15020 }
15021
15022 /*!
15023 @brief get a pointer value (explicit)
15024 @copydoc get()
15025 */
15026 template<typename PointerType, typename std::enable_if<
15027 std::is_pointer<PointerType>::value, int>::type = 0>
15028 constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
15029 {
15030 // delegate the call to get_ptr
15031 return get_ptr<PointerType>();
15032 }
15033
15034 /*!
15035 @brief get a reference value (implicit)
15036
15037 Implicit reference access to the internally stored JSON value. No copies
15038 are made.
15039
15040 @warning Writing data to the referee of the result yields an undefined
15041 state.
15042
15043 @tparam ReferenceType reference type; must be a reference to @ref array_t,
15044 @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
15045 @ref number_float_t. Enforced by static assertion.
15046
15047 @return reference to the internally stored JSON value if the requested
15048 reference type @a ReferenceType fits to the JSON value; throws
15049 type_error.303 otherwise
15050
15051 @throw type_error.303 in case passed type @a ReferenceType is incompatible
15052 with the stored JSON value; see example below
15053
15054 @complexity Constant.
15055
15056 @liveexample{The example shows several calls to `get_ref()`.,get_ref}
15057
15058 @since version 1.1.0
15059 */
15060 template<typename ReferenceType, typename std::enable_if<
15061 std::is_reference<ReferenceType>::value, int>::type = 0>
15062 ReferenceType get_ref()
15063 {
15064 // delegate call to get_ref_impl
15065 return get_ref_impl<ReferenceType>(*this);
15066 }
15067
15068 /*!
15069 @brief get a reference value (implicit)
15070 @copydoc get_ref()
15071 */
15072 template<typename ReferenceType, typename std::enable_if<
15073 std::is_reference<ReferenceType>::value and
15074 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
15075 ReferenceType get_ref() const
15076 {
15077 // delegate call to get_ref_impl
15078 return get_ref_impl<ReferenceType>(*this);
15079 }
15080
15081 /*!
15082 @brief get a value (implicit)
15083
15084 Implicit type conversion between the JSON value and a compatible value.
15085 The call is realized by calling @ref get() const.
15086
15087 @tparam ValueType non-pointer type compatible to the JSON value, for
15088 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
15089 `std::vector` types for JSON arrays. The character type of @ref string_t
15090 as well as an initializer list of this type is excluded to avoid
15091 ambiguities as these types implicitly convert to `std::string`.
15092
15093 @return copy of the JSON value, converted to type @a ValueType
15094
15095 @throw type_error.302 in case passed type @a ValueType is incompatible
15096 to the JSON value type (e.g., the JSON value is of type boolean, but a
15097 string is requested); see example below
15098
15099 @complexity Linear in the size of the JSON value.
15100
15101 @liveexample{The example below shows several conversions from JSON values
15102 to other types. There a few things to note: (1) Floating-point numbers can
15103 be converted to integers\, (2) A JSON array can be converted to a standard
15104 `std::vector<short>`\, (3) A JSON object can be converted to C++
15105 associative containers such as `std::unordered_map<std::string\,
15106 json>`.,operator__ValueType}
15107
15108 @since version 1.0.0
15109 */
15110 template < typename ValueType, typename std::enable_if <
15111 not std::is_pointer<ValueType>::value and
15112 not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
15113 not std::is_same<ValueType, typename string_t::value_type>::value and
15114 not detail::is_basic_json<ValueType>::value
15115
15116#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
15117 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
15118#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
15119 and not std::is_same<ValueType, typename std::string_view>::value
15120#endif
15121#endif
15122 and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
15123 , int >::type = 0 >
15124 operator ValueType() const
15125 {
15126 // delegate the call to get<>() const
15127 return get<ValueType>();
15128 }
15129
15130 /// @}
15131
15132
15133 ////////////////////
15134 // element access //
15135 ////////////////////
15136
15137 /// @name element access
15138 /// Access to the JSON value.
15139 /// @{
15140
15141 /*!
15142 @brief access specified array element with bounds checking
15143
15144 Returns a reference to the element at specified location @a idx, with
15145 bounds checking.
15146
15147 @param[in] idx index of the element to access
15148
15149 @return reference to the element at index @a idx
15150
15151 @throw type_error.304 if the JSON value is not an array; in this case,
15152 calling `at` with an index makes no sense. See example below.
15153 @throw out_of_range.401 if the index @a idx is out of range of the array;
15154 that is, `idx >= size()`. See example below.
15155
15156 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15157 changes in the JSON value.
15158
15159 @complexity Constant.
15160
15161 @since version 1.0.0
15162
15163 @liveexample{The example below shows how array elements can be read and
15164 written using `at()`. It also demonstrates the different exceptions that
15165 can be thrown.,at__size_type}
15166 */
15167 reference at(size_type idx)
15168 {
15169 // at only works for arrays
15170 if (JSON_LIKELY(is_array()))
15171 {
15172 JSON_TRY
15173 {
15174 return m_value.array->at(idx);
15175 }
15176 JSON_CATCH (std::out_of_range&)
15177 {
15178 // create better exception explanation
15179 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
15180 }
15181 }
15182 else
15183 {
15184 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15185 }
15186 }
15187
15188 /*!
15189 @brief access specified array element with bounds checking
15190
15191 Returns a const reference to the element at specified location @a idx,
15192 with bounds checking.
15193
15194 @param[in] idx index of the element to access
15195
15196 @return const reference to the element at index @a idx
15197
15198 @throw type_error.304 if the JSON value is not an array; in this case,
15199 calling `at` with an index makes no sense. See example below.
15200 @throw out_of_range.401 if the index @a idx is out of range of the array;
15201 that is, `idx >= size()`. See example below.
15202
15203 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15204 changes in the JSON value.
15205
15206 @complexity Constant.
15207
15208 @since version 1.0.0
15209
15210 @liveexample{The example below shows how array elements can be read using
15211 `at()`. It also demonstrates the different exceptions that can be thrown.,
15212 at__size_type_const}
15213 */
15214 const_reference at(size_type idx) const
15215 {
15216 // at only works for arrays
15217 if (JSON_LIKELY(is_array()))
15218 {
15219 JSON_TRY
15220 {
15221 return m_value.array->at(idx);
15222 }
15223 JSON_CATCH (std::out_of_range&)
15224 {
15225 // create better exception explanation
15226 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
15227 }
15228 }
15229 else
15230 {
15231 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15232 }
15233 }
15234
15235 /*!
15236 @brief access specified object element with bounds checking
15237
15238 Returns a reference to the element at with specified key @a key, with
15239 bounds checking.
15240
15241 @param[in] key key of the element to access
15242
15243 @return reference to the element at key @a key
15244
15245 @throw type_error.304 if the JSON value is not an object; in this case,
15246 calling `at` with a key makes no sense. See example below.
15247 @throw out_of_range.403 if the key @a key is is not stored in the object;
15248 that is, `find(key) == end()`. See example below.
15249
15250 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15251 changes in the JSON value.
15252
15253 @complexity Logarithmic in the size of the container.
15254
15255 @sa @ref operator[](const typename object_t::key_type&) for unchecked
15256 access by reference
15257 @sa @ref value() for access by value with a default value
15258
15259 @since version 1.0.0
15260
15261 @liveexample{The example below shows how object elements can be read and
15262 written using `at()`. It also demonstrates the different exceptions that
15263 can be thrown.,at__object_t_key_type}
15264 */
15265 reference at(const typename object_t::key_type& key)
15266 {
15267 // at only works for objects
15268 if (JSON_LIKELY(is_object()))
15269 {
15270 JSON_TRY
15271 {
15272 return m_value.object->at(key);
15273 }
15274 JSON_CATCH (std::out_of_range&)
15275 {
15276 // create better exception explanation
15277 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
15278 }
15279 }
15280 else
15281 {
15282 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15283 }
15284 }
15285
15286 /*!
15287 @brief access specified object element with bounds checking
15288
15289 Returns a const reference to the element at with specified key @a key,
15290 with bounds checking.
15291
15292 @param[in] key key of the element to access
15293
15294 @return const reference to the element at key @a key
15295
15296 @throw type_error.304 if the JSON value is not an object; in this case,
15297 calling `at` with a key makes no sense. See example below.
15298 @throw out_of_range.403 if the key @a key is is not stored in the object;
15299 that is, `find(key) == end()`. See example below.
15300
15301 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
15302 changes in the JSON value.
15303
15304 @complexity Logarithmic in the size of the container.
15305
15306 @sa @ref operator[](const typename object_t::key_type&) for unchecked
15307 access by reference
15308 @sa @ref value() for access by value with a default value
15309
15310 @since version 1.0.0
15311
15312 @liveexample{The example below shows how object elements can be read using
15313 `at()`. It also demonstrates the different exceptions that can be thrown.,
15314 at__object_t_key_type_const}
15315 */
15316 const_reference at(const typename object_t::key_type& key) const
15317 {
15318 // at only works for objects
15319 if (JSON_LIKELY(is_object()))
15320 {
15321 JSON_TRY
15322 {
15323 return m_value.object->at(key);
15324 }
15325 JSON_CATCH (std::out_of_range&)
15326 {
15327 // create better exception explanation
15328 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
15329 }
15330 }
15331 else
15332 {
15333 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15334 }
15335 }
15336
15337 /*!
15338 @brief access specified array element
15339
15340 Returns a reference to the element at specified location @a idx.
15341
15342 @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
15343 then the array is silently filled up with `null` values to make `idx` a
15344 valid reference to the last stored element.
15345
15346 @param[in] idx index of the element to access
15347
15348 @return reference to the element at index @a idx
15349
15350 @throw type_error.305 if the JSON value is not an array or null; in that
15351 cases, using the [] operator with an index makes no sense.
15352
15353 @complexity Constant if @a idx is in the range of the array. Otherwise
15354 linear in `idx - size()`.
15355
15356 @liveexample{The example below shows how array elements can be read and
15357 written using `[]` operator. Note the addition of `null`
15358 values.,operatorarray__size_type}
15359
15360 @since version 1.0.0
15361 */
15362 reference operator[](size_type idx)
15363 {
15364 // implicitly convert null value to an empty array
15365 if (is_null())
15366 {
15367 m_type = value_t::array;
15368 m_value.array = create<array_t>();
15369 assert_invariant();
15370 }
15371
15372 // operator[] only works for arrays
15373 if (JSON_LIKELY(is_array()))
15374 {
15375 // fill up array with null values if given idx is outside range
15376 if (idx >= m_value.array->size())
15377 {
15378 m_value.array->insert(m_value.array->end(),
15379 idx - m_value.array->size() + 1,
15380 basic_json());
15381 }
15382
15383 return m_value.array->operator[](idx);
15384 }
15385
15386 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
15387 }
15388
15389 /*!
15390 @brief access specified array element
15391
15392 Returns a const reference to the element at specified location @a idx.
15393
15394 @param[in] idx index of the element to access
15395
15396 @return const reference to the element at index @a idx
15397
15398 @throw type_error.305 if the JSON value is not an array; in that case,
15399 using the [] operator with an index makes no sense.
15400
15401 @complexity Constant.
15402
15403 @liveexample{The example below shows how array elements can be read using
15404 the `[]` operator.,operatorarray__size_type_const}
15405
15406 @since version 1.0.0
15407 */
15408 const_reference operator[](size_type idx) const
15409 {
15410 // const operator[] only works for arrays
15411 if (JSON_LIKELY(is_array()))
15412 {
15413 return m_value.array->operator[](idx);
15414 }
15415
15416 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
15417 }
15418
15419 /*!
15420 @brief access specified object element
15421
15422 Returns a reference to the element at with specified key @a key.
15423
15424 @note If @a key is not found in the object, then it is silently added to
15425 the object and filled with a `null` value to make `key` a valid reference.
15426 In case the value was `null` before, it is converted to an object.
15427
15428 @param[in] key key of the element to access
15429
15430 @return reference to the element at key @a key
15431
15432 @throw type_error.305 if the JSON value is not an object or null; in that
15433 cases, using the [] operator with a key makes no sense.
15434
15435 @complexity Logarithmic in the size of the container.
15436
15437 @liveexample{The example below shows how object elements can be read and
15438 written using the `[]` operator.,operatorarray__key_type}
15439
15440 @sa @ref at(const typename object_t::key_type&) for access by reference
15441 with range checking
15442 @sa @ref value() for access by value with a default value
15443
15444 @since version 1.0.0
15445 */
15446 reference operator[](const typename object_t::key_type& key)
15447 {
15448 // implicitly convert null value to an empty object
15449 if (is_null())
15450 {
15451 m_type = value_t::object;
15452 m_value.object = create<object_t>();
15453 assert_invariant();
15454 }
15455
15456 // operator[] only works for objects
15457 if (JSON_LIKELY(is_object()))
15458 {
15459 return m_value.object->operator[](key);
15460 }
15461
15462 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15463 }
15464
15465 /*!
15466 @brief read-only access specified object element
15467
15468 Returns a const reference to the element at with specified key @a key. No
15469 bounds checking is performed.
15470
15471 @warning If the element with key @a key does not exist, the behavior is
15472 undefined.
15473
15474 @param[in] key key of the element to access
15475
15476 @return const reference to the element at key @a key
15477
15478 @pre The element with key @a key must exist. **This precondition is
15479 enforced with an assertion.**
15480
15481 @throw type_error.305 if the JSON value is not an object; in that case,
15482 using the [] operator with a key makes no sense.
15483
15484 @complexity Logarithmic in the size of the container.
15485
15486 @liveexample{The example below shows how object elements can be read using
15487 the `[]` operator.,operatorarray__key_type_const}
15488
15489 @sa @ref at(const typename object_t::key_type&) for access by reference
15490 with range checking
15491 @sa @ref value() for access by value with a default value
15492
15493 @since version 1.0.0
15494 */
15495 const_reference operator[](const typename object_t::key_type& key) const
15496 {
15497 // const operator[] only works for objects
15498 if (JSON_LIKELY(is_object()))
15499 {
15500 assert(m_value.object->find(key) != m_value.object->end());
15501 return m_value.object->find(key)->second;
15502 }
15503
15504 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15505 }
15506
15507 /*!
15508 @brief access specified object element
15509
15510 Returns a reference to the element at with specified key @a key.
15511
15512 @note If @a key is not found in the object, then it is silently added to
15513 the object and filled with a `null` value to make `key` a valid reference.
15514 In case the value was `null` before, it is converted to an object.
15515
15516 @param[in] key key of the element to access
15517
15518 @return reference to the element at key @a key
15519
15520 @throw type_error.305 if the JSON value is not an object or null; in that
15521 cases, using the [] operator with a key makes no sense.
15522
15523 @complexity Logarithmic in the size of the container.
15524
15525 @liveexample{The example below shows how object elements can be read and
15526 written using the `[]` operator.,operatorarray__key_type}
15527
15528 @sa @ref at(const typename object_t::key_type&) for access by reference
15529 with range checking
15530 @sa @ref value() for access by value with a default value
15531
15532 @since version 1.1.0
15533 */
15534 template<typename T>
15535 reference operator[](T* key)
15536 {
15537 // implicitly convert null to object
15538 if (is_null())
15539 {
15540 m_type = value_t::object;
15541 m_value = value_t::object;
15542 assert_invariant();
15543 }
15544
15545 // at only works for objects
15546 if (JSON_LIKELY(is_object()))
15547 {
15548 return m_value.object->operator[](key);
15549 }
15550
15551 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15552 }
15553
15554 /*!
15555 @brief read-only access specified object element
15556
15557 Returns a const reference to the element at with specified key @a key. No
15558 bounds checking is performed.
15559
15560 @warning If the element with key @a key does not exist, the behavior is
15561 undefined.
15562
15563 @param[in] key key of the element to access
15564
15565 @return const reference to the element at key @a key
15566
15567 @pre The element with key @a key must exist. **This precondition is
15568 enforced with an assertion.**
15569
15570 @throw type_error.305 if the JSON value is not an object; in that case,
15571 using the [] operator with a key makes no sense.
15572
15573 @complexity Logarithmic in the size of the container.
15574
15575 @liveexample{The example below shows how object elements can be read using
15576 the `[]` operator.,operatorarray__key_type_const}
15577
15578 @sa @ref at(const typename object_t::key_type&) for access by reference
15579 with range checking
15580 @sa @ref value() for access by value with a default value
15581
15582 @since version 1.1.0
15583 */
15584 template<typename T>
15585 const_reference operator[](T* key) const
15586 {
15587 // at only works for objects
15588 if (JSON_LIKELY(is_object()))
15589 {
15590 assert(m_value.object->find(key) != m_value.object->end());
15591 return m_value.object->find(key)->second;
15592 }
15593
15594 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15595 }
15596
15597 /*!
15598 @brief access specified object element with default value
15599
15600 Returns either a copy of an object's element at the specified key @a key
15601 or a given default value if no element with key @a key exists.
15602
15603 The function is basically equivalent to executing
15604 @code {.cpp}
15605 try {
15606 return at(key);
15607 } catch(out_of_range) {
15608 return default_value;
15609 }
15610 @endcode
15611
15612 @note Unlike @ref at(const typename object_t::key_type&), this function
15613 does not throw if the given key @a key was not found.
15614
15615 @note Unlike @ref operator[](const typename object_t::key_type& key), this
15616 function does not implicitly add an element to the position defined by @a
15617 key. This function is furthermore also applicable to const objects.
15618
15619 @param[in] key key of the element to access
15620 @param[in] default_value the value to return if @a key is not found
15621
15622 @tparam ValueType type compatible to JSON values, for instance `int` for
15623 JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
15624 JSON arrays. Note the type of the expected value at @a key and the default
15625 value @a default_value must be compatible.
15626
15627 @return copy of the element at key @a key or @a default_value if @a key
15628 is not found
15629
15630 @throw type_error.306 if the JSON value is not an object; in that case,
15631 using `value()` with a key makes no sense.
15632
15633 @complexity Logarithmic in the size of the container.
15634
15635 @liveexample{The example below shows how object elements can be queried
15636 with a default value.,basic_json__value}
15637
15638 @sa @ref at(const typename object_t::key_type&) for access by reference
15639 with range checking
15640 @sa @ref operator[](const typename object_t::key_type&) for unchecked
15641 access by reference
15642
15643 @since version 1.0.0
15644 */
15645 template<class ValueType, typename std::enable_if<
15646 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
15647 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
15648 {
15649 // at only works for objects
15650 if (JSON_LIKELY(is_object()))
15651 {
15652 // if key is found, return value and given default value otherwise
15653 const auto it = find(key);
15654 if (it != end())
15655 {
15656 return *it;
15657 }
15658
15659 return default_value;
15660 }
15661
15662 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
15663 }
15664
15665 /*!
15666 @brief overload for a default value of type const char*
15667 @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const
15668 */
15669 string_t value(const typename object_t::key_type& key, const char* default_value) const
15670 {
15671 return value(key, string_t(default_value));
15672 }
15673
15674 /*!
15675 @brief access specified object element via JSON Pointer with default value
15676
15677 Returns either a copy of an object's element at the specified key @a key
15678 or a given default value if no element with key @a key exists.
15679
15680 The function is basically equivalent to executing
15681 @code {.cpp}
15682 try {
15683 return at(ptr);
15684 } catch(out_of_range) {
15685 return default_value;
15686 }
15687 @endcode
15688
15689 @note Unlike @ref at(const json_pointer&), this function does not throw
15690 if the given key @a key was not found.
15691
15692 @param[in] ptr a JSON pointer to the element to access
15693 @param[in] default_value the value to return if @a ptr found no value
15694
15695 @tparam ValueType type compatible to JSON values, for instance `int` for
15696 JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
15697 JSON arrays. Note the type of the expected value at @a key and the default
15698 value @a default_value must be compatible.
15699
15700 @return copy of the element at key @a key or @a default_value if @a key
15701 is not found
15702
15703 @throw type_error.306 if the JSON value is not an object; in that case,
15704 using `value()` with a key makes no sense.
15705
15706 @complexity Logarithmic in the size of the container.
15707
15708 @liveexample{The example below shows how object elements can be queried
15709 with a default value.,basic_json__value_ptr}
15710
15711 @sa @ref operator[](const json_pointer&) for unchecked access by reference
15712
15713 @since version 2.0.2
15714 */
15715 template<class ValueType, typename std::enable_if<
15716 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
15717 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
15718 {
15719 // at only works for objects
15720 if (JSON_LIKELY(is_object()))
15721 {
15722 // if pointer resolves a value, return it or use default value
15723 JSON_TRY
15724 {
15725 return ptr.get_checked(this);
15726 }
15727 JSON_INTERNAL_CATCH (out_of_range&)
15728 {
15729 return default_value;
15730 }
15731 }
15732
15733 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
15734 }
15735
15736 /*!
15737 @brief overload for a default value of type const char*
15738 @copydoc basic_json::value(const json_pointer&, ValueType) const
15739 */
15740 string_t value(const json_pointer& ptr, const char* default_value) const
15741 {
15742 return value(ptr, string_t(default_value));
15743 }
15744
15745 /*!
15746 @brief access the first element
15747
15748 Returns a reference to the first element in the container. For a JSON
15749 container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
15750
15751 @return In case of a structured type (array or object), a reference to the
15752 first element is returned. In case of number, string, or boolean values, a
15753 reference to the value is returned.
15754
15755 @complexity Constant.
15756
15757 @pre The JSON value must not be `null` (would throw `std::out_of_range`)
15758 or an empty array or object (undefined behavior, **guarded by
15759 assertions**).
15760 @post The JSON value remains unchanged.
15761
15762 @throw invalid_iterator.214 when called on `null` value
15763
15764 @liveexample{The following code shows an example for `front()`.,front}
15765
15766 @sa @ref back() -- access the last element
15767
15768 @since version 1.0.0
15769 */
15770 reference front()
15771 {
15772 return *begin();
15773 }
15774
15775 /*!
15776 @copydoc basic_json::front()
15777 */
15778 const_reference front() const
15779 {
15780 return *cbegin();
15781 }
15782
15783 /*!
15784 @brief access the last element
15785
15786 Returns a reference to the last element in the container. For a JSON
15787 container `c`, the expression `c.back()` is equivalent to
15788 @code {.cpp}
15789 auto tmp = c.end();
15790 --tmp;
15791 return *tmp;
15792 @endcode
15793
15794 @return In case of a structured type (array or object), a reference to the
15795 last element is returned. In case of number, string, or boolean values, a
15796 reference to the value is returned.
15797
15798 @complexity Constant.
15799
15800 @pre The JSON value must not be `null` (would throw `std::out_of_range`)
15801 or an empty array or object (undefined behavior, **guarded by
15802 assertions**).
15803 @post The JSON value remains unchanged.
15804
15805 @throw invalid_iterator.214 when called on a `null` value. See example
15806 below.
15807
15808 @liveexample{The following code shows an example for `back()`.,back}
15809
15810 @sa @ref front() -- access the first element
15811
15812 @since version 1.0.0
15813 */
15814 reference back()
15815 {
15816 auto tmp = end();
15817 --tmp;
15818 return *tmp;
15819 }
15820
15821 /*!
15822 @copydoc basic_json::back()
15823 */
15824 const_reference back() const
15825 {
15826 auto tmp = cend();
15827 --tmp;
15828 return *tmp;
15829 }
15830
15831 /*!
15832 @brief remove element given an iterator
15833
15834 Removes the element specified by iterator @a pos. The iterator @a pos must
15835 be valid and dereferenceable. Thus the `end()` iterator (which is valid,
15836 but is not dereferenceable) cannot be used as a value for @a pos.
15837
15838 If called on a primitive type other than `null`, the resulting JSON value
15839 will be `null`.
15840
15841 @param[in] pos iterator to the element to remove
15842 @return Iterator following the last removed element. If the iterator @a
15843 pos refers to the last element, the `end()` iterator is returned.
15844
15845 @tparam IteratorType an @ref iterator or @ref const_iterator
15846
15847 @post Invalidates iterators and references at or after the point of the
15848 erase, including the `end()` iterator.
15849
15850 @throw type_error.307 if called on a `null` value; example: `"cannot use
15851 erase() with null"`
15852 @throw invalid_iterator.202 if called on an iterator which does not belong
15853 to the current JSON value; example: `"iterator does not fit current
15854 value"`
15855 @throw invalid_iterator.205 if called on a primitive type with invalid
15856 iterator (i.e., any iterator which is not `begin()`); example: `"iterator
15857 out of range"`
15858
15859 @complexity The complexity depends on the type:
15860 - objects: amortized constant
15861 - arrays: linear in distance between @a pos and the end of the container
15862 - strings: linear in the length of the string
15863 - other types: constant
15864
15865 @liveexample{The example shows the result of `erase()` for different JSON
15866 types.,erase__IteratorType}
15867
15868 @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
15869 the given range
15870 @sa @ref erase(const typename object_t::key_type&) -- removes the element
15871 from an object at the given key
15872 @sa @ref erase(const size_type) -- removes the element from an array at
15873 the given index
15874
15875 @since version 1.0.0
15876 */
15877 template<class IteratorType, typename std::enable_if<
15878 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
15879 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
15880 = 0>
15881 IteratorType erase(IteratorType pos)
15882 {
15883 // make sure iterator fits the current value
15884 if (JSON_UNLIKELY(this != pos.m_object))
15885 {
15886 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
15887 }
15888
15889 IteratorType result = end();
15890
15891 switch (m_type)
15892 {
15893 case value_t::boolean:
15894 case value_t::number_float:
15895 case value_t::number_integer:
15896 case value_t::number_unsigned:
15897 case value_t::string:
15898 {
15899 if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
15900 {
15901 JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
15902 }
15903
15904 if (is_string())
15905 {
15906 AllocatorType<string_t> alloc;
15907 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
15908 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
15909 m_value.string = nullptr;
15910 }
15911
15912 m_type = value_t::null;
15913 assert_invariant();
15914 break;
15915 }
15916
15917 case value_t::object:
15918 {
15919 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
15920 break;
15921 }
15922
15923 case value_t::array:
15924 {
15925 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
15926 break;
15927 }
15928
15929 default:
15930 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
15931 }
15932
15933 return result;
15934 }
15935
15936 /*!
15937 @brief remove elements given an iterator range
15938
15939 Removes the element specified by the range `[first; last)`. The iterator
15940 @a first does not need to be dereferenceable if `first == last`: erasing
15941 an empty range is a no-op.
15942
15943 If called on a primitive type other than `null`, the resulting JSON value
15944 will be `null`.
15945
15946 @param[in] first iterator to the beginning of the range to remove
15947 @param[in] last iterator past the end of the range to remove
15948 @return Iterator following the last removed element. If the iterator @a
15949 second refers to the last element, the `end()` iterator is returned.
15950
15951 @tparam IteratorType an @ref iterator or @ref const_iterator
15952
15953 @post Invalidates iterators and references at or after the point of the
15954 erase, including the `end()` iterator.
15955
15956 @throw type_error.307 if called on a `null` value; example: `"cannot use
15957 erase() with null"`
15958 @throw invalid_iterator.203 if called on iterators which does not belong
15959 to the current JSON value; example: `"iterators do not fit current value"`
15960 @throw invalid_iterator.204 if called on a primitive type with invalid
15961 iterators (i.e., if `first != begin()` and `last != end()`); example:
15962 `"iterators out of range"`
15963
15964 @complexity The complexity depends on the type:
15965 - objects: `log(size()) + std::distance(first, last)`
15966 - arrays: linear in the distance between @a first and @a last, plus linear
15967 in the distance between @a last and end of the container
15968 - strings: linear in the length of the string
15969 - other types: constant
15970
15971 @liveexample{The example shows the result of `erase()` for different JSON
15972 types.,erase__IteratorType_IteratorType}
15973
15974 @sa @ref erase(IteratorType) -- removes the element at a given position
15975 @sa @ref erase(const typename object_t::key_type&) -- removes the element
15976 from an object at the given key
15977 @sa @ref erase(const size_type) -- removes the element from an array at
15978 the given index
15979
15980 @since version 1.0.0
15981 */
15982 template<class IteratorType, typename std::enable_if<
15983 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
15984 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
15985 = 0>
15986 IteratorType erase(IteratorType first, IteratorType last)
15987 {
15988 // make sure iterator fits the current value
15989 if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
15990 {
15991 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
15992 }
15993
15994 IteratorType result = end();
15995
15996 switch (m_type)
15997 {
15998 case value_t::boolean:
15999 case value_t::number_float:
16000 case value_t::number_integer:
16001 case value_t::number_unsigned:
16002 case value_t::string:
16003 {
16004 if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
16005 or not last.m_it.primitive_iterator.is_end()))
16006 {
16007 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
16008 }
16009
16010 if (is_string())
16011 {
16012 AllocatorType<string_t> alloc;
16013 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
16014 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
16015 m_value.string = nullptr;
16016 }
16017
16018 m_type = value_t::null;
16019 assert_invariant();
16020 break;
16021 }
16022
16023 case value_t::object:
16024 {
16025 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
16026 last.m_it.object_iterator);
16027 break;
16028 }
16029
16030 case value_t::array:
16031 {
16032 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
16033 last.m_it.array_iterator);
16034 break;
16035 }
16036
16037 default:
16038 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16039 }
16040
16041 return result;
16042 }
16043
16044 /*!
16045 @brief remove element from a JSON object given a key
16046
16047 Removes elements from a JSON object with the key value @a key.
16048
16049 @param[in] key value of the elements to remove
16050
16051 @return Number of elements removed. If @a ObjectType is the default
16052 `std::map` type, the return value will always be `0` (@a key was not
16053 found) or `1` (@a key was found).
16054
16055 @post References and iterators to the erased elements are invalidated.
16056 Other references and iterators are not affected.
16057
16058 @throw type_error.307 when called on a type other than JSON object;
16059 example: `"cannot use erase() with null"`
16060
16061 @complexity `log(size()) + count(key)`
16062
16063 @liveexample{The example shows the effect of `erase()`.,erase__key_type}
16064
16065 @sa @ref erase(IteratorType) -- removes the element at a given position
16066 @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
16067 the given range
16068 @sa @ref erase(const size_type) -- removes the element from an array at
16069 the given index
16070
16071 @since version 1.0.0
16072 */
16073 size_type erase(const typename object_t::key_type& key)
16074 {
16075 // this erase only works for objects
16076 if (JSON_LIKELY(is_object()))
16077 {
16078 return m_value.object->erase(key);
16079 }
16080
16081 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16082 }
16083
16084 /*!
16085 @brief remove element from a JSON array given an index
16086
16087 Removes element from a JSON array at the index @a idx.
16088
16089 @param[in] idx index of the element to remove
16090
16091 @throw type_error.307 when called on a type other than JSON object;
16092 example: `"cannot use erase() with null"`
16093 @throw out_of_range.401 when `idx >= size()`; example: `"array index 17
16094 is out of range"`
16095
16096 @complexity Linear in distance between @a idx and the end of the container.
16097
16098 @liveexample{The example shows the effect of `erase()`.,erase__size_type}
16099
16100 @sa @ref erase(IteratorType) -- removes the element at a given position
16101 @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
16102 the given range
16103 @sa @ref erase(const typename object_t::key_type&) -- removes the element
16104 from an object at the given key
16105
16106 @since version 1.0.0
16107 */
16108 void erase(const size_type idx)
16109 {
16110 // this erase only works for arrays
16111 if (JSON_LIKELY(is_array()))
16112 {
16113 if (JSON_UNLIKELY(idx >= size()))
16114 {
16115 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
16116 }
16117
16118 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
16119 }
16120 else
16121 {
16122 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16123 }
16124 }
16125
16126 /// @}
16127
16128
16129 ////////////
16130 // lookup //
16131 ////////////
16132
16133 /// @name lookup
16134 /// @{
16135
16136 /*!
16137 @brief find an element in a JSON object
16138
16139 Finds an element in a JSON object with key equivalent to @a key. If the
16140 element is not found or the JSON value is not an object, end() is
16141 returned.
16142
16143 @note This method always returns @ref end() when executed on a JSON type
16144 that is not an object.
16145
16146 @param[in] key key value of the element to search for.
16147
16148 @return Iterator to an element with key equivalent to @a key. If no such
16149 element is found or the JSON value is not an object, past-the-end (see
16150 @ref end()) iterator is returned.
16151
16152 @complexity Logarithmic in the size of the JSON object.
16153
16154 @liveexample{The example shows how `find()` is used.,find__key_type}
16155
16156 @since version 1.0.0
16157 */
16158 template<typename KeyT>
16159 iterator find(KeyT&& key)
16160 {
16161 auto result = end();
16162
16163 if (is_object())
16164 {
16165 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
16166 }
16167
16168 return result;
16169 }
16170
16171 /*!
16172 @brief find an element in a JSON object
16173 @copydoc find(KeyT&&)
16174 */
16175 template<typename KeyT>
16176 const_iterator find(KeyT&& key) const
16177 {
16178 auto result = cend();
16179
16180 if (is_object())
16181 {
16182 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
16183 }
16184
16185 return result;
16186 }
16187
16188 /*!
16189 @brief returns the number of occurrences of a key in a JSON object
16190
16191 Returns the number of elements with key @a key. If ObjectType is the
16192 default `std::map` type, the return value will always be `0` (@a key was
16193 not found) or `1` (@a key was found).
16194
16195 @note This method always returns `0` when executed on a JSON type that is
16196 not an object.
16197
16198 @param[in] key key value of the element to count
16199
16200 @return Number of elements with key @a key. If the JSON value is not an
16201 object, the return value will be `0`.
16202
16203 @complexity Logarithmic in the size of the JSON object.
16204
16205 @liveexample{The example shows how `count()` is used.,count}
16206
16207 @since version 1.0.0
16208 */
16209 template<typename KeyT>
16210 size_type count(KeyT&& key) const
16211 {
16212 // return 0 for all nonobject types
16213 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
16214 }
16215
16216 /// @}
16217
16218
16219 ///////////////
16220 // iterators //
16221 ///////////////
16222
16223 /// @name iterators
16224 /// @{
16225
16226 /*!
16227 @brief returns an iterator to the first element
16228
16229 Returns an iterator to the first element.
16230
16231 @image html range-begin-end.svg "Illustration from cppreference.com"
16232
16233 @return iterator to the first element
16234
16235 @complexity Constant.
16236
16237 @requirement This function helps `basic_json` satisfying the
16238 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
16239 requirements:
16240 - The complexity is constant.
16241
16242 @liveexample{The following code shows an example for `begin()`.,begin}
16243
16244 @sa @ref cbegin() -- returns a const iterator to the beginning
16245 @sa @ref end() -- returns an iterator to the end
16246 @sa @ref cend() -- returns a const iterator to the end
16247
16248 @since version 1.0.0
16249 */
16250 iterator begin() noexcept
16251 {
16252 iterator result(this);
16253 result.set_begin();
16254 return result;
16255 }
16256
16257 /*!
16258 @copydoc basic_json::cbegin()
16259 */
16260 const_iterator begin() const noexcept
16261 {
16262 return cbegin();
16263 }
16264
16265 /*!
16266 @brief returns a const iterator to the first element
16267
16268 Returns a const iterator to the first element.
16269
16270 @image html range-begin-end.svg "Illustration from cppreference.com"
16271
16272 @return const iterator to the first element
16273
16274 @complexity Constant.
16275
16276 @requirement This function helps `basic_json` satisfying the
16277 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
16278 requirements:
16279 - The complexity is constant.
16280 - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
16281
16282 @liveexample{The following code shows an example for `cbegin()`.,cbegin}
16283
16284 @sa @ref begin() -- returns an iterator to the beginning
16285 @sa @ref end() -- returns an iterator to the end
16286 @sa @ref cend() -- returns a const iterator to the end
16287
16288 @since version 1.0.0
16289 */
16290 const_iterator cbegin() const noexcept
16291 {
16292 const_iterator result(this);
16293 result.set_begin();
16294 return result;
16295 }
16296
16297 /*!
16298 @brief returns an iterator to one past the last element
16299
16300 Returns an iterator to one past the last element.
16301
16302 @image html range-begin-end.svg "Illustration from cppreference.com"
16303
16304 @return iterator one past the last element
16305
16306 @complexity Constant.
16307
16308 @requirement This function helps `basic_json` satisfying the
16309 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
16310 requirements:
16311 - The complexity is constant.
16312
16313 @liveexample{The following code shows an example for `end()`.,end}
16314
16315 @sa @ref cend() -- returns a const iterator to the end
16316 @sa @ref begin() -- returns an iterator to the beginning
16317 @sa @ref cbegin() -- returns a const iterator to the beginning
16318
16319 @since version 1.0.0
16320 */
16321 iterator end() noexcept
16322 {
16323 iterator result(this);
16324 result.set_end();
16325 return result;
16326 }
16327
16328 /*!
16329 @copydoc basic_json::cend()
16330 */
16331 const_iterator end() const noexcept
16332 {
16333 return cend();
16334 }
16335
16336 /*!
16337 @brief returns a const iterator to one past the last element
16338
16339 Returns a const iterator to one past the last element.
16340
16341 @image html range-begin-end.svg "Illustration from cppreference.com"
16342
16343 @return const iterator one past the last element
16344
16345 @complexity Constant.
16346
16347 @requirement This function helps `basic_json` satisfying the
16348 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
16349 requirements:
16350 - The complexity is constant.
16351 - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
16352
16353 @liveexample{The following code shows an example for `cend()`.,cend}
16354
16355 @sa @ref end() -- returns an iterator to the end
16356 @sa @ref begin() -- returns an iterator to the beginning
16357 @sa @ref cbegin() -- returns a const iterator to the beginning
16358
16359 @since version 1.0.0
16360 */
16361 const_iterator cend() const noexcept
16362 {
16363 const_iterator result(this);
16364 result.set_end();
16365 return result;
16366 }
16367
16368 /*!
16369 @brief returns an iterator to the reverse-beginning
16370
16371 Returns an iterator to the reverse-beginning; that is, the last element.
16372
16373 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
16374
16375 @complexity Constant.
16376
16377 @requirement This function helps `basic_json` satisfying the
16378 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
16379 requirements:
16380 - The complexity is constant.
16381 - Has the semantics of `reverse_iterator(end())`.
16382
16383 @liveexample{The following code shows an example for `rbegin()`.,rbegin}
16384
16385 @sa @ref crbegin() -- returns a const reverse iterator to the beginning
16386 @sa @ref rend() -- returns a reverse iterator to the end
16387 @sa @ref crend() -- returns a const reverse iterator to the end
16388
16389 @since version 1.0.0
16390 */
16391 reverse_iterator rbegin() noexcept
16392 {
16393 return reverse_iterator(end());
16394 }
16395
16396 /*!
16397 @copydoc basic_json::crbegin()
16398 */
16399 const_reverse_iterator rbegin() const noexcept
16400 {
16401 return crbegin();
16402 }
16403
16404 /*!
16405 @brief returns an iterator to the reverse-end
16406
16407 Returns an iterator to the reverse-end; that is, one before the first
16408 element.
16409
16410 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
16411
16412 @complexity Constant.
16413
16414 @requirement This function helps `basic_json` satisfying the
16415 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
16416 requirements:
16417 - The complexity is constant.
16418 - Has the semantics of `reverse_iterator(begin())`.
16419
16420 @liveexample{The following code shows an example for `rend()`.,rend}
16421
16422 @sa @ref crend() -- returns a const reverse iterator to the end
16423 @sa @ref rbegin() -- returns a reverse iterator to the beginning
16424 @sa @ref crbegin() -- returns a const reverse iterator to the beginning
16425
16426 @since version 1.0.0
16427 */
16428 reverse_iterator rend() noexcept
16429 {
16430 return reverse_iterator(begin());
16431 }
16432
16433 /*!
16434 @copydoc basic_json::crend()
16435 */
16436 const_reverse_iterator rend() const noexcept
16437 {
16438 return crend();
16439 }
16440
16441 /*!
16442 @brief returns a const reverse iterator to the last element
16443
16444 Returns a const iterator to the reverse-beginning; that is, the last
16445 element.
16446
16447 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
16448
16449 @complexity Constant.
16450
16451 @requirement This function helps `basic_json` satisfying the
16452 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
16453 requirements:
16454 - The complexity is constant.
16455 - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
16456
16457 @liveexample{The following code shows an example for `crbegin()`.,crbegin}
16458
16459 @sa @ref rbegin() -- returns a reverse iterator to the beginning
16460 @sa @ref rend() -- returns a reverse iterator to the end
16461 @sa @ref crend() -- returns a const reverse iterator to the end
16462
16463 @since version 1.0.0
16464 */
16465 const_reverse_iterator crbegin() const noexcept
16466 {
16467 return const_reverse_iterator(cend());
16468 }
16469
16470 /*!
16471 @brief returns a const reverse iterator to one before the first
16472
16473 Returns a const reverse iterator to the reverse-end; that is, one before
16474 the first element.
16475
16476 @image html range-rbegin-rend.svg "Illustration from cppreference.com"
16477
16478 @complexity Constant.
16479
16480 @requirement This function helps `basic_json` satisfying the
16481 [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
16482 requirements:
16483 - The complexity is constant.
16484 - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
16485
16486 @liveexample{The following code shows an example for `crend()`.,crend}
16487
16488 @sa @ref rend() -- returns a reverse iterator to the end
16489 @sa @ref rbegin() -- returns a reverse iterator to the beginning
16490 @sa @ref crbegin() -- returns a const reverse iterator to the beginning
16491
16492 @since version 1.0.0
16493 */
16494 const_reverse_iterator crend() const noexcept
16495 {
16496 return const_reverse_iterator(cbegin());
16497 }
16498
16499 public:
16500 /*!
16501 @brief wrapper to access iterator member functions in range-based for
16502
16503 This function allows to access @ref iterator::key() and @ref
16504 iterator::value() during range-based for loops. In these loops, a
16505 reference to the JSON values is returned, so there is no access to the
16506 underlying iterator.
16507
16508 For loop without iterator_wrapper:
16509
16510 @code{cpp}
16511 for (auto it = j_object.begin(); it != j_object.end(); ++it)
16512 {
16513 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
16514 }
16515 @endcode
16516
16517 Range-based for loop without iterator proxy:
16518
16519 @code{cpp}
16520 for (auto it : j_object)
16521 {
16522 // "it" is of type json::reference and has no key() member
16523 std::cout << "value: " << it << '\n';
16524 }
16525 @endcode
16526
16527 Range-based for loop with iterator proxy:
16528
16529 @code{cpp}
16530 for (auto it : json::iterator_wrapper(j_object))
16531 {
16532 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
16533 }
16534 @endcode
16535
16536 @note When iterating over an array, `key()` will return the index of the
16537 element as string (see example).
16538
16539 @param[in] ref reference to a JSON value
16540 @return iteration proxy object wrapping @a ref with an interface to use in
16541 range-based for loops
16542
16543 @liveexample{The following code shows how the wrapper is used,iterator_wrapper}
16544
16545 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
16546 changes in the JSON value.
16547
16548 @complexity Constant.
16549
16550 @note The name of this function is not yet final and may change in the
16551 future.
16552
16553 @deprecated This stream operator is deprecated and will be removed in
16554 future 4.0.0 of the library. Please use @ref items() instead;
16555 that is, replace `json::iterator_wrapper(j)` with `j.items()`.
16556 */
16557 JSON_DEPRECATED
16558 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
16559 {
16560 return ref.items();
16561 }
16562
16563 /*!
16564 @copydoc iterator_wrapper(reference)
16565 */
16566 JSON_DEPRECATED
16567 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
16568 {
16569 return ref.items();
16570 }
16571
16572 /*!
16573 @brief helper to access iterator member functions in range-based for
16574
16575 This function allows to access @ref iterator::key() and @ref
16576 iterator::value() during range-based for loops. In these loops, a
16577 reference to the JSON values is returned, so there is no access to the
16578 underlying iterator.
16579
16580 For loop without `items()` function:
16581
16582 @code{cpp}
16583 for (auto it = j_object.begin(); it != j_object.end(); ++it)
16584 {
16585 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
16586 }
16587 @endcode
16588
16589 Range-based for loop without `items()` function:
16590
16591 @code{cpp}
16592 for (auto it : j_object)
16593 {
16594 // "it" is of type json::reference and has no key() member
16595 std::cout << "value: " << it << '\n';
16596 }
16597 @endcode
16598
16599 Range-based for loop with `items()` function:
16600
16601 @code{cpp}
16602 for (auto it : j_object.items())
16603 {
16604 std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
16605 }
16606 @endcode
16607
16608 @note When iterating over an array, `key()` will return the index of the
16609 element as string (see example). For primitive types (e.g., numbers),
16610 `key()` returns an empty string.
16611
16612 @return iteration proxy object wrapping @a ref with an interface to use in
16613 range-based for loops
16614
16615 @liveexample{The following code shows how the function is used.,items}
16616
16617 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
16618 changes in the JSON value.
16619
16620 @complexity Constant.
16621
16622 @since version 3.1.0.
16623 */
16624 iteration_proxy<iterator> items() noexcept
16625 {
16626 return iteration_proxy<iterator>(*this);
16627 }
16628
16629 /*!
16630 @copydoc items()
16631 */
16632 iteration_proxy<const_iterator> items() const noexcept
16633 {
16634 return iteration_proxy<const_iterator>(*this);
16635 }
16636
16637 /// @}
16638
16639
16640 //////////////
16641 // capacity //
16642 //////////////
16643
16644 /// @name capacity
16645 /// @{
16646
16647 /*!
16648 @brief checks whether the container is empty.
16649
16650 Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
16651
16652 @return The return value depends on the different types and is
16653 defined as follows:
16654 Value type | return value
16655 ----------- | -------------
16656 null | `true`
16657 boolean | `false`
16658 string | `false`
16659 number | `false`
16660 object | result of function `object_t::empty()`
16661 array | result of function `array_t::empty()`
16662
16663 @liveexample{The following code uses `empty()` to check if a JSON
16664 object contains any elements.,empty}
16665
16666 @complexity Constant, as long as @ref array_t and @ref object_t satisfy
16667 the Container concept; that is, their `empty()` functions have constant
16668 complexity.
16669
16670 @iterators No changes.
16671
16672 @exceptionsafety No-throw guarantee: this function never throws exceptions.
16673
16674 @note This function does not return whether a string stored as JSON value
16675 is empty - it returns whether the JSON container itself is empty which is
16676 false in the case of a string.
16677
16678 @requirement This function helps `basic_json` satisfying the
16679 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
16680 requirements:
16681 - The complexity is constant.
16682 - Has the semantics of `begin() == end()`.
16683
16684 @sa @ref size() -- returns the number of elements
16685
16686 @since version 1.0.0
16687 */
16688 bool empty() const noexcept
16689 {
16690 switch (m_type)
16691 {
16692 case value_t::null:
16693 {
16694 // null values are empty
16695 return true;
16696 }
16697
16698 case value_t::array:
16699 {
16700 // delegate call to array_t::empty()
16701 return m_value.array->empty();
16702 }
16703
16704 case value_t::object:
16705 {
16706 // delegate call to object_t::empty()
16707 return m_value.object->empty();
16708 }
16709
16710 default:
16711 {
16712 // all other types are nonempty
16713 return false;
16714 }
16715 }
16716 }
16717
16718 /*!
16719 @brief returns the number of elements
16720
16721 Returns the number of elements in a JSON value.
16722
16723 @return The return value depends on the different types and is
16724 defined as follows:
16725 Value type | return value
16726 ----------- | -------------
16727 null | `0`
16728 boolean | `1`
16729 string | `1`
16730 number | `1`
16731 object | result of function object_t::size()
16732 array | result of function array_t::size()
16733
16734 @liveexample{The following code calls `size()` on the different value
16735 types.,size}
16736
16737 @complexity Constant, as long as @ref array_t and @ref object_t satisfy
16738 the Container concept; that is, their size() functions have constant
16739 complexity.
16740
16741 @iterators No changes.
16742
16743 @exceptionsafety No-throw guarantee: this function never throws exceptions.
16744
16745 @note This function does not return the length of a string stored as JSON
16746 value - it returns the number of elements in the JSON value which is 1 in
16747 the case of a string.
16748
16749 @requirement This function helps `basic_json` satisfying the
16750 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
16751 requirements:
16752 - The complexity is constant.
16753 - Has the semantics of `std::distance(begin(), end())`.
16754
16755 @sa @ref empty() -- checks whether the container is empty
16756 @sa @ref max_size() -- returns the maximal number of elements
16757
16758 @since version 1.0.0
16759 */
16760 size_type size() const noexcept
16761 {
16762 switch (m_type)
16763 {
16764 case value_t::null:
16765 {
16766 // null values are empty
16767 return 0;
16768 }
16769
16770 case value_t::array:
16771 {
16772 // delegate call to array_t::size()
16773 return m_value.array->size();
16774 }
16775
16776 case value_t::object:
16777 {
16778 // delegate call to object_t::size()
16779 return m_value.object->size();
16780 }
16781
16782 default:
16783 {
16784 // all other types have size 1
16785 return 1;
16786 }
16787 }
16788 }
16789
16790 /*!
16791 @brief returns the maximum possible number of elements
16792
16793 Returns the maximum number of elements a JSON value is able to hold due to
16794 system or library implementation limitations, i.e. `std::distance(begin(),
16795 end())` for the JSON value.
16796
16797 @return The return value depends on the different types and is
16798 defined as follows:
16799 Value type | return value
16800 ----------- | -------------
16801 null | `0` (same as `size()`)
16802 boolean | `1` (same as `size()`)
16803 string | `1` (same as `size()`)
16804 number | `1` (same as `size()`)
16805 object | result of function `object_t::max_size()`
16806 array | result of function `array_t::max_size()`
16807
16808 @liveexample{The following code calls `max_size()` on the different value
16809 types. Note the output is implementation specific.,max_size}
16810
16811 @complexity Constant, as long as @ref array_t and @ref object_t satisfy
16812 the Container concept; that is, their `max_size()` functions have constant
16813 complexity.
16814
16815 @iterators No changes.
16816
16817 @exceptionsafety No-throw guarantee: this function never throws exceptions.
16818
16819 @requirement This function helps `basic_json` satisfying the
16820 [Container](https://en.cppreference.com/w/cpp/named_req/Container)
16821 requirements:
16822 - The complexity is constant.
16823 - Has the semantics of returning `b.size()` where `b` is the largest
16824 possible JSON value.
16825
16826 @sa @ref size() -- returns the number of elements
16827
16828 @since version 1.0.0
16829 */
16830 size_type max_size() const noexcept
16831 {
16832 switch (m_type)
16833 {
16834 case value_t::array:
16835 {
16836 // delegate call to array_t::max_size()
16837 return m_value.array->max_size();
16838 }
16839
16840 case value_t::object:
16841 {
16842 // delegate call to object_t::max_size()
16843 return m_value.object->max_size();
16844 }
16845
16846 default:
16847 {
16848 // all other types have max_size() == size()
16849 return size();
16850 }
16851 }
16852 }
16853
16854 /// @}
16855
16856
16857 ///////////////
16858 // modifiers //
16859 ///////////////
16860
16861 /// @name modifiers
16862 /// @{
16863
16864 /*!
16865 @brief clears the contents
16866
16867 Clears the content of a JSON value and resets it to the default value as
16868 if @ref basic_json(value_t) would have been called with the current value
16869 type from @ref type():
16870
16871 Value type | initial value
16872 ----------- | -------------
16873 null | `null`
16874 boolean | `false`
16875 string | `""`
16876 number | `0`
16877 object | `{}`
16878 array | `[]`
16879
16880 @post Has the same effect as calling
16881 @code {.cpp}
16882 *this = basic_json(type());
16883 @endcode
16884
16885 @liveexample{The example below shows the effect of `clear()` to different
16886 JSON types.,clear}
16887
16888 @complexity Linear in the size of the JSON value.
16889
16890 @iterators All iterators, pointers and references related to this container
16891 are invalidated.
16892
16893 @exceptionsafety No-throw guarantee: this function never throws exceptions.
16894
16895 @sa @ref basic_json(value_t) -- constructor that creates an object with the
16896 same value than calling `clear()`
16897
16898 @since version 1.0.0
16899 */
16900 void clear() noexcept
16901 {
16902 switch (m_type)
16903 {
16904 case value_t::number_integer:
16905 {
16906 m_value.number_integer = 0;
16907 break;
16908 }
16909
16910 case value_t::number_unsigned:
16911 {
16912 m_value.number_unsigned = 0;
16913 break;
16914 }
16915
16916 case value_t::number_float:
16917 {
16918 m_value.number_float = 0.0;
16919 break;
16920 }
16921
16922 case value_t::boolean:
16923 {
16924 m_value.boolean = false;
16925 break;
16926 }
16927
16928 case value_t::string:
16929 {
16930 m_value.string->clear();
16931 break;
16932 }
16933
16934 case value_t::array:
16935 {
16936 m_value.array->clear();
16937 break;
16938 }
16939
16940 case value_t::object:
16941 {
16942 m_value.object->clear();
16943 break;
16944 }
16945
16946 default:
16947 break;
16948 }
16949 }
16950
16951 /*!
16952 @brief add an object to an array
16953
16954 Appends the given element @a val to the end of the JSON value. If the
16955 function is called on a JSON null value, an empty array is created before
16956 appending @a val.
16957
16958 @param[in] val the value to add to the JSON array
16959
16960 @throw type_error.308 when called on a type other than JSON array or
16961 null; example: `"cannot use push_back() with number"`
16962
16963 @complexity Amortized constant.
16964
16965 @liveexample{The example shows how `push_back()` and `+=` can be used to
16966 add elements to a JSON array. Note how the `null` value was silently
16967 converted to a JSON array.,push_back}
16968
16969 @since version 1.0.0
16970 */
16971 void push_back(basic_json&& val)
16972 {
16973 // push_back only works for null objects or arrays
16974 if (JSON_UNLIKELY(not(is_null() or is_array())))
16975 {
16976 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
16977 }
16978
16979 // transform null object into an array
16980 if (is_null())
16981 {
16982 m_type = value_t::array;
16983 m_value = value_t::array;
16984 assert_invariant();
16985 }
16986
16987 // add element to array (move semantics)
16988 m_value.array->push_back(std::move(val));
16989 // invalidate object
16990 val.m_type = value_t::null;
16991 }
16992
16993 /*!
16994 @brief add an object to an array
16995 @copydoc push_back(basic_json&&)
16996 */
16997 reference operator+=(basic_json&& val)
16998 {
16999 push_back(std::move(val));
17000 return *this;
17001 }
17002
17003 /*!
17004 @brief add an object to an array
17005 @copydoc push_back(basic_json&&)
17006 */
17007 void push_back(const basic_json& val)
17008 {
17009 // push_back only works for null objects or arrays
17010 if (JSON_UNLIKELY(not(is_null() or is_array())))
17011 {
17012 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17013 }
17014
17015 // transform null object into an array
17016 if (is_null())
17017 {
17018 m_type = value_t::array;
17019 m_value = value_t::array;
17020 assert_invariant();
17021 }
17022
17023 // add element to array
17024 m_value.array->push_back(val);
17025 }
17026
17027 /*!
17028 @brief add an object to an array
17029 @copydoc push_back(basic_json&&)
17030 */
17031 reference operator+=(const basic_json& val)
17032 {
17033 push_back(val);
17034 return *this;
17035 }
17036
17037 /*!
17038 @brief add an object to an object
17039
17040 Inserts the given element @a val to the JSON object. If the function is
17041 called on a JSON null value, an empty object is created before inserting
17042 @a val.
17043
17044 @param[in] val the value to add to the JSON object
17045
17046 @throw type_error.308 when called on a type other than JSON object or
17047 null; example: `"cannot use push_back() with number"`
17048
17049 @complexity Logarithmic in the size of the container, O(log(`size()`)).
17050
17051 @liveexample{The example shows how `push_back()` and `+=` can be used to
17052 add elements to a JSON object. Note how the `null` value was silently
17053 converted to a JSON object.,push_back__object_t__value}
17054
17055 @since version 1.0.0
17056 */
17057 void push_back(const typename object_t::value_type& val)
17058 {
17059 // push_back only works for null objects or objects
17060 if (JSON_UNLIKELY(not(is_null() or is_object())))
17061 {
17062 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17063 }
17064
17065 // transform null object into an object
17066 if (is_null())
17067 {
17068 m_type = value_t::object;
17069 m_value = value_t::object;
17070 assert_invariant();
17071 }
17072
17073 // add element to array
17074 m_value.object->insert(val);
17075 }
17076
17077 /*!
17078 @brief add an object to an object
17079 @copydoc push_back(const typename object_t::value_type&)
17080 */
17081 reference operator+=(const typename object_t::value_type& val)
17082 {
17083 push_back(val);
17084 return *this;
17085 }
17086
17087 /*!
17088 @brief add an object to an object
17089
17090 This function allows to use `push_back` with an initializer list. In case
17091
17092 1. the current value is an object,
17093 2. the initializer list @a init contains only two elements, and
17094 3. the first element of @a init is a string,
17095
17096 @a init is converted into an object element and added using
17097 @ref push_back(const typename object_t::value_type&). Otherwise, @a init
17098 is converted to a JSON value and added using @ref push_back(basic_json&&).
17099
17100 @param[in] init an initializer list
17101
17102 @complexity Linear in the size of the initializer list @a init.
17103
17104 @note This function is required to resolve an ambiguous overload error,
17105 because pairs like `{"key", "value"}` can be both interpreted as
17106 `object_t::value_type` or `std::initializer_list<basic_json>`, see
17107 https://github.com/nlohmann/json/issues/235 for more information.
17108
17109 @liveexample{The example shows how initializer lists are treated as
17110 objects when possible.,push_back__initializer_list}
17111 */
17112 void push_back(initializer_list_t init)
17113 {
17114 if (is_object() and init.size() == 2 and (*init.begin())->is_string())
17115 {
17116 basic_json&& key = init.begin()->moved_or_copied();
17117 push_back(typename object_t::value_type(
17118 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
17119 }
17120 else
17121 {
17122 push_back(basic_json(init));
17123 }
17124 }
17125
17126 /*!
17127 @brief add an object to an object
17128 @copydoc push_back(initializer_list_t)
17129 */
17130 reference operator+=(initializer_list_t init)
17131 {
17132 push_back(init);
17133 return *this;
17134 }
17135
17136 /*!
17137 @brief add an object to an array
17138
17139 Creates a JSON value from the passed parameters @a args to the end of the
17140 JSON value. If the function is called on a JSON null value, an empty array
17141 is created before appending the value created from @a args.
17142
17143 @param[in] args arguments to forward to a constructor of @ref basic_json
17144 @tparam Args compatible types to create a @ref basic_json object
17145
17146 @throw type_error.311 when called on a type other than JSON array or
17147 null; example: `"cannot use emplace_back() with number"`
17148
17149 @complexity Amortized constant.
17150
17151 @liveexample{The example shows how `push_back()` can be used to add
17152 elements to a JSON array. Note how the `null` value was silently converted
17153 to a JSON array.,emplace_back}
17154
17155 @since version 2.0.8
17156 */
17157 template<class... Args>
17158 void emplace_back(Args&& ... args)
17159 {
17160 // emplace_back only works for null objects or arrays
17161 if (JSON_UNLIKELY(not(is_null() or is_array())))
17162 {
17163 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
17164 }
17165
17166 // transform null object into an array
17167 if (is_null())
17168 {
17169 m_type = value_t::array;
17170 m_value = value_t::array;
17171 assert_invariant();
17172 }
17173
17174 // add element to array (perfect forwarding)
17175 m_value.array->emplace_back(std::forward<Args>(args)...);
17176 }
17177
17178 /*!
17179 @brief add an object to an object if key does not exist
17180
17181 Inserts a new element into a JSON object constructed in-place with the
17182 given @a args if there is no element with the key in the container. If the
17183 function is called on a JSON null value, an empty object is created before
17184 appending the value created from @a args.
17185
17186 @param[in] args arguments to forward to a constructor of @ref basic_json
17187 @tparam Args compatible types to create a @ref basic_json object
17188
17189 @return a pair consisting of an iterator to the inserted element, or the
17190 already-existing element if no insertion happened, and a bool
17191 denoting whether the insertion took place.
17192
17193 @throw type_error.311 when called on a type other than JSON object or
17194 null; example: `"cannot use emplace() with number"`
17195
17196 @complexity Logarithmic in the size of the container, O(log(`size()`)).
17197
17198 @liveexample{The example shows how `emplace()` can be used to add elements
17199 to a JSON object. Note how the `null` value was silently converted to a
17200 JSON object. Further note how no value is added if there was already one
17201 value stored with the same key.,emplace}
17202
17203 @since version 2.0.8
17204 */
17205 template<class... Args>
17206 std::pair<iterator, bool> emplace(Args&& ... args)
17207 {
17208 // emplace only works for null objects or arrays
17209 if (JSON_UNLIKELY(not(is_null() or is_object())))
17210 {
17211 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
17212 }
17213
17214 // transform null object into an object
17215 if (is_null())
17216 {
17217 m_type = value_t::object;
17218 m_value = value_t::object;
17219 assert_invariant();
17220 }
17221
17222 // add element to array (perfect forwarding)
17223 auto res = m_value.object->emplace(std::forward<Args>(args)...);
17224 // create result iterator and set iterator to the result of emplace
17225 auto it = begin();
17226 it.m_it.object_iterator = res.first;
17227
17228 // return pair of iterator and boolean
17229 return {it, res.second};
17230 }
17231
17232 /// Helper for insertion of an iterator
17233 /// @note: This uses std::distance to support GCC 4.8,
17234 /// see https://github.com/nlohmann/json/pull/1257
17235 template<typename... Args>
17236 iterator insert_iterator(const_iterator pos, Args&& ... args)
17237 {
17238 iterator result(this);
17239 assert(m_value.array != nullptr);
17240
17241 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
17242 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
17243 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
17244
17245 // This could have been written as:
17246 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
17247 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
17248
17249 return result;
17250 }
17251
17252 /*!
17253 @brief inserts element
17254
17255 Inserts element @a val before iterator @a pos.
17256
17257 @param[in] pos iterator before which the content will be inserted; may be
17258 the end() iterator
17259 @param[in] val element to insert
17260 @return iterator pointing to the inserted @a val.
17261
17262 @throw type_error.309 if called on JSON values other than arrays;
17263 example: `"cannot use insert() with string"`
17264 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
17265 example: `"iterator does not fit current value"`
17266
17267 @complexity Constant plus linear in the distance between @a pos and end of
17268 the container.
17269
17270 @liveexample{The example shows how `insert()` is used.,insert}
17271
17272 @since version 1.0.0
17273 */
17274 iterator insert(const_iterator pos, const basic_json& val)
17275 {
17276 // insert only works for arrays
17277 if (JSON_LIKELY(is_array()))
17278 {
17279 // check if iterator pos fits to this JSON value
17280 if (JSON_UNLIKELY(pos.m_object != this))
17281 {
17282 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17283 }
17284
17285 // insert to array and return iterator
17286 return insert_iterator(pos, val);
17287 }
17288
17289 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17290 }
17291
17292 /*!
17293 @brief inserts element
17294 @copydoc insert(const_iterator, const basic_json&)
17295 */
17296 iterator insert(const_iterator pos, basic_json&& val)
17297 {
17298 return insert(pos, val);
17299 }
17300
17301 /*!
17302 @brief inserts elements
17303
17304 Inserts @a cnt copies of @a val before iterator @a pos.
17305
17306 @param[in] pos iterator before which the content will be inserted; may be
17307 the end() iterator
17308 @param[in] cnt number of copies of @a val to insert
17309 @param[in] val element to insert
17310 @return iterator pointing to the first element inserted, or @a pos if
17311 `cnt==0`
17312
17313 @throw type_error.309 if called on JSON values other than arrays; example:
17314 `"cannot use insert() with string"`
17315 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
17316 example: `"iterator does not fit current value"`
17317
17318 @complexity Linear in @a cnt plus linear in the distance between @a pos
17319 and end of the container.
17320
17321 @liveexample{The example shows how `insert()` is used.,insert__count}
17322
17323 @since version 1.0.0
17324 */
17325 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
17326 {
17327 // insert only works for arrays
17328 if (JSON_LIKELY(is_array()))
17329 {
17330 // check if iterator pos fits to this JSON value
17331 if (JSON_UNLIKELY(pos.m_object != this))
17332 {
17333 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17334 }
17335
17336 // insert to array and return iterator
17337 return insert_iterator(pos, cnt, val);
17338 }
17339
17340 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17341 }
17342
17343 /*!
17344 @brief inserts elements
17345
17346 Inserts elements from range `[first, last)` before iterator @a pos.
17347
17348 @param[in] pos iterator before which the content will be inserted; may be
17349 the end() iterator
17350 @param[in] first begin of the range of elements to insert
17351 @param[in] last end of the range of elements to insert
17352
17353 @throw type_error.309 if called on JSON values other than arrays; example:
17354 `"cannot use insert() with string"`
17355 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
17356 example: `"iterator does not fit current value"`
17357 @throw invalid_iterator.210 if @a first and @a last do not belong to the
17358 same JSON value; example: `"iterators do not fit"`
17359 @throw invalid_iterator.211 if @a first or @a last are iterators into
17360 container for which insert is called; example: `"passed iterators may not
17361 belong to container"`
17362
17363 @return iterator pointing to the first element inserted, or @a pos if
17364 `first==last`
17365
17366 @complexity Linear in `std::distance(first, last)` plus linear in the
17367 distance between @a pos and end of the container.
17368
17369 @liveexample{The example shows how `insert()` is used.,insert__range}
17370
17371 @since version 1.0.0
17372 */
17373 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
17374 {
17375 // insert only works for arrays
17376 if (JSON_UNLIKELY(not is_array()))
17377 {
17378 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17379 }
17380
17381 // check if iterator pos fits to this JSON value
17382 if (JSON_UNLIKELY(pos.m_object != this))
17383 {
17384 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17385 }
17386
17387 // check if range iterators belong to the same JSON object
17388 if (JSON_UNLIKELY(first.m_object != last.m_object))
17389 {
17390 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
17391 }
17392
17393 if (JSON_UNLIKELY(first.m_object == this))
17394 {
17395 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
17396 }
17397
17398 // insert to array and return iterator
17399 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
17400 }
17401
17402 /*!
17403 @brief inserts elements
17404
17405 Inserts elements from initializer list @a ilist before iterator @a pos.
17406
17407 @param[in] pos iterator before which the content will be inserted; may be
17408 the end() iterator
17409 @param[in] ilist initializer list to insert the values from
17410
17411 @throw type_error.309 if called on JSON values other than arrays; example:
17412 `"cannot use insert() with string"`
17413 @throw invalid_iterator.202 if @a pos is not an iterator of *this;
17414 example: `"iterator does not fit current value"`
17415
17416 @return iterator pointing to the first element inserted, or @a pos if
17417 `ilist` is empty
17418
17419 @complexity Linear in `ilist.size()` plus linear in the distance between
17420 @a pos and end of the container.
17421
17422 @liveexample{The example shows how `insert()` is used.,insert__ilist}
17423
17424 @since version 1.0.0
17425 */
17426 iterator insert(const_iterator pos, initializer_list_t ilist)
17427 {
17428 // insert only works for arrays
17429 if (JSON_UNLIKELY(not is_array()))
17430 {
17431 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17432 }
17433
17434 // check if iterator pos fits to this JSON value
17435 if (JSON_UNLIKELY(pos.m_object != this))
17436 {
17437 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17438 }
17439
17440 // insert to array and return iterator
17441 return insert_iterator(pos, ilist.begin(), ilist.end());
17442 }
17443
17444 /*!
17445 @brief inserts elements
17446
17447 Inserts elements from range `[first, last)`.
17448
17449 @param[in] first begin of the range of elements to insert
17450 @param[in] last end of the range of elements to insert
17451
17452 @throw type_error.309 if called on JSON values other than objects; example:
17453 `"cannot use insert() with string"`
17454 @throw invalid_iterator.202 if iterator @a first or @a last does does not
17455 point to an object; example: `"iterators first and last must point to
17456 objects"`
17457 @throw invalid_iterator.210 if @a first and @a last do not belong to the
17458 same JSON value; example: `"iterators do not fit"`
17459
17460 @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
17461 of elements to insert.
17462
17463 @liveexample{The example shows how `insert()` is used.,insert__range_object}
17464
17465 @since version 3.0.0
17466 */
17467 void insert(const_iterator first, const_iterator last)
17468 {
17469 // insert only works for objects
17470 if (JSON_UNLIKELY(not is_object()))
17471 {
17472 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17473 }
17474
17475 // check if range iterators belong to the same JSON object
17476 if (JSON_UNLIKELY(first.m_object != last.m_object))
17477 {
17478 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
17479 }
17480
17481 // passed iterators must belong to objects
17482 if (JSON_UNLIKELY(not first.m_object->is_object()))
17483 {
17484 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
17485 }
17486
17487 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
17488 }
17489
17490 /*!
17491 @brief updates a JSON object from another object, overwriting existing keys
17492
17493 Inserts all values from JSON object @a j and overwrites existing keys.
17494
17495 @param[in] j JSON object to read values from
17496
17497 @throw type_error.312 if called on JSON values other than objects; example:
17498 `"cannot use update() with string"`
17499
17500 @complexity O(N*log(size() + N)), where N is the number of elements to
17501 insert.
17502
17503 @liveexample{The example shows how `update()` is used.,update}
17504
17505 @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
17506
17507 @since version 3.0.0
17508 */
17509 void update(const_reference j)
17510 {
17511 // implicitly convert null value to an empty object
17512 if (is_null())
17513 {
17514 m_type = value_t::object;
17515 m_value.object = create<object_t>();
17516 assert_invariant();
17517 }
17518
17519 if (JSON_UNLIKELY(not is_object()))
17520 {
17521 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
17522 }
17523 if (JSON_UNLIKELY(not j.is_object()))
17524 {
17525 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
17526 }
17527
17528 for (auto it = j.cbegin(); it != j.cend(); ++it)
17529 {
17530 m_value.object->operator[](it.key()) = it.value();
17531 }
17532 }
17533
17534 /*!
17535 @brief updates a JSON object from another object, overwriting existing keys
17536
17537 Inserts all values from from range `[first, last)` and overwrites existing
17538 keys.
17539
17540 @param[in] first begin of the range of elements to insert
17541 @param[in] last end of the range of elements to insert
17542
17543 @throw type_error.312 if called on JSON values other than objects; example:
17544 `"cannot use update() with string"`
17545 @throw invalid_iterator.202 if iterator @a first or @a last does does not
17546 point to an object; example: `"iterators first and last must point to
17547 objects"`
17548 @throw invalid_iterator.210 if @a first and @a last do not belong to the
17549 same JSON value; example: `"iterators do not fit"`
17550
17551 @complexity O(N*log(size() + N)), where N is the number of elements to
17552 insert.
17553
17554 @liveexample{The example shows how `update()` is used__range.,update}
17555
17556 @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
17557
17558 @since version 3.0.0
17559 */
17560 void update(const_iterator first, const_iterator last)
17561 {
17562 // implicitly convert null value to an empty object
17563 if (is_null())
17564 {
17565 m_type = value_t::object;
17566 m_value.object = create<object_t>();
17567 assert_invariant();
17568 }
17569
17570 if (JSON_UNLIKELY(not is_object()))
17571 {
17572 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
17573 }
17574
17575 // check if range iterators belong to the same JSON object
17576 if (JSON_UNLIKELY(first.m_object != last.m_object))
17577 {
17578 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
17579 }
17580
17581 // passed iterators must belong to objects
17582 if (JSON_UNLIKELY(not first.m_object->is_object()
17583 or not last.m_object->is_object()))
17584 {
17585 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
17586 }
17587
17588 for (auto it = first; it != last; ++it)
17589 {
17590 m_value.object->operator[](it.key()) = it.value();
17591 }
17592 }
17593
17594 /*!
17595 @brief exchanges the values
17596
17597 Exchanges the contents of the JSON value with those of @a other. Does not
17598 invoke any move, copy, or swap operations on individual elements. All
17599 iterators and references remain valid. The past-the-end iterator is
17600 invalidated.
17601
17602 @param[in,out] other JSON value to exchange the contents with
17603
17604 @complexity Constant.
17605
17606 @liveexample{The example below shows how JSON values can be swapped with
17607 `swap()`.,swap__reference}
17608
17609 @since version 1.0.0
17610 */
17611 void swap(reference other) noexcept (
17612 std::is_nothrow_move_constructible<value_t>::value and
17613 std::is_nothrow_move_assignable<value_t>::value and
17614 std::is_nothrow_move_constructible<json_value>::value and
17615 std::is_nothrow_move_assignable<json_value>::value
17616 )
17617 {
17618 std::swap(m_type, other.m_type);
17619 std::swap(m_value, other.m_value);
17620 assert_invariant();
17621 }
17622
17623 /*!
17624 @brief exchanges the values
17625
17626 Exchanges the contents of a JSON array with those of @a other. Does not
17627 invoke any move, copy, or swap operations on individual elements. All
17628 iterators and references remain valid. The past-the-end iterator is
17629 invalidated.
17630
17631 @param[in,out] other array to exchange the contents with
17632
17633 @throw type_error.310 when JSON value is not an array; example: `"cannot
17634 use swap() with string"`
17635
17636 @complexity Constant.
17637
17638 @liveexample{The example below shows how arrays can be swapped with
17639 `swap()`.,swap__array_t}
17640
17641 @since version 1.0.0
17642 */
17643 void swap(array_t& other)
17644 {
17645 // swap only works for arrays
17646 if (JSON_LIKELY(is_array()))
17647 {
17648 std::swap(*(m_value.array), other);
17649 }
17650 else
17651 {
17652 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
17653 }
17654 }
17655
17656 /*!
17657 @brief exchanges the values
17658
17659 Exchanges the contents of a JSON object with those of @a other. Does not
17660 invoke any move, copy, or swap operations on individual elements. All
17661 iterators and references remain valid. The past-the-end iterator is
17662 invalidated.
17663
17664 @param[in,out] other object to exchange the contents with
17665
17666 @throw type_error.310 when JSON value is not an object; example:
17667 `"cannot use swap() with string"`
17668
17669 @complexity Constant.
17670
17671 @liveexample{The example below shows how objects can be swapped with
17672 `swap()`.,swap__object_t}
17673
17674 @since version 1.0.0
17675 */
17676 void swap(object_t& other)
17677 {
17678 // swap only works for objects
17679 if (JSON_LIKELY(is_object()))
17680 {
17681 std::swap(*(m_value.object), other);
17682 }
17683 else
17684 {
17685 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
17686 }
17687 }
17688
17689 /*!
17690 @brief exchanges the values
17691
17692 Exchanges the contents of a JSON string with those of @a other. Does not
17693 invoke any move, copy, or swap operations on individual elements. All
17694 iterators and references remain valid. The past-the-end iterator is
17695 invalidated.
17696
17697 @param[in,out] other string to exchange the contents with
17698
17699 @throw type_error.310 when JSON value is not a string; example: `"cannot
17700 use swap() with boolean"`
17701
17702 @complexity Constant.
17703
17704 @liveexample{The example below shows how strings can be swapped with
17705 `swap()`.,swap__string_t}
17706
17707 @since version 1.0.0
17708 */
17709 void swap(string_t& other)
17710 {
17711 // swap only works for strings
17712 if (JSON_LIKELY(is_string()))
17713 {
17714 std::swap(*(m_value.string), other);
17715 }
17716 else
17717 {
17718 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
17719 }
17720 }
17721
17722 /// @}
17723
17724 public:
17725 //////////////////////////////////////////
17726 // lexicographical comparison operators //
17727 //////////////////////////////////////////
17728
17729 /// @name lexicographical comparison operators
17730 /// @{
17731
17732 /*!
17733 @brief comparison: equal
17734
17735 Compares two JSON values for equality according to the following rules:
17736 - Two JSON values are equal if (1) they are from the same type and (2)
17737 their stored values are the same according to their respective
17738 `operator==`.
17739 - Integer and floating-point numbers are automatically converted before
17740 comparison. Note than two NaN values are always treated as unequal.
17741 - Two JSON null values are equal.
17742
17743 @note Floating-point inside JSON values numbers are compared with
17744 `json::number_float_t::operator==` which is `double::operator==` by
17745 default. To compare floating-point while respecting an epsilon, an alternative
17746 [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)
17747 could be used, for instance
17748 @code {.cpp}
17749 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
17750 inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
17751 {
17752 return std::abs(a - b) <= epsilon;
17753 }
17754 @endcode
17755
17756 @note NaN values never compare equal to themselves or to other NaN values.
17757
17758 @param[in] lhs first JSON value to consider
17759 @param[in] rhs second JSON value to consider
17760 @return whether the values @a lhs and @a rhs are equal
17761
17762 @exceptionsafety No-throw guarantee: this function never throws exceptions.
17763
17764 @complexity Linear.
17765
17766 @liveexample{The example demonstrates comparing several JSON
17767 types.,operator__equal}
17768
17769 @since version 1.0.0
17770 */
17771 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
17772 {
17773 const auto lhs_type = lhs.type();
17774 const auto rhs_type = rhs.type();
17775
17776 if (lhs_type == rhs_type)
17777 {
17778 switch (lhs_type)
17779 {
17780 case value_t::array:
17781 return (*lhs.m_value.array == *rhs.m_value.array);
17782
17783 case value_t::object:
17784 return (*lhs.m_value.object == *rhs.m_value.object);
17785
17786 case value_t::null:
17787 return true;
17788
17789 case value_t::string:
17790 return (*lhs.m_value.string == *rhs.m_value.string);
17791
17792 case value_t::boolean:
17793 return (lhs.m_value.boolean == rhs.m_value.boolean);
17794
17795 case value_t::number_integer:
17796 return (lhs.m_value.number_integer == rhs.m_value.number_integer);
17797
17798 case value_t::number_unsigned:
17799 return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
17800
17801 case value_t::number_float:
17802 return (lhs.m_value.number_float == rhs.m_value.number_float);
17803
17804 default:
17805 return false;
17806 }
17807 }
17808 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
17809 {
17810 return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
17811 }
17812 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
17813 {
17814 return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
17815 }
17816 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
17817 {
17818 return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
17819 }
17820 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
17821 {
17822 return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
17823 }
17824 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
17825 {
17826 return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
17827 }
17828 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
17829 {
17830 return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
17831 }
17832
17833 return false;
17834 }
17835
17836 /*!
17837 @brief comparison: equal
17838 @copydoc operator==(const_reference, const_reference)
17839 */
17840 template<typename ScalarType, typename std::enable_if<
17841 std::is_scalar<ScalarType>::value, int>::type = 0>
17842 friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
17843 {
17844 return (lhs == basic_json(rhs));
17845 }
17846
17847 /*!
17848 @brief comparison: equal
17849 @copydoc operator==(const_reference, const_reference)
17850 */
17851 template<typename ScalarType, typename std::enable_if<
17852 std::is_scalar<ScalarType>::value, int>::type = 0>
17853 friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
17854 {
17855 return (basic_json(lhs) == rhs);
17856 }
17857
17858 /*!
17859 @brief comparison: not equal
17860
17861 Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
17862
17863 @param[in] lhs first JSON value to consider
17864 @param[in] rhs second JSON value to consider
17865 @return whether the values @a lhs and @a rhs are not equal
17866
17867 @complexity Linear.
17868
17869 @exceptionsafety No-throw guarantee: this function never throws exceptions.
17870
17871 @liveexample{The example demonstrates comparing several JSON
17872 types.,operator__notequal}
17873
17874 @since version 1.0.0
17875 */
17876 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
17877 {
17878 return not (lhs == rhs);
17879 }
17880
17881 /*!
17882 @brief comparison: not equal
17883 @copydoc operator!=(const_reference, const_reference)
17884 */
17885 template<typename ScalarType, typename std::enable_if<
17886 std::is_scalar<ScalarType>::value, int>::type = 0>
17887 friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
17888 {
17889 return (lhs != basic_json(rhs));
17890 }
17891
17892 /*!
17893 @brief comparison: not equal
17894 @copydoc operator!=(const_reference, const_reference)
17895 */
17896 template<typename ScalarType, typename std::enable_if<
17897 std::is_scalar<ScalarType>::value, int>::type = 0>
17898 friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
17899 {
17900 return (basic_json(lhs) != rhs);
17901 }
17902
17903 /*!
17904 @brief comparison: less than
17905
17906 Compares whether one JSON value @a lhs is less than another JSON value @a
17907 rhs according to the following rules:
17908 - If @a lhs and @a rhs have the same type, the values are compared using
17909 the default `<` operator.
17910 - Integer and floating-point numbers are automatically converted before
17911 comparison
17912 - In case @a lhs and @a rhs have different types, the values are ignored
17913 and the order of the types is considered, see
17914 @ref operator<(const value_t, const value_t).
17915
17916 @param[in] lhs first JSON value to consider
17917 @param[in] rhs second JSON value to consider
17918 @return whether @a lhs is less than @a rhs
17919
17920 @complexity Linear.
17921
17922 @exceptionsafety No-throw guarantee: this function never throws exceptions.
17923
17924 @liveexample{The example demonstrates comparing several JSON
17925 types.,operator__less}
17926
17927 @since version 1.0.0
17928 */
17929 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
17930 {
17931 const auto lhs_type = lhs.type();
17932 const auto rhs_type = rhs.type();
17933
17934 if (lhs_type == rhs_type)
17935 {
17936 switch (lhs_type)
17937 {
17938 case value_t::array:
17939 return (*lhs.m_value.array) < (*rhs.m_value.array);
17940
17941 case value_t::object:
17942 return *lhs.m_value.object < *rhs.m_value.object;
17943
17944 case value_t::null:
17945 return false;
17946
17947 case value_t::string:
17948 return *lhs.m_value.string < *rhs.m_value.string;
17949
17950 case value_t::boolean:
17951 return lhs.m_value.boolean < rhs.m_value.boolean;
17952
17953 case value_t::number_integer:
17954 return lhs.m_value.number_integer < rhs.m_value.number_integer;
17955
17956 case value_t::number_unsigned:
17957 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
17958
17959 case value_t::number_float:
17960 return lhs.m_value.number_float < rhs.m_value.number_float;
17961
17962 default:
17963 return false;
17964 }
17965 }
17966 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
17967 {
17968 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
17969 }
17970 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
17971 {
17972 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
17973 }
17974 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
17975 {
17976 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
17977 }
17978 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
17979 {
17980 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
17981 }
17982 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
17983 {
17984 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
17985 }
17986 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
17987 {
17988 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
17989 }
17990
17991 // We only reach this line if we cannot compare values. In that case,
17992 // we compare types. Note we have to call the operator explicitly,
17993 // because MSVC has problems otherwise.
17994 return operator<(lhs_type, rhs_type);
17995 }
17996
17997 /*!
17998 @brief comparison: less than
17999 @copydoc operator<(const_reference, const_reference)
18000 */
18001 template<typename ScalarType, typename std::enable_if<
18002 std::is_scalar<ScalarType>::value, int>::type = 0>
18003 friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
18004 {
18005 return (lhs < basic_json(rhs));
18006 }
18007
18008 /*!
18009 @brief comparison: less than
18010 @copydoc operator<(const_reference, const_reference)
18011 */
18012 template<typename ScalarType, typename std::enable_if<
18013 std::is_scalar<ScalarType>::value, int>::type = 0>
18014 friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
18015 {
18016 return (basic_json(lhs) < rhs);
18017 }
18018
18019 /*!
18020 @brief comparison: less than or equal
18021
18022 Compares whether one JSON value @a lhs is less than or equal to another
18023 JSON value by calculating `not (rhs < lhs)`.
18024
18025 @param[in] lhs first JSON value to consider
18026 @param[in] rhs second JSON value to consider
18027 @return whether @a lhs is less than or equal to @a rhs
18028
18029 @complexity Linear.
18030
18031 @exceptionsafety No-throw guarantee: this function never throws exceptions.
18032
18033 @liveexample{The example demonstrates comparing several JSON
18034 types.,operator__greater}
18035
18036 @since version 1.0.0
18037 */
18038 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
18039 {
18040 return not (rhs < lhs);
18041 }
18042
18043 /*!
18044 @brief comparison: less than or equal
18045 @copydoc operator<=(const_reference, const_reference)
18046 */
18047 template<typename ScalarType, typename std::enable_if<
18048 std::is_scalar<ScalarType>::value, int>::type = 0>
18049 friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
18050 {
18051 return (lhs <= basic_json(rhs));
18052 }
18053
18054 /*!
18055 @brief comparison: less than or equal
18056 @copydoc operator<=(const_reference, const_reference)
18057 */
18058 template<typename ScalarType, typename std::enable_if<
18059 std::is_scalar<ScalarType>::value, int>::type = 0>
18060 friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
18061 {
18062 return (basic_json(lhs) <= rhs);
18063 }
18064
18065 /*!
18066 @brief comparison: greater than
18067
18068 Compares whether one JSON value @a lhs is greater than another
18069 JSON value by calculating `not (lhs <= rhs)`.
18070
18071 @param[in] lhs first JSON value to consider
18072 @param[in] rhs second JSON value to consider
18073 @return whether @a lhs is greater than to @a rhs
18074
18075 @complexity Linear.
18076
18077 @exceptionsafety No-throw guarantee: this function never throws exceptions.
18078
18079 @liveexample{The example demonstrates comparing several JSON
18080 types.,operator__lessequal}
18081
18082 @since version 1.0.0
18083 */
18084 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
18085 {
18086 return not (lhs <= rhs);
18087 }
18088
18089 /*!
18090 @brief comparison: greater than
18091 @copydoc operator>(const_reference, const_reference)
18092 */
18093 template<typename ScalarType, typename std::enable_if<
18094 std::is_scalar<ScalarType>::value, int>::type = 0>
18095 friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
18096 {
18097 return (lhs > basic_json(rhs));
18098 }
18099
18100 /*!
18101 @brief comparison: greater than
18102 @copydoc operator>(const_reference, const_reference)
18103 */
18104 template<typename ScalarType, typename std::enable_if<
18105 std::is_scalar<ScalarType>::value, int>::type = 0>
18106 friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
18107 {
18108 return (basic_json(lhs) > rhs);
18109 }
18110
18111 /*!
18112 @brief comparison: greater than or equal
18113
18114 Compares whether one JSON value @a lhs is greater than or equal to another
18115 JSON value by calculating `not (lhs < rhs)`.
18116
18117 @param[in] lhs first JSON value to consider
18118 @param[in] rhs second JSON value to consider
18119 @return whether @a lhs is greater than or equal to @a rhs
18120
18121 @complexity Linear.
18122
18123 @exceptionsafety No-throw guarantee: this function never throws exceptions.
18124
18125 @liveexample{The example demonstrates comparing several JSON
18126 types.,operator__greaterequal}
18127
18128 @since version 1.0.0
18129 */
18130 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
18131 {
18132 return not (lhs < rhs);
18133 }
18134
18135 /*!
18136 @brief comparison: greater than or equal
18137 @copydoc operator>=(const_reference, const_reference)
18138 */
18139 template<typename ScalarType, typename std::enable_if<
18140 std::is_scalar<ScalarType>::value, int>::type = 0>
18141 friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
18142 {
18143 return (lhs >= basic_json(rhs));
18144 }
18145
18146 /*!
18147 @brief comparison: greater than or equal
18148 @copydoc operator>=(const_reference, const_reference)
18149 */
18150 template<typename ScalarType, typename std::enable_if<
18151 std::is_scalar<ScalarType>::value, int>::type = 0>
18152 friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
18153 {
18154 return (basic_json(lhs) >= rhs);
18155 }
18156
18157 /// @}
18158
18159 ///////////////////
18160 // serialization //
18161 ///////////////////
18162
18163 /// @name serialization
18164 /// @{
18165
18166 /*!
18167 @brief serialize to stream
18168
18169 Serialize the given JSON value @a j to the output stream @a o. The JSON
18170 value will be serialized using the @ref dump member function.
18171
18172 - The indentation of the output can be controlled with the member variable
18173 `width` of the output stream @a o. For instance, using the manipulator
18174 `std::setw(4)` on @a o sets the indentation level to `4` and the
18175 serialization result is the same as calling `dump(4)`.
18176
18177 - The indentation character can be controlled with the member variable
18178 `fill` of the output stream @a o. For instance, the manipulator
18179 `std::setfill('\\t')` sets indentation to use a tab character rather than
18180 the default space character.
18181
18182 @param[in,out] o stream to serialize to
18183 @param[in] j JSON value to serialize
18184
18185 @return the stream @a o
18186
18187 @throw type_error.316 if a string stored inside the JSON value is not
18188 UTF-8 encoded
18189
18190 @complexity Linear.
18191
18192 @liveexample{The example below shows the serialization with different
18193 parameters to `width` to adjust the indentation level.,operator_serialize}
18194
18195 @since version 1.0.0; indentation character added in version 3.0.0
18196 */
18197 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
18198 {
18199 // read width member and use it as indentation parameter if nonzero
18200 const bool pretty_print = (o.width() > 0);
18201 const auto indentation = (pretty_print ? o.width() : 0);
18202
18203 // reset width to 0 for subsequent calls to this stream
18204 o.width(0);
18205
18206 // do the actual serialization
18207 serializer s(detail::output_adapter<char>(o), o.fill());
18208 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
18209 return o;
18210 }
18211
18212 /*!
18213 @brief serialize to stream
18214 @deprecated This stream operator is deprecated and will be removed in
18215 future 4.0.0 of the library. Please use
18216 @ref operator<<(std::ostream&, const basic_json&)
18217 instead; that is, replace calls like `j >> o;` with `o << j;`.
18218 @since version 1.0.0; deprecated since version 3.0.0
18219 */
18220 JSON_DEPRECATED
18221 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
18222 {
18223 return o << j;
18224 }
18225
18226 /// @}
18227
18228
18229 /////////////////////
18230 // deserialization //
18231 /////////////////////
18232
18233 /// @name deserialization
18234 /// @{
18235
18236 /*!
18237 @brief deserialize from a compatible input
18238
18239 This function reads from a compatible input. Examples are:
18240 - an array of 1-byte values
18241 - strings with character/literal type with size of 1 byte
18242 - input streams
18243 - container with contiguous storage of 1-byte values. Compatible container
18244 types include `std::vector`, `std::string`, `std::array`,
18245 `std::valarray`, and `std::initializer_list`. Furthermore, C-style
18246 arrays can be used with `std::begin()`/`std::end()`. User-defined
18247 containers can be used as long as they implement random-access iterators
18248 and a contiguous storage.
18249
18250 @pre Each element of the container has a size of 1 byte. Violating this
18251 precondition yields undefined behavior. **This precondition is enforced
18252 with a static assertion.**
18253
18254 @pre The container storage is contiguous. Violating this precondition
18255 yields undefined behavior. **This precondition is enforced with an
18256 assertion.**
18257 @pre Each element of the container has a size of 1 byte. Violating this
18258 precondition yields undefined behavior. **This precondition is enforced
18259 with a static assertion.**
18260
18261 @warning There is no way to enforce all preconditions at compile-time. If
18262 the function is called with a noncompliant container and with
18263 assertions switched off, the behavior is undefined and will most
18264 likely yield segmentation violation.
18265
18266 @param[in] i input to read from
18267 @param[in] cb a parser callback function of type @ref parser_callback_t
18268 which is used to control the deserialization by filtering unwanted values
18269 (optional)
18270 @param[in] allow_exceptions whether to throw exceptions in case of a
18271 parse error (optional, true by default)
18272
18273 @return result of the deserialization
18274
18275 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
18276 of input; expected string literal""`
18277 @throw parse_error.102 if to_unicode fails or surrogate error
18278 @throw parse_error.103 if to_unicode fails
18279
18280 @complexity Linear in the length of the input. The parser is a predictive
18281 LL(1) parser. The complexity can be higher if the parser callback function
18282 @a cb has a super-linear complexity.
18283
18284 @note A UTF-8 byte order mark is silently ignored.
18285
18286 @liveexample{The example below demonstrates the `parse()` function reading
18287 from an array.,parse__array__parser_callback_t}
18288
18289 @liveexample{The example below demonstrates the `parse()` function with
18290 and without callback function.,parse__string__parser_callback_t}
18291
18292 @liveexample{The example below demonstrates the `parse()` function with
18293 and without callback function.,parse__istream__parser_callback_t}
18294
18295 @liveexample{The example below demonstrates the `parse()` function reading
18296 from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
18297
18298 @since version 2.0.3 (contiguous containers)
18299 */
18300 static basic_json parse(detail::input_adapter&& i,
18301 const parser_callback_t cb = nullptr,
18302 const bool allow_exceptions = true)
18303 {
18304 basic_json result;
18305 parser(i, cb, allow_exceptions).parse(true, result);
18306 return result;
18307 }
18308
18309 static bool accept(detail::input_adapter&& i)
18310 {
18311 return parser(i).accept(true);
18312 }
18313
18314 /*!
18315 @brief generate SAX events
18316
18317 The SAX event lister must follow the interface of @ref json_sax.
18318
18319 This function reads from a compatible input. Examples are:
18320 - an array of 1-byte values
18321 - strings with character/literal type with size of 1 byte
18322 - input streams
18323 - container with contiguous storage of 1-byte values. Compatible container
18324 types include `std::vector`, `std::string`, `std::array`,
18325 `std::valarray`, and `std::initializer_list`. Furthermore, C-style
18326 arrays can be used with `std::begin()`/`std::end()`. User-defined
18327 containers can be used as long as they implement random-access iterators
18328 and a contiguous storage.
18329
18330 @pre Each element of the container has a size of 1 byte. Violating this
18331 precondition yields undefined behavior. **This precondition is enforced
18332 with a static assertion.**
18333
18334 @pre The container storage is contiguous. Violating this precondition
18335 yields undefined behavior. **This precondition is enforced with an
18336 assertion.**
18337 @pre Each element of the container has a size of 1 byte. Violating this
18338 precondition yields undefined behavior. **This precondition is enforced
18339 with a static assertion.**
18340
18341 @warning There is no way to enforce all preconditions at compile-time. If
18342 the function is called with a noncompliant container and with
18343 assertions switched off, the behavior is undefined and will most
18344 likely yield segmentation violation.
18345
18346 @param[in] i input to read from
18347 @param[in,out] sax SAX event listener
18348 @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON)
18349 @param[in] strict whether the input has to be consumed completely
18350
18351 @return return value of the last processed SAX event
18352
18353 @throw parse_error.101 if a parse error occurs; example: `""unexpected end
18354 of input; expected string literal""`
18355 @throw parse_error.102 if to_unicode fails or surrogate error
18356 @throw parse_error.103 if to_unicode fails
18357
18358 @complexity Linear in the length of the input. The parser is a predictive
18359 LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
18360 a super-linear complexity.
18361
18362 @note A UTF-8 byte order mark is silently ignored.
18363
18364 @liveexample{The example below demonstrates the `sax_parse()` function
18365 reading from string and processing the events with a user-defined SAX
18366 event consumer.,sax_parse}
18367
18368 @since version 3.2.0
18369 */
18370 template <typename SAX>
18371 static bool sax_parse(detail::input_adapter&& i, SAX* sax,
18372 input_format_t format = input_format_t::json,
18373 const bool strict = true)
18374 {
18375 assert(sax);
18376 switch (format)
18377 {
18378 case input_format_t::json:
18379 return parser(std::move(i)).sax_parse(sax, strict);
18380 default:
18381 return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
18382 }
18383 }
18384
18385 /*!
18386 @brief deserialize from an iterator range with contiguous storage
18387
18388 This function reads from an iterator range of a container with contiguous
18389 storage of 1-byte values. Compatible container types include
18390 `std::vector`, `std::string`, `std::array`, `std::valarray`, and
18391 `std::initializer_list`. Furthermore, C-style arrays can be used with
18392 `std::begin()`/`std::end()`. User-defined containers can be used as long
18393 as they implement random-access iterators and a contiguous storage.
18394
18395 @pre The iterator range is contiguous. Violating this precondition yields
18396 undefined behavior. **This precondition is enforced with an assertion.**
18397 @pre Each element in the range has a size of 1 byte. Violating this
18398 precondition yields undefined behavior. **This precondition is enforced
18399 with a static assertion.**
18400
18401 @warning There is no way to enforce all preconditions at compile-time. If
18402 the function is called with noncompliant iterators and with
18403 assertions switched off, the behavior is undefined and will most
18404 likely yield segmentation violation.
18405
18406 @tparam IteratorType iterator of container with contiguous storage
18407 @param[in] first begin of the range to parse (included)
18408 @param[in] last end of the range to parse (excluded)
18409 @param[in] cb a parser callback function of type @ref parser_callback_t
18410 which is used to control the deserialization by filtering unwanted values
18411 (optional)
18412 @param[in] allow_exceptions whether to throw exceptions in case of a
18413 parse error (optional, true by default)
18414
18415 @return result of the deserialization
18416
18417 @throw parse_error.101 in case of an unexpected token
18418 @throw parse_error.102 if to_unicode fails or surrogate error
18419 @throw parse_error.103 if to_unicode fails
18420
18421 @complexity Linear in the length of the input. The parser is a predictive
18422 LL(1) parser. The complexity can be higher if the parser callback function
18423 @a cb has a super-linear complexity.
18424
18425 @note A UTF-8 byte order mark is silently ignored.
18426
18427 @liveexample{The example below demonstrates the `parse()` function reading
18428 from an iterator range.,parse__iteratortype__parser_callback_t}
18429
18430 @since version 2.0.3
18431 */
18432 template<class IteratorType, typename std::enable_if<
18433 std::is_base_of<
18434 std::random_access_iterator_tag,
18435 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
18436 static basic_json parse(IteratorType first, IteratorType last,
18437 const parser_callback_t cb = nullptr,
18438 const bool allow_exceptions = true)
18439 {
18440 basic_json result;
18441 parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
18442 return result;
18443 }
18444
18445 template<class IteratorType, typename std::enable_if<
18446 std::is_base_of<
18447 std::random_access_iterator_tag,
18448 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
18449 static bool accept(IteratorType first, IteratorType last)
18450 {
18451 return parser(detail::input_adapter(first, last)).accept(true);
18452 }
18453
18454 template<class IteratorType, class SAX, typename std::enable_if<
18455 std::is_base_of<
18456 std::random_access_iterator_tag,
18457 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
18458 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
18459 {
18460 return parser(detail::input_adapter(first, last)).sax_parse(sax);
18461 }
18462
18463 /*!
18464 @brief deserialize from stream
18465 @deprecated This stream operator is deprecated and will be removed in
18466 version 4.0.0 of the library. Please use
18467 @ref operator>>(std::istream&, basic_json&)
18468 instead; that is, replace calls like `j << i;` with `i >> j;`.
18469 @since version 1.0.0; deprecated since version 3.0.0
18470 */
18471 JSON_DEPRECATED
18472 friend std::istream& operator<<(basic_json& j, std::istream& i)
18473 {
18474 return operator>>(i, j);
18475 }
18476
18477 /*!
18478 @brief deserialize from stream
18479
18480 Deserializes an input stream to a JSON value.
18481
18482 @param[in,out] i input stream to read a serialized JSON value from
18483 @param[in,out] j JSON value to write the deserialized input to
18484
18485 @throw parse_error.101 in case of an unexpected token
18486 @throw parse_error.102 if to_unicode fails or surrogate error
18487 @throw parse_error.103 if to_unicode fails
18488
18489 @complexity Linear in the length of the input. The parser is a predictive
18490 LL(1) parser.
18491
18492 @note A UTF-8 byte order mark is silently ignored.
18493
18494 @liveexample{The example below shows how a JSON value is constructed by
18495 reading a serialization from a stream.,operator_deserialize}
18496
18497 @sa parse(std::istream&, const parser_callback_t) for a variant with a
18498 parser callback function to filter values while parsing
18499
18500 @since version 1.0.0
18501 */
18502 friend std::istream& operator>>(std::istream& i, basic_json& j)
18503 {
18504 parser(detail::input_adapter(i)).parse(false, j);
18505 return i;
18506 }
18507
18508 /// @}
18509
18510 ///////////////////////////
18511 // convenience functions //
18512 ///////////////////////////
18513
18514 /*!
18515 @brief return the type as string
18516
18517 Returns the type name as string to be used in error messages - usually to
18518 indicate that a function was called on a wrong JSON type.
18519
18520 @return a string representation of a the @a m_type member:
18521 Value type | return value
18522 ----------- | -------------
18523 null | `"null"`
18524 boolean | `"boolean"`
18525 string | `"string"`
18526 number | `"number"` (for all number types)
18527 object | `"object"`
18528 array | `"array"`
18529 discarded | `"discarded"`
18530
18531 @exceptionsafety No-throw guarantee: this function never throws exceptions.
18532
18533 @complexity Constant.
18534
18535 @liveexample{The following code exemplifies `type_name()` for all JSON
18536 types.,type_name}
18537
18538 @sa @ref type() -- return the type of the JSON value
18539 @sa @ref operator value_t() -- return the type of the JSON value (implicit)
18540
18541 @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
18542 since 3.0.0
18543 */
18544 const char* type_name() const noexcept
18545 {
18546 {
18547 switch (m_type)
18548 {
18549 case value_t::null:
18550 return "null";
18551 case value_t::object:
18552 return "object";
18553 case value_t::array:
18554 return "array";
18555 case value_t::string:
18556 return "string";
18557 case value_t::boolean:
18558 return "boolean";
18559 case value_t::discarded:
18560 return "discarded";
18561 default:
18562 return "number";
18563 }
18564 }
18565 }
18566
18567
18568 private:
18569 //////////////////////
18570 // member variables //
18571 //////////////////////
18572
18573 /// the type of the current element
18574 value_t m_type = value_t::null;
18575
18576 /// the value of the current element
18577 json_value m_value = {};
18578
18579 //////////////////////////////////////////
18580 // binary serialization/deserialization //
18581 //////////////////////////////////////////
18582
18583 /// @name binary serialization/deserialization support
18584 /// @{
18585
18586 public:
18587 /*!
18588 @brief create a CBOR serialization of a given JSON value
18589
18590 Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
18591 Binary Object Representation) serialization format. CBOR is a binary
18592 serialization format which aims to be more compact than JSON itself, yet
18593 more efficient to parse.
18594
18595 The library uses the following mapping from JSON values types to
18596 CBOR types according to the CBOR specification (RFC 7049):
18597
18598 JSON value type | value/range | CBOR type | first byte
18599 --------------- | ------------------------------------------ | ---------------------------------- | ---------------
18600 null | `null` | Null | 0xF6
18601 boolean | `true` | True | 0xF5
18602 boolean | `false` | False | 0xF4
18603 number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B
18604 number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A
18605 number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39
18606 number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38
18607 number_integer | -24..-1 | Negative integer | 0x20..0x37
18608 number_integer | 0..23 | Integer | 0x00..0x17
18609 number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18
18610 number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
18611 number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
18612 number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
18613 number_unsigned | 0..23 | Integer | 0x00..0x17
18614 number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18
18615 number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
18616 number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
18617 number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
18618 number_float | *any value* | Double-Precision Float | 0xFB
18619 string | *length*: 0..23 | UTF-8 string | 0x60..0x77
18620 string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78
18621 string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79
18622 string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A
18623 string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B
18624 array | *size*: 0..23 | array | 0x80..0x97
18625 array | *size*: 23..255 | array (1 byte follow) | 0x98
18626 array | *size*: 256..65535 | array (2 bytes follow) | 0x99
18627 array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A
18628 array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B
18629 object | *size*: 0..23 | map | 0xA0..0xB7
18630 object | *size*: 23..255 | map (1 byte follow) | 0xB8
18631 object | *size*: 256..65535 | map (2 bytes follow) | 0xB9
18632 object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA
18633 object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB
18634
18635 @note The mapping is **complete** in the sense that any JSON value type
18636 can be converted to a CBOR value.
18637
18638 @note If NaN or Infinity are stored inside a JSON number, they are
18639 serialized properly. This behavior differs from the @ref dump()
18640 function which serializes NaN or Infinity to `null`.
18641
18642 @note The following CBOR types are not used in the conversion:
18643 - byte strings (0x40..0x5F)
18644 - UTF-8 strings terminated by "break" (0x7F)
18645 - arrays terminated by "break" (0x9F)
18646 - maps terminated by "break" (0xBF)
18647 - date/time (0xC0..0xC1)
18648 - bignum (0xC2..0xC3)
18649 - decimal fraction (0xC4)
18650 - bigfloat (0xC5)
18651 - tagged items (0xC6..0xD4, 0xD8..0xDB)
18652 - expected conversions (0xD5..0xD7)
18653 - simple values (0xE0..0xF3, 0xF8)
18654 - undefined (0xF7)
18655 - half and single-precision floats (0xF9-0xFA)
18656 - break (0xFF)
18657
18658 @param[in] j JSON value to serialize
18659 @return MessagePack serialization as byte vector
18660
18661 @complexity Linear in the size of the JSON value @a j.
18662
18663 @liveexample{The example shows the serialization of a JSON value to a byte
18664 vector in CBOR format.,to_cbor}
18665
18666 @sa http://cbor.io
18667 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
18668 analogous deserialization
18669 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
18670 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
18671 related UBJSON format
18672
18673 @since version 2.0.9
18674 */
18675 static std::vector<uint8_t> to_cbor(const basic_json& j)
18676 {
18677 std::vector<uint8_t> result;
18678 to_cbor(j, result);
18679 return result;
18680 }
18681
18682 static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
18683 {
18684 binary_writer<uint8_t>(o).write_cbor(j);
18685 }
18686
18687 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
18688 {
18689 binary_writer<char>(o).write_cbor(j);
18690 }
18691
18692 /*!
18693 @brief create a MessagePack serialization of a given JSON value
18694
18695 Serializes a given JSON value @a j to a byte vector using the MessagePack
18696 serialization format. MessagePack is a binary serialization format which
18697 aims to be more compact than JSON itself, yet more efficient to parse.
18698
18699 The library uses the following mapping from JSON values types to
18700 MessagePack types according to the MessagePack specification:
18701
18702 JSON value type | value/range | MessagePack type | first byte
18703 --------------- | --------------------------------- | ---------------- | ----------
18704 null | `null` | nil | 0xC0
18705 boolean | `true` | true | 0xC3
18706 boolean | `false` | false | 0xC2
18707 number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3
18708 number_integer | -2147483648..-32769 | int32 | 0xD2
18709 number_integer | -32768..-129 | int16 | 0xD1
18710 number_integer | -128..-33 | int8 | 0xD0
18711 number_integer | -32..-1 | negative fixint | 0xE0..0xFF
18712 number_integer | 0..127 | positive fixint | 0x00..0x7F
18713 number_integer | 128..255 | uint 8 | 0xCC
18714 number_integer | 256..65535 | uint 16 | 0xCD
18715 number_integer | 65536..4294967295 | uint 32 | 0xCE
18716 number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF
18717 number_unsigned | 0..127 | positive fixint | 0x00..0x7F
18718 number_unsigned | 128..255 | uint 8 | 0xCC
18719 number_unsigned | 256..65535 | uint 16 | 0xCD
18720 number_unsigned | 65536..4294967295 | uint 32 | 0xCE
18721 number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF
18722 number_float | *any value* | float 64 | 0xCB
18723 string | *length*: 0..31 | fixstr | 0xA0..0xBF
18724 string | *length*: 32..255 | str 8 | 0xD9
18725 string | *length*: 256..65535 | str 16 | 0xDA
18726 string | *length*: 65536..4294967295 | str 32 | 0xDB
18727 array | *size*: 0..15 | fixarray | 0x90..0x9F
18728 array | *size*: 16..65535 | array 16 | 0xDC
18729 array | *size*: 65536..4294967295 | array 32 | 0xDD
18730 object | *size*: 0..15 | fix map | 0x80..0x8F
18731 object | *size*: 16..65535 | map 16 | 0xDE
18732 object | *size*: 65536..4294967295 | map 32 | 0xDF
18733
18734 @note The mapping is **complete** in the sense that any JSON value type
18735 can be converted to a MessagePack value.
18736
18737 @note The following values can **not** be converted to a MessagePack value:
18738 - strings with more than 4294967295 bytes
18739 - arrays with more than 4294967295 elements
18740 - objects with more than 4294967295 elements
18741
18742 @note The following MessagePack types are not used in the conversion:
18743 - bin 8 - bin 32 (0xC4..0xC6)
18744 - ext 8 - ext 32 (0xC7..0xC9)
18745 - float 32 (0xCA)
18746 - fixext 1 - fixext 16 (0xD4..0xD8)
18747
18748 @note Any MessagePack output created @ref to_msgpack can be successfully
18749 parsed by @ref from_msgpack.
18750
18751 @note If NaN or Infinity are stored inside a JSON number, they are
18752 serialized properly. This behavior differs from the @ref dump()
18753 function which serializes NaN or Infinity to `null`.
18754
18755 @param[in] j JSON value to serialize
18756 @return MessagePack serialization as byte vector
18757
18758 @complexity Linear in the size of the JSON value @a j.
18759
18760 @liveexample{The example shows the serialization of a JSON value to a byte
18761 vector in MessagePack format.,to_msgpack}
18762
18763 @sa http://msgpack.org
18764 @sa @ref from_msgpack for the analogous deserialization
18765 @sa @ref to_cbor(const basic_json& for the related CBOR format
18766 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
18767 related UBJSON format
18768
18769 @since version 2.0.9
18770 */
18771 static std::vector<uint8_t> to_msgpack(const basic_json& j)
18772 {
18773 std::vector<uint8_t> result;
18774 to_msgpack(j, result);
18775 return result;
18776 }
18777
18778 static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
18779 {
18780 binary_writer<uint8_t>(o).write_msgpack(j);
18781 }
18782
18783 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
18784 {
18785 binary_writer<char>(o).write_msgpack(j);
18786 }
18787
18788 /*!
18789 @brief create a UBJSON serialization of a given JSON value
18790
18791 Serializes a given JSON value @a j to a byte vector using the UBJSON
18792 (Universal Binary JSON) serialization format. UBJSON aims to be more compact
18793 than JSON itself, yet more efficient to parse.
18794
18795 The library uses the following mapping from JSON values types to
18796 UBJSON types according to the UBJSON specification:
18797
18798 JSON value type | value/range | UBJSON type | marker
18799 --------------- | --------------------------------- | ----------- | ------
18800 null | `null` | null | `Z`
18801 boolean | `true` | true | `T`
18802 boolean | `false` | false | `F`
18803 number_integer | -9223372036854775808..-2147483649 | int64 | `L`
18804 number_integer | -2147483648..-32769 | int32 | `l`
18805 number_integer | -32768..-129 | int16 | `I`
18806 number_integer | -128..127 | int8 | `i`
18807 number_integer | 128..255 | uint8 | `U`
18808 number_integer | 256..32767 | int16 | `I`
18809 number_integer | 32768..2147483647 | int32 | `l`
18810 number_integer | 2147483648..9223372036854775807 | int64 | `L`
18811 number_unsigned | 0..127 | int8 | `i`
18812 number_unsigned | 128..255 | uint8 | `U`
18813 number_unsigned | 256..32767 | int16 | `I`
18814 number_unsigned | 32768..2147483647 | int32 | `l`
18815 number_unsigned | 2147483648..9223372036854775807 | int64 | `L`
18816 number_float | *any value* | float64 | `D`
18817 string | *with shortest length indicator* | string | `S`
18818 array | *see notes on optimized format* | array | `[`
18819 object | *see notes on optimized format* | map | `{`
18820
18821 @note The mapping is **complete** in the sense that any JSON value type
18822 can be converted to a UBJSON value.
18823
18824 @note The following values can **not** be converted to a UBJSON value:
18825 - strings with more than 9223372036854775807 bytes (theoretical)
18826 - unsigned integer numbers above 9223372036854775807
18827
18828 @note The following markers are not used in the conversion:
18829 - `Z`: no-op values are not created.
18830 - `C`: single-byte strings are serialized with `S` markers.
18831
18832 @note Any UBJSON output created @ref to_ubjson can be successfully parsed
18833 by @ref from_ubjson.
18834
18835 @note If NaN or Infinity are stored inside a JSON number, they are
18836 serialized properly. This behavior differs from the @ref dump()
18837 function which serializes NaN or Infinity to `null`.
18838
18839 @note The optimized formats for containers are supported: Parameter
18840 @a use_size adds size information to the beginning of a container and
18841 removes the closing marker. Parameter @a use_type further checks
18842 whether all elements of a container have the same type and adds the
18843 type marker to the beginning of the container. The @a use_type
18844 parameter must only be used together with @a use_size = true. Note
18845 that @a use_size = true alone may result in larger representations -
18846 the benefit of this parameter is that the receiving side is
18847 immediately informed on the number of elements of the container.
18848
18849 @param[in] j JSON value to serialize
18850 @param[in] use_size whether to add size annotations to container types
18851 @param[in] use_type whether to add type annotations to container types
18852 (must be combined with @a use_size = true)
18853 @return UBJSON serialization as byte vector
18854
18855 @complexity Linear in the size of the JSON value @a j.
18856
18857 @liveexample{The example shows the serialization of a JSON value to a byte
18858 vector in UBJSON format.,to_ubjson}
18859
18860 @sa http://ubjson.org
18861 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
18862 analogous deserialization
18863 @sa @ref to_cbor(const basic_json& for the related CBOR format
18864 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
18865
18866 @since version 3.1.0
18867 */
18868 static std::vector<uint8_t> to_ubjson(const basic_json& j,
18869 const bool use_size = false,
18870 const bool use_type = false)
18871 {
18872 std::vector<uint8_t> result;
18873 to_ubjson(j, result, use_size, use_type);
18874 return result;
18875 }
18876
18877 static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
18878 const bool use_size = false, const bool use_type = false)
18879 {
18880 binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
18881 }
18882
18883 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
18884 const bool use_size = false, const bool use_type = false)
18885 {
18886 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
18887 }
18888
18889
18890 /*!
18891 @brief Serializes the given JSON object `j` to BSON and returns a vector
18892 containing the corresponding BSON-representation.
18893
18894 BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are
18895 stored as a single entity (a so-called document).
18896
18897 The library uses the following mapping from JSON values types to BSON types:
18898
18899 JSON value type | value/range | BSON type | marker
18900 --------------- | --------------------------------- | ----------- | ------
18901 null | `null` | null | 0x0A
18902 boolean | `true`, `false` | boolean | 0x08
18903 number_integer | -9223372036854775808..-2147483649 | int64 | 0x12
18904 number_integer | -2147483648..2147483647 | int32 | 0x10
18905 number_integer | 2147483648..9223372036854775807 | int64 | 0x12
18906 number_unsigned | 0..2147483647 | int32 | 0x10
18907 number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12
18908 number_unsigned | 9223372036854775808..18446744073709551615| -- | --
18909 number_float | *any value* | double | 0x01
18910 string | *any value* | string | 0x02
18911 array | *any value* | document | 0x04
18912 object | *any value* | document | 0x03
18913
18914 @warning The mapping is **incomplete**, since only JSON-objects (and things
18915 contained therein) can be serialized to BSON.
18916 Also, integers larger than 9223372036854775807 cannot be serialized to BSON,
18917 and the keys may not contain U+0000, since they are serialized a
18918 zero-terminated c-strings.
18919
18920 @throw out_of_range.407 if `j.is_number_unsigned() && j.get<std::uint64_t>() > 9223372036854775807`
18921 @throw out_of_range.409 if a key in `j` contains a NULL (U+0000)
18922 @throw type_error.317 if `!j.is_object()`
18923
18924 @pre The input `j` is required to be an object: `j.is_object() == true`.
18925
18926 @note Any BSON output created via @ref to_bson can be successfully parsed
18927 by @ref from_bson.
18928
18929 @param[in] j JSON value to serialize
18930 @return BSON serialization as byte vector
18931
18932 @complexity Linear in the size of the JSON value @a j.
18933
18934 @liveexample{The example shows the serialization of a JSON value to a byte
18935 vector in BSON format.,to_bson}
18936
18937 @sa http://bsonspec.org/spec.html
18938 @sa @ref from_bson(detail::input_adapter&&, const bool strict) for the
18939 analogous deserialization
18940 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
18941 related UBJSON format
18942 @sa @ref to_cbor(const basic_json&) for the related CBOR format
18943 @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
18944 */
18945 static std::vector<uint8_t> to_bson(const basic_json& j)
18946 {
18947 std::vector<uint8_t> result;
18948 to_bson(j, result);
18949 return result;
18950 }
18951
18952 /*!
18953 @brief Serializes the given JSON object `j` to BSON and forwards the
18954 corresponding BSON-representation to the given output_adapter `o`.
18955 @param j The JSON object to convert to BSON.
18956 @param o The output adapter that receives the binary BSON representation.
18957 @pre The input `j` shall be an object: `j.is_object() == true`
18958 @sa @ref to_bson(const basic_json&)
18959 */
18960 static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)
18961 {
18962 binary_writer<uint8_t>(o).write_bson(j);
18963 }
18964
18965 /*!
18966 @copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>)
18967 */
18968 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
18969 {
18970 binary_writer<char>(o).write_bson(j);
18971 }
18972
18973
18974 /*!
18975 @brief create a JSON value from an input in CBOR format
18976
18977 Deserializes a given input @a i to a JSON value using the CBOR (Concise
18978 Binary Object Representation) serialization format.
18979
18980 The library maps CBOR types to JSON value types as follows:
18981
18982 CBOR type | JSON value type | first byte
18983 ---------------------- | --------------- | ----------
18984 Integer | number_unsigned | 0x00..0x17
18985 Unsigned integer | number_unsigned | 0x18
18986 Unsigned integer | number_unsigned | 0x19
18987 Unsigned integer | number_unsigned | 0x1A
18988 Unsigned integer | number_unsigned | 0x1B
18989 Negative integer | number_integer | 0x20..0x37
18990 Negative integer | number_integer | 0x38
18991 Negative integer | number_integer | 0x39
18992 Negative integer | number_integer | 0x3A
18993 Negative integer | number_integer | 0x3B
18994 Negative integer | number_integer | 0x40..0x57
18995 UTF-8 string | string | 0x60..0x77
18996 UTF-8 string | string | 0x78
18997 UTF-8 string | string | 0x79
18998 UTF-8 string | string | 0x7A
18999 UTF-8 string | string | 0x7B
19000 UTF-8 string | string | 0x7F
19001 array | array | 0x80..0x97
19002 array | array | 0x98
19003 array | array | 0x99
19004 array | array | 0x9A
19005 array | array | 0x9B
19006 array | array | 0x9F
19007 map | object | 0xA0..0xB7
19008 map | object | 0xB8
19009 map | object | 0xB9
19010 map | object | 0xBA
19011 map | object | 0xBB
19012 map | object | 0xBF
19013 False | `false` | 0xF4
19014 True | `true` | 0xF5
19015 Null | `null` | 0xF6
19016 Half-Precision Float | number_float | 0xF9
19017 Single-Precision Float | number_float | 0xFA
19018 Double-Precision Float | number_float | 0xFB
19019
19020 @warning The mapping is **incomplete** in the sense that not all CBOR
19021 types can be converted to a JSON value. The following CBOR types
19022 are not supported and will yield parse errors (parse_error.112):
19023 - byte strings (0x40..0x5F)
19024 - date/time (0xC0..0xC1)
19025 - bignum (0xC2..0xC3)
19026 - decimal fraction (0xC4)
19027 - bigfloat (0xC5)
19028 - tagged items (0xC6..0xD4, 0xD8..0xDB)
19029 - expected conversions (0xD5..0xD7)
19030 - simple values (0xE0..0xF3, 0xF8)
19031 - undefined (0xF7)
19032
19033 @warning CBOR allows map keys of any type, whereas JSON only allows
19034 strings as keys in object values. Therefore, CBOR maps with keys
19035 other than UTF-8 strings are rejected (parse_error.113).
19036
19037 @note Any CBOR output created @ref to_cbor can be successfully parsed by
19038 @ref from_cbor.
19039
19040 @param[in] i an input in CBOR format convertible to an input adapter
19041 @param[in] strict whether to expect the input to be consumed until EOF
19042 (true by default)
19043 @param[in] allow_exceptions whether to throw exceptions in case of a
19044 parse error (optional, true by default)
19045
19046 @return deserialized JSON value
19047
19048 @throw parse_error.110 if the given input ends prematurely or the end of
19049 file was not reached when @a strict was set to true
19050 @throw parse_error.112 if unsupported features from CBOR were
19051 used in the given input @a v or if the input is not valid CBOR
19052 @throw parse_error.113 if a string was expected as map key, but not found
19053
19054 @complexity Linear in the size of the input @a i.
19055
19056 @liveexample{The example shows the deserialization of a byte vector in CBOR
19057 format to a JSON value.,from_cbor}
19058
19059 @sa http://cbor.io
19060 @sa @ref to_cbor(const basic_json&) for the analogous serialization
19061 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the
19062 related MessagePack format
19063 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
19064 related UBJSON format
19065
19066 @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
19067 consume input adapters, removed start_index parameter, and added
19068 @a strict parameter since 3.0.0; added @a allow_exceptions parameter
19069 since 3.2.0
19070 */
19071 static basic_json from_cbor(detail::input_adapter&& i,
19072 const bool strict = true,
19073 const bool allow_exceptions = true)
19074 {
19075 basic_json result;
19076 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19077 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
19078 return res ? result : basic_json(value_t::discarded);
19079 }
19080
19081 /*!
19082 @copydoc from_cbor(detail::input_adapter&&, const bool, const bool)
19083 */
19084 template<typename A1, typename A2,
19085 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19086 static basic_json from_cbor(A1 && a1, A2 && a2,
19087 const bool strict = true,
19088 const bool allow_exceptions = true)
19089 {
19090 basic_json result;
19091 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19092 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
19093 return res ? result : basic_json(value_t::discarded);
19094 }
19095
19096 /*!
19097 @brief create a JSON value from an input in MessagePack format
19098
19099 Deserializes a given input @a i to a JSON value using the MessagePack
19100 serialization format.
19101
19102 The library maps MessagePack types to JSON value types as follows:
19103
19104 MessagePack type | JSON value type | first byte
19105 ---------------- | --------------- | ----------
19106 positive fixint | number_unsigned | 0x00..0x7F
19107 fixmap | object | 0x80..0x8F
19108 fixarray | array | 0x90..0x9F
19109 fixstr | string | 0xA0..0xBF
19110 nil | `null` | 0xC0
19111 false | `false` | 0xC2
19112 true | `true` | 0xC3
19113 float 32 | number_float | 0xCA
19114 float 64 | number_float | 0xCB
19115 uint 8 | number_unsigned | 0xCC
19116 uint 16 | number_unsigned | 0xCD
19117 uint 32 | number_unsigned | 0xCE
19118 uint 64 | number_unsigned | 0xCF
19119 int 8 | number_integer | 0xD0
19120 int 16 | number_integer | 0xD1
19121 int 32 | number_integer | 0xD2
19122 int 64 | number_integer | 0xD3
19123 str 8 | string | 0xD9
19124 str 16 | string | 0xDA
19125 str 32 | string | 0xDB
19126 array 16 | array | 0xDC
19127 array 32 | array | 0xDD
19128 map 16 | object | 0xDE
19129 map 32 | object | 0xDF
19130 negative fixint | number_integer | 0xE0-0xFF
19131
19132 @warning The mapping is **incomplete** in the sense that not all
19133 MessagePack types can be converted to a JSON value. The following
19134 MessagePack types are not supported and will yield parse errors:
19135 - bin 8 - bin 32 (0xC4..0xC6)
19136 - ext 8 - ext 32 (0xC7..0xC9)
19137 - fixext 1 - fixext 16 (0xD4..0xD8)
19138
19139 @note Any MessagePack output created @ref to_msgpack can be successfully
19140 parsed by @ref from_msgpack.
19141
19142 @param[in] i an input in MessagePack format convertible to an input
19143 adapter
19144 @param[in] strict whether to expect the input to be consumed until EOF
19145 (true by default)
19146 @param[in] allow_exceptions whether to throw exceptions in case of a
19147 parse error (optional, true by default)
19148
19149 @return deserialized JSON value
19150
19151 @throw parse_error.110 if the given input ends prematurely or the end of
19152 file was not reached when @a strict was set to true
19153 @throw parse_error.112 if unsupported features from MessagePack were
19154 used in the given input @a i or if the input is not valid MessagePack
19155 @throw parse_error.113 if a string was expected as map key, but not found
19156
19157 @complexity Linear in the size of the input @a i.
19158
19159 @liveexample{The example shows the deserialization of a byte vector in
19160 MessagePack format to a JSON value.,from_msgpack}
19161
19162 @sa http://msgpack.org
19163 @sa @ref to_msgpack(const basic_json&) for the analogous serialization
19164 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
19165 related CBOR format
19166 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for
19167 the related UBJSON format
19168 @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
19169 the related BSON format
19170
19171 @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
19172 consume input adapters, removed start_index parameter, and added
19173 @a strict parameter since 3.0.0; added @a allow_exceptions parameter
19174 since 3.2.0
19175 */
19176 static basic_json from_msgpack(detail::input_adapter&& i,
19177 const bool strict = true,
19178 const bool allow_exceptions = true)
19179 {
19180 basic_json result;
19181 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19182 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
19183 return res ? result : basic_json(value_t::discarded);
19184 }
19185
19186 /*!
19187 @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool)
19188 */
19189 template<typename A1, typename A2,
19190 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19191 static basic_json from_msgpack(A1 && a1, A2 && a2,
19192 const bool strict = true,
19193 const bool allow_exceptions = true)
19194 {
19195 basic_json result;
19196 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19197 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
19198 return res ? result : basic_json(value_t::discarded);
19199 }
19200
19201 /*!
19202 @brief create a JSON value from an input in UBJSON format
19203
19204 Deserializes a given input @a i to a JSON value using the UBJSON (Universal
19205 Binary JSON) serialization format.
19206
19207 The library maps UBJSON types to JSON value types as follows:
19208
19209 UBJSON type | JSON value type | marker
19210 ----------- | --------------------------------------- | ------
19211 no-op | *no value, next value is read* | `N`
19212 null | `null` | `Z`
19213 false | `false` | `F`
19214 true | `true` | `T`
19215 float32 | number_float | `d`
19216 float64 | number_float | `D`
19217 uint8 | number_unsigned | `U`
19218 int8 | number_integer | `i`
19219 int16 | number_integer | `I`
19220 int32 | number_integer | `l`
19221 int64 | number_integer | `L`
19222 string | string | `S`
19223 char | string | `C`
19224 array | array (optimized values are supported) | `[`
19225 object | object (optimized values are supported) | `{`
19226
19227 @note The mapping is **complete** in the sense that any UBJSON value can
19228 be converted to a JSON value.
19229
19230 @param[in] i an input in UBJSON format convertible to an input adapter
19231 @param[in] strict whether to expect the input to be consumed until EOF
19232 (true by default)
19233 @param[in] allow_exceptions whether to throw exceptions in case of a
19234 parse error (optional, true by default)
19235
19236 @return deserialized JSON value
19237
19238 @throw parse_error.110 if the given input ends prematurely or the end of
19239 file was not reached when @a strict was set to true
19240 @throw parse_error.112 if a parse error occurs
19241 @throw parse_error.113 if a string could not be parsed successfully
19242
19243 @complexity Linear in the size of the input @a i.
19244
19245 @liveexample{The example shows the deserialization of a byte vector in
19246 UBJSON format to a JSON value.,from_ubjson}
19247
19248 @sa http://ubjson.org
19249 @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
19250 analogous serialization
19251 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
19252 related CBOR format
19253 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
19254 the related MessagePack format
19255 @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
19256 the related BSON format
19257
19258 @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0
19259 */
19260 static basic_json from_ubjson(detail::input_adapter&& i,
19261 const bool strict = true,
19262 const bool allow_exceptions = true)
19263 {
19264 basic_json result;
19265 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19266 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
19267 return res ? result : basic_json(value_t::discarded);
19268 }
19269
19270 /*!
19271 @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool)
19272 */
19273 template<typename A1, typename A2,
19274 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19275 static basic_json from_ubjson(A1 && a1, A2 && a2,
19276 const bool strict = true,
19277 const bool allow_exceptions = true)
19278 {
19279 basic_json result;
19280 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19281 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
19282 return res ? result : basic_json(value_t::discarded);
19283 }
19284
19285 /*!
19286 @brief Create a JSON value from an input in BSON format
19287
19288 Deserializes a given input @a i to a JSON value using the BSON (Binary JSON)
19289 serialization format.
19290
19291 The library maps BSON record types to JSON value types as follows:
19292
19293 BSON type | BSON marker byte | JSON value type
19294 --------------- | ---------------- | ---------------------------
19295 double | 0x01 | number_float
19296 string | 0x02 | string
19297 document | 0x03 | object
19298 array | 0x04 | array
19299 binary | 0x05 | still unsupported
19300 undefined | 0x06 | still unsupported
19301 ObjectId | 0x07 | still unsupported
19302 boolean | 0x08 | boolean
19303 UTC Date-Time | 0x09 | still unsupported
19304 null | 0x0A | null
19305 Regular Expr. | 0x0B | still unsupported
19306 DB Pointer | 0x0C | still unsupported
19307 JavaScript Code | 0x0D | still unsupported
19308 Symbol | 0x0E | still unsupported
19309 JavaScript Code | 0x0F | still unsupported
19310 int32 | 0x10 | number_integer
19311 Timestamp | 0x11 | still unsupported
19312 128-bit decimal float | 0x13 | still unsupported
19313 Max Key | 0x7F | still unsupported
19314 Min Key | 0xFF | still unsupported
19315
19316 @warning The mapping is **incomplete**. The unsupported mappings
19317 are indicated in the table above.
19318
19319 @param[in] i an input in BSON format convertible to an input adapter
19320 @param[in] strict whether to expect the input to be consumed until EOF
19321 (true by default)
19322 @param[in] allow_exceptions whether to throw exceptions in case of a
19323 parse error (optional, true by default)
19324
19325 @return deserialized JSON value
19326
19327 @throw parse_error.114 if an unsupported BSON record type is encountered
19328
19329 @complexity Linear in the size of the input @a i.
19330
19331 @liveexample{The example shows the deserialization of a byte vector in
19332 BSON format to a JSON value.,from_bson}
19333
19334 @sa http://bsonspec.org/spec.html
19335 @sa @ref to_bson(const basic_json&) for the analogous serialization
19336 @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
19337 related CBOR format
19338 @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
19339 the related MessagePack format
19340 @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
19341 related UBJSON format
19342 */
19343 static basic_json from_bson(detail::input_adapter&& i,
19344 const bool strict = true,
19345 const bool allow_exceptions = true)
19346 {
19347 basic_json result;
19348 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19349 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::bson, &sdp, strict);
19350 return res ? result : basic_json(value_t::discarded);
19351 }
19352
19353 /*!
19354 @copydoc from_bson(detail::input_adapter&&, const bool, const bool)
19355 */
19356 template<typename A1, typename A2,
19357 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19358 static basic_json from_bson(A1 && a1, A2 && a2,
19359 const bool strict = true,
19360 const bool allow_exceptions = true)
19361 {
19362 basic_json result;
19363 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19364 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::bson, &sdp, strict);
19365 return res ? result : basic_json(value_t::discarded);
19366 }
19367
19368
19369
19370 /// @}
19371
19372 //////////////////////////
19373 // JSON Pointer support //
19374 //////////////////////////
19375
19376 /// @name JSON Pointer functions
19377 /// @{
19378
19379 /*!
19380 @brief access specified element via JSON Pointer
19381
19382 Uses a JSON pointer to retrieve a reference to the respective JSON value.
19383 No bound checking is performed. Similar to @ref operator[](const typename
19384 object_t::key_type&), `null` values are created in arrays and objects if
19385 necessary.
19386
19387 In particular:
19388 - If the JSON pointer points to an object key that does not exist, it
19389 is created an filled with a `null` value before a reference to it
19390 is returned.
19391 - If the JSON pointer points to an array index that does not exist, it
19392 is created an filled with a `null` value before a reference to it
19393 is returned. All indices between the current maximum and the given
19394 index are also filled with `null`.
19395 - The special value `-` is treated as a synonym for the index past the
19396 end.
19397
19398 @param[in] ptr a JSON pointer
19399
19400 @return reference to the element pointed to by @a ptr
19401
19402 @complexity Constant.
19403
19404 @throw parse_error.106 if an array index begins with '0'
19405 @throw parse_error.109 if an array index was not a number
19406 @throw out_of_range.404 if the JSON pointer can not be resolved
19407
19408 @liveexample{The behavior is shown in the example.,operatorjson_pointer}
19409
19410 @since version 2.0.0
19411 */
19412 reference operator[](const json_pointer& ptr)
19413 {
19414 return ptr.get_unchecked(this);
19415 }
19416
19417 /*!
19418 @brief access specified element via JSON Pointer
19419
19420 Uses a JSON pointer to retrieve a reference to the respective JSON value.
19421 No bound checking is performed. The function does not change the JSON
19422 value; no `null` values are created. In particular, the the special value
19423 `-` yields an exception.
19424
19425 @param[in] ptr JSON pointer to the desired element
19426
19427 @return const reference to the element pointed to by @a ptr
19428
19429 @complexity Constant.
19430
19431 @throw parse_error.106 if an array index begins with '0'
19432 @throw parse_error.109 if an array index was not a number
19433 @throw out_of_range.402 if the array index '-' is used
19434 @throw out_of_range.404 if the JSON pointer can not be resolved
19435
19436 @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
19437
19438 @since version 2.0.0
19439 */
19440 const_reference operator[](const json_pointer& ptr) const
19441 {
19442 return ptr.get_unchecked(this);
19443 }
19444
19445 /*!
19446 @brief access specified element via JSON Pointer
19447
19448 Returns a reference to the element at with specified JSON pointer @a ptr,
19449 with bounds checking.
19450
19451 @param[in] ptr JSON pointer to the desired element
19452
19453 @return reference to the element pointed to by @a ptr
19454
19455 @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
19456 begins with '0'. See example below.
19457
19458 @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
19459 is not a number. See example below.
19460
19461 @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
19462 is out of range. See example below.
19463
19464 @throw out_of_range.402 if the array index '-' is used in the passed JSON
19465 pointer @a ptr. As `at` provides checked access (and no elements are
19466 implicitly inserted), the index '-' is always invalid. See example below.
19467
19468 @throw out_of_range.403 if the JSON pointer describes a key of an object
19469 which cannot be found. See example below.
19470
19471 @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
19472 See example below.
19473
19474 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
19475 changes in the JSON value.
19476
19477 @complexity Constant.
19478
19479 @since version 2.0.0
19480
19481 @liveexample{The behavior is shown in the example.,at_json_pointer}
19482 */
19483 reference at(const json_pointer& ptr)
19484 {
19485 return ptr.get_checked(this);
19486 }
19487
19488 /*!
19489 @brief access specified element via JSON Pointer
19490
19491 Returns a const reference to the element at with specified JSON pointer @a
19492 ptr, with bounds checking.
19493
19494 @param[in] ptr JSON pointer to the desired element
19495
19496 @return reference to the element pointed to by @a ptr
19497
19498 @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
19499 begins with '0'. See example below.
19500
19501 @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
19502 is not a number. See example below.
19503
19504 @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
19505 is out of range. See example below.
19506
19507 @throw out_of_range.402 if the array index '-' is used in the passed JSON
19508 pointer @a ptr. As `at` provides checked access (and no elements are
19509 implicitly inserted), the index '-' is always invalid. See example below.
19510
19511 @throw out_of_range.403 if the JSON pointer describes a key of an object
19512 which cannot be found. See example below.
19513
19514 @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
19515 See example below.
19516
19517 @exceptionsafety Strong guarantee: if an exception is thrown, there are no
19518 changes in the JSON value.
19519
19520 @complexity Constant.
19521
19522 @since version 2.0.0
19523
19524 @liveexample{The behavior is shown in the example.,at_json_pointer_const}
19525 */
19526 const_reference at(const json_pointer& ptr) const
19527 {
19528 return ptr.get_checked(this);
19529 }
19530
19531 /*!
19532 @brief return flattened JSON value
19533
19534 The function creates a JSON object whose keys are JSON pointers (see [RFC
19535 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all
19536 primitive. The original JSON value can be restored using the @ref
19537 unflatten() function.
19538
19539 @return an object that maps JSON pointers to primitive values
19540
19541 @note Empty objects and arrays are flattened to `null` and will not be
19542 reconstructed correctly by the @ref unflatten() function.
19543
19544 @complexity Linear in the size the JSON value.
19545
19546 @liveexample{The following code shows how a JSON object is flattened to an
19547 object whose keys consist of JSON pointers.,flatten}
19548
19549 @sa @ref unflatten() for the reverse function
19550
19551 @since version 2.0.0
19552 */
19553 basic_json flatten() const
19554 {
19555 basic_json result(value_t::object);
19556 json_pointer::flatten("", *this, result);
19557 return result;
19558 }
19559
19560 /*!
19561 @brief unflatten a previously flattened JSON value
19562
19563 The function restores the arbitrary nesting of a JSON value that has been
19564 flattened before using the @ref flatten() function. The JSON value must
19565 meet certain constraints:
19566 1. The value must be an object.
19567 2. The keys must be JSON pointers (see
19568 [RFC 6901](https://tools.ietf.org/html/rfc6901))
19569 3. The mapped values must be primitive JSON types.
19570
19571 @return the original JSON from a flattened version
19572
19573 @note Empty objects and arrays are flattened by @ref flatten() to `null`
19574 values and can not unflattened to their original type. Apart from
19575 this example, for a JSON value `j`, the following is always true:
19576 `j == j.flatten().unflatten()`.
19577
19578 @complexity Linear in the size the JSON value.
19579
19580 @throw type_error.314 if value is not an object
19581 @throw type_error.315 if object values are not primitive
19582
19583 @liveexample{The following code shows how a flattened JSON object is
19584 unflattened into the original nested JSON object.,unflatten}
19585
19586 @sa @ref flatten() for the reverse function
19587
19588 @since version 2.0.0
19589 */
19590 basic_json unflatten() const
19591 {
19592 return json_pointer::unflatten(*this);
19593 }
19594
19595 /// @}
19596
19597 //////////////////////////
19598 // JSON Patch functions //
19599 //////////////////////////
19600
19601 /// @name JSON Patch functions
19602 /// @{
19603
19604 /*!
19605 @brief applies a JSON patch
19606
19607 [JSON Patch](http://jsonpatch.com) defines a JSON document structure for
19608 expressing a sequence of operations to apply to a JSON) document. With
19609 this function, a JSON Patch is applied to the current JSON value by
19610 executing all operations from the patch.
19611
19612 @param[in] json_patch JSON patch document
19613 @return patched document
19614
19615 @note The application of a patch is atomic: Either all operations succeed
19616 and the patched document is returned or an exception is thrown. In
19617 any case, the original value is not changed: the patch is applied
19618 to a copy of the value.
19619
19620 @throw parse_error.104 if the JSON patch does not consist of an array of
19621 objects
19622
19623 @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
19624 attributes are missing); example: `"operation add must have member path"`
19625
19626 @throw out_of_range.401 if an array index is out of range.
19627
19628 @throw out_of_range.403 if a JSON pointer inside the patch could not be
19629 resolved successfully in the current JSON value; example: `"key baz not
19630 found"`
19631
19632 @throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
19633 "move")
19634
19635 @throw other_error.501 if "test" operation was unsuccessful
19636
19637 @complexity Linear in the size of the JSON value and the length of the
19638 JSON patch. As usually only a fraction of the JSON value is affected by
19639 the patch, the complexity can usually be neglected.
19640
19641 @liveexample{The following code shows how a JSON patch is applied to a
19642 value.,patch}
19643
19644 @sa @ref diff -- create a JSON patch by comparing two JSON values
19645
19646 @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
19647 @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
19648
19649 @since version 2.0.0
19650 */
19651 basic_json patch(const basic_json& json_patch) const
19652 {
19653 // make a working copy to apply the patch to
19654 basic_json result = *this;
19655
19656 // the valid JSON Patch operations
19657 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
19658
19659 const auto get_op = [](const std::string & op)
19660 {
19661 if (op == "add")
19662 {
19663 return patch_operations::add;
19664 }
19665 if (op == "remove")
19666 {
19667 return patch_operations::remove;
19668 }
19669 if (op == "replace")
19670 {
19671 return patch_operations::replace;
19672 }
19673 if (op == "move")
19674 {
19675 return patch_operations::move;
19676 }
19677 if (op == "copy")
19678 {
19679 return patch_operations::copy;
19680 }
19681 if (op == "test")
19682 {
19683 return patch_operations::test;
19684 }
19685
19686 return patch_operations::invalid;
19687 };
19688
19689 // wrapper for "add" operation; add value at ptr
19690 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
19691 {
19692 // adding to the root of the target document means replacing it
19693 if (ptr.is_root())
19694 {
19695 result = val;
19696 }
19697 else
19698 {
19699 // make sure the top element of the pointer exists
19700 json_pointer top_pointer = ptr.top();
19701 if (top_pointer != ptr)
19702 {
19703 result.at(top_pointer);
19704 }
19705
19706 // get reference to parent of JSON pointer ptr
19707 const auto last_path = ptr.pop_back();
19708 basic_json& parent = result[ptr];
19709
19710 switch (parent.m_type)
19711 {
19712 case value_t::null:
19713 case value_t::object:
19714 {
19715 // use operator[] to add value
19716 parent[last_path] = val;
19717 break;
19718 }
19719
19720 case value_t::array:
19721 {
19722 if (last_path == "-")
19723 {
19724 // special case: append to back
19725 parent.push_back(val);
19726 }
19727 else
19728 {
19729 const auto idx = json_pointer::array_index(last_path);
19730 if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
19731 {
19732 // avoid undefined behavior
19733 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
19734 }
19735
19736 // default case: insert add offset
19737 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
19738 }
19739 break;
19740 }
19741
19742 // LCOV_EXCL_START
19743 default:
19744 {
19745 // if there exists a parent it cannot be primitive
19746 assert(false);
19747 }
19748 // LCOV_EXCL_STOP
19749 }
19750 }
19751 };
19752
19753 // wrapper for "remove" operation; remove value at ptr
19754 const auto operation_remove = [&result](json_pointer & ptr)
19755 {
19756 // get reference to parent of JSON pointer ptr
19757 const auto last_path = ptr.pop_back();
19758 basic_json& parent = result.at(ptr);
19759
19760 // remove child
19761 if (parent.is_object())
19762 {
19763 // perform range check
19764 auto it = parent.find(last_path);
19765 if (JSON_LIKELY(it != parent.end()))
19766 {
19767 parent.erase(it);
19768 }
19769 else
19770 {
19771 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
19772 }
19773 }
19774 else if (parent.is_array())
19775 {
19776 // note erase performs range check
19777 parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
19778 }
19779 };
19780
19781 // type check: top level value must be an array
19782 if (JSON_UNLIKELY(not json_patch.is_array()))
19783 {
19784 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
19785 }
19786
19787 // iterate and apply the operations
19788 for (const auto& val : json_patch)
19789 {
19790 // wrapper to get a value for an operation
19791 const auto get_value = [&val](const std::string & op,
19792 const std::string & member,
19793 bool string_type) -> basic_json &
19794 {
19795 // find value
19796 auto it = val.m_value.object->find(member);
19797
19798 // context-sensitive error message
19799 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
19800
19801 // check if desired value is present
19802 if (JSON_UNLIKELY(it == val.m_value.object->end()))
19803 {
19804 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
19805 }
19806
19807 // check if result is of type string
19808 if (JSON_UNLIKELY(string_type and not it->second.is_string()))
19809 {
19810 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
19811 }
19812
19813 // no error: return value
19814 return it->second;
19815 };
19816
19817 // type check: every element of the array must be an object
19818 if (JSON_UNLIKELY(not val.is_object()))
19819 {
19820 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
19821 }
19822
19823 // collect mandatory members
19824 const std::string op = get_value("op", "op", true);
19825 const std::string path = get_value(op, "path", true);
19826 json_pointer ptr(path);
19827
19828 switch (get_op(op))
19829 {
19830 case patch_operations::add:
19831 {
19832 operation_add(ptr, get_value("add", "value", false));
19833 break;
19834 }
19835
19836 case patch_operations::remove:
19837 {
19838 operation_remove(ptr);
19839 break;
19840 }
19841
19842 case patch_operations::replace:
19843 {
19844 // the "path" location must exist - use at()
19845 result.at(ptr) = get_value("replace", "value", false);
19846 break;
19847 }
19848
19849 case patch_operations::move:
19850 {
19851 const std::string from_path = get_value("move", "from", true);
19852 json_pointer from_ptr(from_path);
19853
19854 // the "from" location must exist - use at()
19855 basic_json v = result.at(from_ptr);
19856
19857 // The move operation is functionally identical to a
19858 // "remove" operation on the "from" location, followed
19859 // immediately by an "add" operation at the target
19860 // location with the value that was just removed.
19861 operation_remove(from_ptr);
19862 operation_add(ptr, v);
19863 break;
19864 }
19865
19866 case patch_operations::copy:
19867 {
19868 const std::string from_path = get_value("copy", "from", true);
19869 const json_pointer from_ptr(from_path);
19870
19871 // the "from" location must exist - use at()
19872 basic_json v = result.at(from_ptr);
19873
19874 // The copy is functionally identical to an "add"
19875 // operation at the target location using the value
19876 // specified in the "from" member.
19877 operation_add(ptr, v);
19878 break;
19879 }
19880
19881 case patch_operations::test:
19882 {
19883 bool success = false;
19884 JSON_TRY
19885 {
19886 // check if "value" matches the one at "path"
19887 // the "path" location must exist - use at()
19888 success = (result.at(ptr) == get_value("test", "value", false));
19889 }
19890 JSON_INTERNAL_CATCH (out_of_range&)
19891 {
19892 // ignore out of range errors: success remains false
19893 }
19894
19895 // throw an exception if test fails
19896 if (JSON_UNLIKELY(not success))
19897 {
19898 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
19899 }
19900
19901 break;
19902 }
19903
19904 case patch_operations::invalid:
19905 {
19906 // op must be "add", "remove", "replace", "move", "copy", or
19907 // "test"
19908 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
19909 }
19910 }
19911 }
19912
19913 return result;
19914 }
19915
19916 /*!
19917 @brief creates a diff as a JSON patch
19918
19919 Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can
19920 be changed into the value @a target by calling @ref patch function.
19921
19922 @invariant For two JSON values @a source and @a target, the following code
19923 yields always `true`:
19924 @code {.cpp}
19925 source.patch(diff(source, target)) == target;
19926 @endcode
19927
19928 @note Currently, only `remove`, `add`, and `replace` operations are
19929 generated.
19930
19931 @param[in] source JSON value to compare from
19932 @param[in] target JSON value to compare against
19933 @param[in] path helper value to create JSON pointers
19934
19935 @return a JSON patch to convert the @a source to @a target
19936
19937 @complexity Linear in the lengths of @a source and @a target.
19938
19939 @liveexample{The following code shows how a JSON patch is created as a
19940 diff for two JSON values.,diff}
19941
19942 @sa @ref patch -- apply a JSON patch
19943 @sa @ref merge_patch -- apply a JSON Merge Patch
19944
19945 @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
19946
19947 @since version 2.0.0
19948 */
19949 static basic_json diff(const basic_json& source, const basic_json& target,
19950 const std::string& path = "")
19951 {
19952 // the patch
19953 basic_json result(value_t::array);
19954
19955 // if the values are the same, return empty patch
19956 if (source == target)
19957 {
19958 return result;
19959 }
19960
19961 if (source.type() != target.type())
19962 {
19963 // different types: replace value
19964 result.push_back(
19965 {
19966 {"op", "replace"}, {"path", path}, {"value", target}
19967 });
19968 }
19969 else
19970 {
19971 switch (source.type())
19972 {
19973 case value_t::array:
19974 {
19975 // first pass: traverse common elements
19976 std::size_t i = 0;
19977 while (i < source.size() and i < target.size())
19978 {
19979 // recursive call to compare array values at index i
19980 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
19981 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
19982 ++i;
19983 }
19984
19985 // i now reached the end of at least one array
19986 // in a second pass, traverse the remaining elements
19987
19988 // remove my remaining elements
19989 const auto end_index = static_cast<difference_type>(result.size());
19990 while (i < source.size())
19991 {
19992 // add operations in reverse order to avoid invalid
19993 // indices
19994 result.insert(result.begin() + end_index, object(
19995 {
19996 {"op", "remove"},
19997 {"path", path + "/" + std::to_string(i)}
19998 }));
19999 ++i;
20000 }
20001
20002 // add other remaining elements
20003 while (i < target.size())
20004 {
20005 result.push_back(
20006 {
20007 {"op", "add"},
20008 {"path", path + "/" + std::to_string(i)},
20009 {"value", target[i]}
20010 });
20011 ++i;
20012 }
20013
20014 break;
20015 }
20016
20017 case value_t::object:
20018 {
20019 // first pass: traverse this object's elements
20020 for (auto it = source.cbegin(); it != source.cend(); ++it)
20021 {
20022 // escape the key name to be used in a JSON patch
20023 const auto key = json_pointer::escape(it.key());
20024
20025 if (target.find(it.key()) != target.end())
20026 {
20027 // recursive call to compare object values at key it
20028 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
20029 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
20030 }
20031 else
20032 {
20033 // found a key that is not in o -> remove it
20034 result.push_back(object(
20035 {
20036 {"op", "remove"}, {"path", path + "/" + key}
20037 }));
20038 }
20039 }
20040
20041 // second pass: traverse other object's elements
20042 for (auto it = target.cbegin(); it != target.cend(); ++it)
20043 {
20044 if (source.find(it.key()) == source.end())
20045 {
20046 // found a key that is not in this -> add it
20047 const auto key = json_pointer::escape(it.key());
20048 result.push_back(
20049 {
20050 {"op", "add"}, {"path", path + "/" + key},
20051 {"value", it.value()}
20052 });
20053 }
20054 }
20055
20056 break;
20057 }
20058
20059 default:
20060 {
20061 // both primitive type: replace value
20062 result.push_back(
20063 {
20064 {"op", "replace"}, {"path", path}, {"value", target}
20065 });
20066 break;
20067 }
20068 }
20069 }
20070
20071 return result;
20072 }
20073
20074 /// @}
20075
20076 ////////////////////////////////
20077 // JSON Merge Patch functions //
20078 ////////////////////////////////
20079
20080 /// @name JSON Merge Patch functions
20081 /// @{
20082
20083 /*!
20084 @brief applies a JSON Merge Patch
20085
20086 The merge patch format is primarily intended for use with the HTTP PATCH
20087 method as a means of describing a set of modifications to a target
20088 resource's content. This function applies a merge patch to the current
20089 JSON value.
20090
20091 The function implements the following algorithm from Section 2 of
20092 [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):
20093
20094 ```
20095 define MergePatch(Target, Patch):
20096 if Patch is an Object:
20097 if Target is not an Object:
20098 Target = {} // Ignore the contents and set it to an empty Object
20099 for each Name/Value pair in Patch:
20100 if Value is null:
20101 if Name exists in Target:
20102 remove the Name/Value pair from Target
20103 else:
20104 Target[Name] = MergePatch(Target[Name], Value)
20105 return Target
20106 else:
20107 return Patch
20108 ```
20109
20110 Thereby, `Target` is the current object; that is, the patch is applied to
20111 the current value.
20112
20113 @param[in] patch the patch to apply
20114
20115 @complexity Linear in the lengths of @a patch.
20116
20117 @liveexample{The following code shows how a JSON Merge Patch is applied to
20118 a JSON document.,merge_patch}
20119
20120 @sa @ref patch -- apply a JSON patch
20121 @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
20122
20123 @since version 3.0.0
20124 */
20125 void merge_patch(const basic_json& patch)
20126 {
20127 if (patch.is_object())
20128 {
20129 if (not is_object())
20130 {
20131 *this = object();
20132 }
20133 for (auto it = patch.begin(); it != patch.end(); ++it)
20134 {
20135 if (it.value().is_null())
20136 {
20137 erase(it.key());
20138 }
20139 else
20140 {
20141 operator[](it.key()).merge_patch(it.value());
20142 }
20143 }
20144 }
20145 else
20146 {
20147 *this = patch;
20148 }
20149 }
20150
20151 /// @}
20152};
20153} // namespace nlohmann
20154
20155///////////////////////
20156// nonmember support //
20157///////////////////////
20158
20159// specialization of std::swap, and std::hash
20160namespace std
20161{
20162
20163/// hash value for JSON objects
20164template<>
20165struct hash<nlohmann::json>
20166{
20167 /*!
20168 @brief return a hash value for a JSON object
20169
20170 @since version 1.0.0
20171 */
20172 std::size_t operator()(const nlohmann::json& j) const
20173 {
20174 // a naive hashing via the string representation
20175 const auto& h = hash<nlohmann::json::string_t>();
20176 return h(j.dump());
20177 }
20178};
20179
20180/// specialization for std::less<value_t>
20181/// @note: do not remove the space after '<',
20182/// see https://github.com/nlohmann/json/pull/679
20183template<>
20184struct less< ::nlohmann::detail::value_t>
20185{
20186 /*!
20187 @brief compare two value_t enum values
20188 @since version 3.0.0
20189 */
20190 bool operator()(nlohmann::detail::value_t lhs,
20191 nlohmann::detail::value_t rhs) const noexcept
20192 {
20193 return nlohmann::detail::operator<(lhs, rhs);
20194 }
20195};
20196
20197/*!
20198@brief exchanges the values of two JSON objects
20199
20200@since version 1.0.0
20201*/
20202template<>
20203inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
20204 is_nothrow_move_constructible<nlohmann::json>::value and
20205 is_nothrow_move_assignable<nlohmann::json>::value
20206)
20207{
20208 j1.swap(j2);
20209}
20210
20211} // namespace std
20212
20213/*!
20214@brief user-defined string literal for JSON values
20215
20216This operator implements a user-defined string literal for JSON objects. It
20217can be used by adding `"_json"` to a string literal and returns a JSON object
20218if no parse error occurred.
20219
20220@param[in] s a string representation of a JSON object
20221@param[in] n the length of string @a s
20222@return a JSON object
20223
20224@since version 1.0.0
20225*/
20226inline nlohmann::json operator "" _json(const char* s, std::size_t n)
20227{
20228 return nlohmann::json::parse(s, s + n);
20229}
20230
20231/*!
20232@brief user-defined string literal for JSON pointer
20233
20234This operator implements a user-defined string literal for JSON Pointers. It
20235can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
20236object if no parse error occurred.
20237
20238@param[in] s a string representation of a JSON Pointer
20239@param[in] n the length of string @a s
20240@return a JSON pointer object
20241
20242@since version 2.0.0
20243*/
20244inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
20245{
20246 return nlohmann::json::json_pointer(std::string(s, n));
20247}
20248
20249// #include <nlohmann/detail/macro_unscope.hpp>
20250
20251
20252// restore GCC/clang diagnostic settings
20253#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
20254 #pragma GCC diagnostic pop
20255#endif
20256#if defined(__clang__)
20257 #pragma GCC diagnostic pop
20258#endif
20259
20260// clean up
20261#undef JSON_INTERNAL_CATCH
20262#undef JSON_CATCH
20263#undef JSON_THROW
20264#undef JSON_TRY
20265#undef JSON_LIKELY
20266#undef JSON_UNLIKELY
20267#undef JSON_DEPRECATED
20268#undef JSON_HAS_CPP_14
20269#undef JSON_HAS_CPP_17
20270#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
20271#undef NLOHMANN_BASIC_JSON_TPL
20272
20273
20274#endif