Add standalone exe build tooling under scripts/exe
build_exe.py compiles every unit in data/compile.json with the pinned toolchain and links Ragexe.exe. Not part of the decompilation and not in data/compile.json: imports/*.def (original DLL import tables), jsoncons/ (v0.170.2 headers + JsonCppLoader glue), nProtect/GameGuard.cpp (no-op GameGuard stand-in).
This commit is contained in:
parent
9dbafafea9
commit
e11260a408
149 changed files with 80735 additions and 0 deletions
188
scripts/exe/build_exe.py
Normal file
188
scripts/exe/build_exe.py
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
"""Build every unit in data/compile.json and link them into Ragexe.exe (+ .pdb).
|
||||
|
||||
Optional and local: clank checks and merges never run this. It uses only the
|
||||
toolchain `td toolchain install` provides (the root and runner come from
|
||||
.td/config.json), with the exact compiler flags of data/compile.json. Vendor
|
||||
DLL imports (Bink, Granny, Stove, ...) come from scripts/exe/imports/*.def, the
|
||||
exact import table of the original executable, so a declaration that does not
|
||||
match the real DLL export fails at link time.
|
||||
|
||||
python scripts/exe/build_exe.py # compile + link, fail on any error
|
||||
python scripts/exe/build_exe.py --force-multiple # accept duplicate definitions
|
||||
python scripts/exe/build_exe.py --link-only # relink objects from a previous run
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import concurrent.futures
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import Counter
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent.parent
|
||||
EXE_DIR = Path(__file__).resolve().parent
|
||||
MSVC = "VC/Tools/MSVC/14.29.30133"
|
||||
SDK_LIB = "Program Files/Windows Kits/10/Lib/10.0.19041.0"
|
||||
SYSTEM_LIBS = [
|
||||
"kernel32.lib", "user32.lib", "gdi32.lib", "advapi32.lib", "winmm.lib", "ws2_32.lib",
|
||||
"ole32.lib", "oleaut32.lib", "uuid.lib", "shell32.lib", "imm32.lib", "version.lib",
|
||||
"comctl32.lib", "comdlg32.lib", "shlwapi.lib", "wininet.lib", "gdiplus.lib", "bcrypt.lib",
|
||||
"dxguid.lib", "ddraw.lib", "d3d9.lib", "dinput8.lib", "dbghelp.lib", "crypt32.lib",
|
||||
"iphlpapi.lib", "psapi.lib", "wintrust.lib", "winhttp.lib", "netapi32.lib",
|
||||
]
|
||||
|
||||
|
||||
class Toolchain:
|
||||
"""The td toolchain, run the way td runs it (native on Windows, wine elsewhere)."""
|
||||
|
||||
def __init__(self):
|
||||
config = json.loads((ROOT / ".td" / "config.json").read_text(encoding="utf-8"))
|
||||
runner = config["runners"]["ragnarok"]
|
||||
self.kind = runner["type"]
|
||||
if self.kind not in ("native", "wine"):
|
||||
sys.exit(f"runner '{self.kind}' is not supported; use td's native (Windows) or wine runner")
|
||||
self.root = Path(runner["toolchainRoot"])
|
||||
self.bin = self.root / MSVC / "bin" / "Hostx64" / "x86"
|
||||
crt = self.root / MSVC / "lib" / "x86"
|
||||
if not (crt / "msvcrt.lib").exists() or not (self.root / SDK_LIB / "um" / "x86" / "kernel32.Lib").exists():
|
||||
sys.exit(f"{self.root} has no link libraries (msvcrt.lib, kernel32.lib): run 'td toolchain install' to update it")
|
||||
self.env = dict(os.environ)
|
||||
self.env.update(runner.get("env", {}))
|
||||
self.env["LIB"] = ";".join(self.path(p) for p in (
|
||||
crt, self.root / MSVC / "atlmfc" / "lib" / "x86",
|
||||
self.root / SDK_LIB / "ucrt" / "x86", self.root / SDK_LIB / "um" / "x86"))
|
||||
|
||||
def path(self, p):
|
||||
if self.kind == "native":
|
||||
return str(p)
|
||||
return subprocess.run(["winepath", "-w", str(p)], capture_output=True, text=True, check=True).stdout.strip()
|
||||
|
||||
def run(self, tool, args, env=None, cwd=None):
|
||||
exe = str(self.bin / tool)
|
||||
command = [exe, *args] if self.kind == "native" else ["wine", exe, *args]
|
||||
return subprocess.run(command, env=env or self.env, cwd=cwd, capture_output=True, text=True, errors="replace")
|
||||
|
||||
|
||||
def build_import_libs(tc, out_dir):
|
||||
lib_dir = out_dir / "importlibs"
|
||||
lib_dir.mkdir(exist_ok=True)
|
||||
libs = []
|
||||
for definition in sorted((EXE_DIR / "imports").glob("*.def")):
|
||||
lib = lib_dir / (definition.stem + ".lib")
|
||||
result = tc.run("lib.exe", ["/nologo", "/MACHINE:X86", f"/DEF:{tc.path(definition)}", f"/OUT:{tc.path(lib)}"])
|
||||
if result.returncode != 0:
|
||||
sys.exit(f"import library {definition.name} failed:\n{result.stdout}{result.stderr}")
|
||||
libs.append(lib)
|
||||
return libs
|
||||
|
||||
# Units only the standalone exe needs: stand-ins for third-party code the
|
||||
# decompilation does not reproduce. Each is compiled with the flags of the
|
||||
# listed data/compile.json unit plus any extra include directories (relative to
|
||||
# the repository). Clank does not know about these files.
|
||||
EXE_ONLY_UNITS = {
|
||||
"scripts/exe/nProtect/GameGuard.cpp": ("Source/Security/NProtectGameGuardMgr.cpp", []),
|
||||
"scripts/exe/jsoncons/JsonCppLoaderGlue.cpp": ("Source/Utility/JsonCppLoader.cpp", ["scripts/exe/jsoncons/include"]),
|
||||
}
|
||||
|
||||
|
||||
def exe_units(config):
|
||||
"""unit -> (shape index, extra include directories)."""
|
||||
units = {unit: (shape, []) for unit, shape in config["units"].items()}
|
||||
for unit, (flags_of, includes) in EXE_ONLY_UNITS.items():
|
||||
units[unit] = (config["units"][flags_of], includes)
|
||||
return units
|
||||
|
||||
|
||||
def compile_units(tc, config, out_dir, jobs):
|
||||
root = tc.path(ROOT).replace("\\", "/")
|
||||
|
||||
def expand(value):
|
||||
return value.replace("${TC}", tc.path(tc.root)).replace("${SRC}", root)
|
||||
|
||||
env = dict(tc.env)
|
||||
for key, value in config["env"].items():
|
||||
env[key] = expand(value)
|
||||
|
||||
def build(item):
|
||||
unit, (shape, includes) = item
|
||||
obj = out_dir / (unit.replace("/", "_") + ".obj")
|
||||
extra = [f"/I{tc.path(ROOT / directory)}" for directory in includes]
|
||||
args = [*(expand(a) for a in config["shapes"][shape]), *extra, "/Z7", f"/Fo{tc.path(obj)}", tc.path(ROOT / unit)]
|
||||
result = tc.run("cl.exe", args, env=env, cwd=ROOT)
|
||||
return unit, obj, result.returncode, result.stdout + result.stderr
|
||||
|
||||
with concurrent.futures.ThreadPoolExecutor(jobs) as pool:
|
||||
results = list(pool.map(build, exe_units(config).items()))
|
||||
failures = [r for r in results if r[2] != 0]
|
||||
for unit, _, _, output in failures:
|
||||
print(f"== {unit}")
|
||||
print("\n".join(line for line in output.splitlines() if " error " in line or "fatal error" in line))
|
||||
print(f"compiled {len(results) - len(failures)}/{len(results)} units")
|
||||
return [r[1] for r in results if r[2] == 0], len(failures)
|
||||
|
||||
|
||||
def link(tc, objects, out_dir, extra_args):
|
||||
rsp = out_dir / "link.rsp"
|
||||
rsp.write_text("\n".join([*(f'"{tc.path(o)}"' for o in objects), *extra_args]), encoding="utf-8")
|
||||
exe = out_dir / "Ragexe.exe"
|
||||
outputs = (exe, exe.with_suffix(".pdb"))
|
||||
for stale in outputs:
|
||||
stale.unlink(missing_ok=True)
|
||||
args = ["/nologo", "/MACHINE:X86", "/SUBSYSTEM:WINDOWS", "/LARGEADDRESSAWARE",
|
||||
"/DEBUG:FULL", f"/PDB:{tc.path(exe.with_suffix('.pdb'))}", "/INCREMENTAL:NO", "/OPT:REF", "/OPT:ICF",
|
||||
"/ERRORLIMIT:0", f"/OUT:{tc.path(exe)}", f"@{tc.path(rsp)}", *SYSTEM_LIBS]
|
||||
result = tc.run("link.exe", args)
|
||||
if result.returncode != 0:
|
||||
for partial in outputs:
|
||||
partial.unlink(missing_ok=True)
|
||||
return result.returncode, result.stdout + result.stderr, exe
|
||||
|
||||
|
||||
def summarize(log, out_dir):
|
||||
(out_dir / "link.log").write_text(log, encoding="utf-8")
|
||||
duplicates = sorted(set(re.findall(r'(?:error LNK2005|warning LNK4006): "([^"]+)"', log)))
|
||||
unresolved = sorted(set(a or b for a, b in re.findall(r'unresolved external symbol (?:"[^"]+" \((\S+)\)|(\S+))', log)))
|
||||
print(f"link log: {out_dir / 'link.log'}")
|
||||
print(f"duplicate definitions: {len(duplicates)}")
|
||||
for symbol in duplicates:
|
||||
print(f" {symbol}")
|
||||
print(f"unresolved symbols: {len(unresolved)}")
|
||||
codes = Counter(re.findall(r"error (LNK\d+)", log))
|
||||
if codes:
|
||||
print("linker errors: " + ", ".join(f"{code} x{count}" for code, count in codes.most_common()))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument("--out", default=str(ROOT / "build" / "exe"), help="output directory")
|
||||
parser.add_argument("--jobs", type=int, default=os.cpu_count(), help="parallel compiles")
|
||||
parser.add_argument("--force-multiple", action="store_true",
|
||||
help="link despite duplicate definitions (/FORCE:MULTIPLE)")
|
||||
parser.add_argument("--link-only", action="store_true", help="reuse the objects from a previous run")
|
||||
args = parser.parse_args()
|
||||
|
||||
out_dir = Path(args.out)
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
config = json.loads((ROOT / "data" / "compile.json").read_text(encoding="utf-8"))
|
||||
tc = Toolchain()
|
||||
print(f"toolchain: {tc.root} ({tc.kind})")
|
||||
|
||||
if args.link_only:
|
||||
objects = [out_dir / (unit.replace("/", "_") + ".obj") for unit in exe_units(config)]
|
||||
compile_failures = 0
|
||||
else:
|
||||
objects, compile_failures = compile_units(tc, config, out_dir, args.jobs)
|
||||
|
||||
extra = ["/FORCE:MULTIPLE"] if args.force_multiple else []
|
||||
code, log, exe = link(tc, [*objects, *build_import_libs(tc, out_dir)], out_dir, extra)
|
||||
summarize(log, out_dir)
|
||||
if code == 0:
|
||||
print(f"built {exe}")
|
||||
sys.exit(1 if code != 0 or compile_failures else 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
29
scripts/exe/imports/BaseSDK.def
Normal file
29
scripts/exe/imports/BaseSDK.def
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
; Imports of the original Ragexe 2026-02-19 from BaseSDK.dll, checked against the shipped DLL's exports.
|
||||
LIBRARY BaseSDK.dll
|
||||
EXPORTS
|
||||
??0CallbackResult@PCSDK@Stove@@QAE@ABU012@@Z
|
||||
??0StovePCInitializeParam@Base@PCSDK@Stove@@QAE@XZ
|
||||
??0StovePCShutdown@Base@PCSDK@Stove@@QAE@ABU0123@@Z
|
||||
??0StovePCUser@Base@PCSDK@Stove@@QAE@XZ
|
||||
??1CallbackResult@PCSDK@Stove@@QAE@XZ
|
||||
??1Result@PCSDK@Stove@@QAE@XZ
|
||||
??1StovePCInitializeParam@Base@PCSDK@Stove@@QAE@XZ
|
||||
??1StovePCShutdown@Base@PCSDK@Stove@@QAE@XZ
|
||||
??1StovePCUser@Base@PCSDK@Stove@@QAE@XZ
|
||||
??4Result@PCSDK@Stove@@QAEAAU012@ABU012@@Z
|
||||
?GetAccessToken@StovePCToken@Base@PCSDK@Stove@@QBEPB_WXZ
|
||||
?GetCategory1@StovePCLogEvent@Base@PCSDK@Stove@@QBEPB_WXZ
|
||||
?GetGameUserId@StovePCUser@Base@PCSDK@Stove@@QBE_KXZ
|
||||
?GetMemberNumber@StovePCUser@Base@PCSDK@Stove@@QBE_KXZ
|
||||
?GetResult@CallbackResult@PCSDK@Stove@@QBE?AUResult@23@XZ
|
||||
?IsSuccessful@Result@PCSDK@Stove@@QBE_NXZ
|
||||
?SetApplicationKey@StovePCInitializeParam@Base@PCSDK@Stove@@QAEXPB_W@Z
|
||||
?SetCategory1@StovePCLogEvent@Base@PCSDK@Stove@@QAEXPB_W@Z
|
||||
?SetEnvironment@StovePCInitializeParam@Base@PCSDK@Stove@@QAEXPB_W@Z
|
||||
Base_GetAccessToken
|
||||
Base_GetShutdown
|
||||
Base_GetUser
|
||||
Base_Initialize
|
||||
Base_RestartAppIfNecessary
|
||||
Base_RunCallback
|
||||
Base_UnInitialize
|
||||
9
scripts/exe/imports/D3DX9_43.def
Normal file
9
scripts/exe/imports/D3DX9_43.def
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
; Imports of the original Ragexe 2026-02-19 from D3DX9_43.dll, checked against the shipped DLL's exports.
|
||||
; D3DX is __stdcall but exports undecorated names, so the decorated import maps to the plain export.
|
||||
LIBRARY D3DX9_43.dll
|
||||
EXPORTS
|
||||
D3DXFilterTexture@16=D3DXFilterTexture
|
||||
D3DXLoadSurfaceFromMemory@40=D3DXLoadSurfaceFromMemory
|
||||
D3DXLoadSurfaceFromSurface@32=D3DXLoadSurfaceFromSurface
|
||||
D3DXMatrixPerspectiveFovLH@20=D3DXMatrixPerspectiveFovLH
|
||||
D3DXSaveSurfaceToFileA@20=D3DXSaveSurfaceToFileA
|
||||
41
scripts/exe/imports/IAPSDK.def
Normal file
41
scripts/exe/imports/IAPSDK.def
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
; Imports of the original Ragexe 2026-02-19 from IAPSDK.dll, checked against the shipped DLL's exports.
|
||||
LIBRARY IAPSDK.dll
|
||||
EXPORTS
|
||||
??0StovePCFetchProductParam@IAP@PCSDK@Stove@@QAE@XZ
|
||||
??0StovePCOrderProduct@IAP@PCSDK@Stove@@QAE@XZ
|
||||
??0StovePCPaymentOption@IAP@PCSDK@Stove@@QAE@ABU0123@@Z
|
||||
??0StovePCPaymentOption@IAP@PCSDK@Stove@@QAE@XZ
|
||||
??0StovePCPurchaseResult@IAP@PCSDK@Stove@@QAE@ABU0123@@Z
|
||||
??0StovePCStartPurchaseParam@IAP@PCSDK@Stove@@QAE@XZ
|
||||
??0StovePCTermsOption@IAP@PCSDK@Stove@@QAE@XZ
|
||||
??1StovePCFetchProductParam@IAP@PCSDK@Stove@@QAE@XZ
|
||||
??1StovePCPurchaseResult@IAP@PCSDK@Stove@@QAE@XZ
|
||||
??1StovePCStartPurchaseParam@IAP@PCSDK@Stove@@QAE@XZ
|
||||
?CreateOrderProduct@StovePCStartPurchaseParam@IAP@PCSDK@Stove@@QAEXI@Z
|
||||
?GetCategoryId@StovePCProduct@IAP@PCSDK@Stove@@QBEPB_WXZ
|
||||
?GetCategoryId@StovePCPurchasedProduct@IAP@PCSDK@Stove@@QBEPB_WXZ
|
||||
?GetChargeTypeName@StovePCChargeInfo@IAP@PCSDK@Stove@@QBEPB_WXZ
|
||||
?GetDisplayNumber@StovePCShopCategory@IAP@PCSDK@Stove@@QBEHXZ
|
||||
?GetGuidQuantity@StovePCProduct@IAP@PCSDK@Stove@@QBEHXZ
|
||||
?GetProductId@StovePCOrderProduct@IAP@PCSDK@Stove@@QBE_JXZ
|
||||
?GetProductId@StovePCOrderProduct@IAP@PCSDK@Stove@@QBE_JXZ
|
||||
?GetPurchaseLimitCount@StovePCProduct@IAP@PCSDK@Stove@@QBEHXZ
|
||||
?GetSaleBeginDate@StovePCProduct@IAP@PCSDK@Stove@@QBE_JXZ
|
||||
?GetSaleEndDate@StovePCProduct@IAP@PCSDK@Stove@@QBE_JXZ
|
||||
?GetSalePrice@StovePCProduct@IAP@PCSDK@Stove@@QBENXZ
|
||||
?SetCategoryId@StovePCFetchProductParam@IAP@PCSDK@Stove@@QAEXPB_W@Z
|
||||
?SetChargeDisplayDeductVal@StovePCChargeInfo@IAP@PCSDK@Stove@@QAEXN@Z
|
||||
?SetChargeType@StovePCChargeInfo@IAP@PCSDK@Stove@@QAEXH@Z
|
||||
?SetOperation@StovePCPaymentOption@IAP@PCSDK@Stove@@QAEXW4StovePCPaymentOperation@234@@Z
|
||||
?SetOperation@StovePCPaymentOption@IAP@PCSDK@Stove@@QAEXW4StovePCPaymentOperation@234@@Z
|
||||
?SetOrderProduct@StovePCStartPurchaseParam@IAP@PCSDK@Stove@@QAEXHPBUStovePCOrderProduct@234@@Z
|
||||
?SetPageNumber@StovePCFetchProductParam@IAP@PCSDK@Stove@@QAEXH@Z
|
||||
?SetPageSize@StovePCFetchProductParam@IAP@PCSDK@Stove@@QAEXH@Z
|
||||
?SetProductId@StovePCOrderProduct@IAP@PCSDK@Stove@@QAEX_J@Z
|
||||
?SetPurchaseOption@StovePCStartPurchaseParam@IAP@PCSDK@Stove@@QAEXUStovePCPurchaseOption@234@@Z
|
||||
IAP_ConfirmPurchase
|
||||
IAP_FetchProducts
|
||||
IAP_FetchTermsAgreement
|
||||
IAP_Initialize
|
||||
IAP_StartPurchase
|
||||
IAP_UnInitialize
|
||||
50
scripts/exe/imports/Mss32.def
Normal file
50
scripts/exe/imports/Mss32.def
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
; Imports of the original Ragexe 2026-02-19 from Mss32.dll, checked against the shipped DLL's exports.
|
||||
LIBRARY Mss32.dll
|
||||
EXPORTS
|
||||
AIL_3D_room_type@4=_AIL_3D_room_type@4
|
||||
AIL_3D_sample_status@4=_AIL_3D_sample_status@4
|
||||
AIL_3D_speaker_type@4=_AIL_3D_speaker_type@4
|
||||
AIL_WAV_info@8=_AIL_WAV_info@8
|
||||
AIL_allocate_3D_sample_handle@4=_AIL_allocate_3D_sample_handle@4
|
||||
AIL_allocate_sample_handle@4=_AIL_allocate_sample_handle@4
|
||||
AIL_close_3D_listener@4=_AIL_close_3D_listener@4
|
||||
AIL_close_3D_provider@4=_AIL_close_3D_provider@4
|
||||
AIL_close_digital_driver@4=_AIL_close_digital_driver@4
|
||||
AIL_close_stream@4=_AIL_close_stream@4
|
||||
AIL_decompress_ADPCM@12=_AIL_decompress_ADPCM@12
|
||||
AIL_decompress_ASI@24=_AIL_decompress_ASI@24
|
||||
AIL_end_3D_sample@4=_AIL_end_3D_sample@4
|
||||
AIL_end_sample@4=_AIL_end_sample@4
|
||||
AIL_enumerate_3D_providers@12=_AIL_enumerate_3D_providers@12
|
||||
AIL_file_type@8=_AIL_file_type@8
|
||||
AIL_init_sample@4=_AIL_init_sample@4
|
||||
AIL_mem_free_lock@4=_AIL_mem_free_lock@4
|
||||
AIL_open_3D_listener@4=_AIL_open_3D_listener@4
|
||||
AIL_open_3D_provider@4=_AIL_open_3D_provider@4
|
||||
AIL_open_digital_driver@16=_AIL_open_digital_driver@16
|
||||
AIL_open_stream@12=_AIL_open_stream@12
|
||||
AIL_pause_stream@8=_AIL_pause_stream@8
|
||||
AIL_release_3D_sample_handle@4=_AIL_release_3D_sample_handle@4
|
||||
AIL_release_sample_handle@4=_AIL_release_sample_handle@4
|
||||
AIL_sample_status@4=_AIL_sample_status@4
|
||||
AIL_set_3D_orientation@28=_AIL_set_3D_orientation@28
|
||||
AIL_set_3D_position@16=_AIL_set_3D_position@16
|
||||
AIL_set_3D_room_type@8=_AIL_set_3D_room_type@8
|
||||
AIL_set_3D_sample_distances@12=_AIL_set_3D_sample_distances@12
|
||||
AIL_set_3D_sample_effects_level@8=_AIL_set_3D_sample_effects_level@8
|
||||
AIL_set_3D_sample_file@8=_AIL_set_3D_sample_file@8
|
||||
AIL_set_3D_sample_volume@8=_AIL_set_3D_sample_volume@8
|
||||
AIL_set_3D_speaker_type@8=_AIL_set_3D_speaker_type@8
|
||||
AIL_set_preference@8=_AIL_set_preference@8
|
||||
AIL_set_redist_directory@4=_AIL_set_redist_directory@4
|
||||
AIL_set_sample_file@12=_AIL_set_sample_file@12
|
||||
AIL_set_sample_volume@8=_AIL_set_sample_volume@8
|
||||
AIL_set_stream_loop_count@8=_AIL_set_stream_loop_count@8
|
||||
AIL_set_stream_volume@8=_AIL_set_stream_volume@8
|
||||
AIL_shutdown@0=_AIL_shutdown@0
|
||||
AIL_start_3D_sample@4=_AIL_start_3D_sample@4
|
||||
AIL_start_sample@4=_AIL_start_sample@4
|
||||
AIL_start_stream@4=_AIL_start_stream@4
|
||||
AIL_startup@0=_AIL_startup@0
|
||||
AIL_stream_status@4=_AIL_stream_status@4
|
||||
AIL_stream_volume@4=_AIL_stream_volume@4
|
||||
16
scripts/exe/imports/binkw32.def
Normal file
16
scripts/exe/imports/binkw32.def
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
; Imports of the original Ragexe 2026-02-19 from binkw32.dll, checked against the shipped DLL's exports.
|
||||
LIBRARY binkw32.dll
|
||||
EXPORTS
|
||||
BinkClose@4=_BinkClose@4
|
||||
BinkCopyToBuffer@28=_BinkCopyToBuffer@28
|
||||
BinkDoFrame@4=_BinkDoFrame@4
|
||||
BinkGetError@0=_BinkGetError@0
|
||||
BinkGoto@12=_BinkGoto@12
|
||||
BinkNextFrame@4=_BinkNextFrame@4
|
||||
BinkOpen@8=_BinkOpen@8
|
||||
BinkOpenDirectSound@4=_BinkOpenDirectSound@4
|
||||
BinkPause@8=_BinkPause@8
|
||||
BinkSetSoundSystem@8=_BinkSetSoundSystem@8
|
||||
BinkSetVolume@12=_BinkSetVolume@12
|
||||
BinkShouldSkip@4=_BinkShouldSkip@4
|
||||
BinkWait@4=_BinkWait@4
|
||||
49
scripts/exe/imports/granny2.def
Normal file
49
scripts/exe/imports/granny2.def
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
; Imports of the original Ragexe 2026-02-19 from granny2.dll, checked against the shipped DLL's exports.
|
||||
LIBRARY granny2.dll
|
||||
EXPORTS
|
||||
GrannyPNT332VertexType DATA
|
||||
GrannyRGBA8888PixelFormat DATA
|
||||
GrannyBuildWorldPose@24=_GrannyBuildWorldPose@24
|
||||
GrannyControlModelsNext@4=_GrannyControlModelsNext@4
|
||||
GrannyCopyMeshIndices@12=_GrannyCopyMeshIndices@12
|
||||
GrannyCopyMeshVertices@12=_GrannyCopyMeshVertices@12
|
||||
GrannyCopyTextureImage@32=_GrannyCopyTextureImage@32
|
||||
GrannyDeformVertices@24=_GrannyDeformVertices@24
|
||||
GrannyFreeCompletedModelControls@4=_GrannyFreeCompletedModelControls@4
|
||||
GrannyFreeControl@4=_GrannyFreeControl@4
|
||||
GrannyFreeFile@4=_GrannyFreeFile@4
|
||||
GrannyFreeFileSection@8=_GrannyFreeFileSection@8
|
||||
GrannyFreeLocalPose@4=_GrannyFreeLocalPose@4
|
||||
GrannyFreeMeshBinding@4=_GrannyFreeMeshBinding@4
|
||||
GrannyFreeMeshDeformer@4=_GrannyFreeMeshDeformer@4
|
||||
GrannyFreeModelInstance@4=_GrannyFreeModelInstance@4
|
||||
GrannyFreeWorldPose@4=_GrannyFreeWorldPose@4
|
||||
GrannyGetControlDurationLeft@4=_GrannyGetControlDurationLeft@4
|
||||
GrannyGetFileInfo@4=_GrannyGetFileInfo@4
|
||||
GrannyGetMaterialTextureByType@8=_GrannyGetMaterialTextureByType@8
|
||||
GrannyGetMeshBindingToBoneIndices@4=_GrannyGetMeshBindingToBoneIndices@4
|
||||
GrannyGetMeshBytesPerIndex@4=_GrannyGetMeshBytesPerIndex@4
|
||||
GrannyGetMeshIndexCount@4=_GrannyGetMeshIndexCount@4
|
||||
GrannyGetMeshIndices@4=_GrannyGetMeshIndices@4
|
||||
GrannyGetMeshTriangleGroups@4=_GrannyGetMeshTriangleGroups@4
|
||||
GrannyGetMeshVertexCount@4=_GrannyGetMeshVertexCount@4
|
||||
GrannyGetMeshVertexType@4=_GrannyGetMeshVertexType@4
|
||||
GrannyGetMeshVertices@4=_GrannyGetMeshVertices@4
|
||||
GrannyGetSecondsElapsed@8=_GrannyGetSecondsElapsed@8
|
||||
GrannyGetSourceSkeleton@4=_GrannyGetSourceSkeleton@4
|
||||
GrannyGetSystemSeconds@0=_GrannyGetSystemSeconds@0
|
||||
GrannyGetWorldPoseComposite4x4@8=_GrannyGetWorldPoseComposite4x4@8
|
||||
GrannyInstantiateModel@4=_GrannyInstantiateModel@4
|
||||
GrannyMeshIsRigid@4=_GrannyMeshIsRigid@4
|
||||
GrannyNewLocalPose@4=_GrannyNewLocalPose@4
|
||||
GrannyNewMeshBinding@12=_GrannyNewMeshBinding@12
|
||||
GrannyNewMeshDeformer@12=_GrannyNewMeshDeformer@12
|
||||
GrannyNewWorldPose@4=_GrannyNewWorldPose@4
|
||||
GrannyPlayControlledAnimation@12=_GrannyPlayControlledAnimation@12
|
||||
GrannyReadEntireFileFromMemory@8=_GrannyReadEntireFileFromMemory@8
|
||||
GrannySampleModelAnimations@16=_GrannySampleModelAnimations@16
|
||||
GrannySetControlActive@8=_GrannySetControlActive@8
|
||||
GrannySetControlLoopCount@8=_GrannySetControlLoopCount@8
|
||||
GrannySetModelClock@8=_GrannySetModelClock@8
|
||||
GrannyTextureHasAlpha@4=_GrannyTextureHasAlpha@4
|
||||
GrannyVersionsMatch_@16=_GrannyVersionsMatch_@16
|
||||
8
scripts/exe/imports/ijl15.def
Normal file
8
scripts/exe/imports/ijl15.def
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
; Imports of the original Ragexe 2026-02-19 from ijl15.dll, checked against the shipped DLL's exports.
|
||||
; IJL is __stdcall but exports undecorated names, so the decorated import maps to the plain export.
|
||||
LIBRARY ijl15.dll
|
||||
EXPORTS
|
||||
ijlFree@4=ijlFree
|
||||
ijlInit@4=ijlInit
|
||||
ijlRead@8=ijlRead
|
||||
ijlWrite@8=ijlWrite
|
||||
124
scripts/exe/jsoncons/JsonCppLoaderGlue.cpp
Normal file
124
scripts/exe/jsoncons/JsonCppLoaderGlue.cpp
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
// jsoncons v0.170.2 entry points used by Source/Utility/JsonCppLoader.cpp,
|
||||
// linked only into the standalone exe built by scripts/exe/build_exe.py. Clank
|
||||
// never compiles this file.
|
||||
//
|
||||
// The original statically links jsoncons; these ten functions are the
|
||||
// instantiations JsonCppLoader calls by address (fn_00198 ... fn_00769).
|
||||
// v0.170.2 is the last release whose basic_json storage tags (short string 6,
|
||||
// long string 7, byte string 8, array 9, empty object 10, object 11, const
|
||||
// pointer 12) and basic_json_decode_options layout (virtual base at +8)
|
||||
// match JsonValue and the loader's option storage.
|
||||
//
|
||||
// JsonCppLoader declares them as extern "C" void(), takes their address and
|
||||
// calls them through __thiscall or __cdecl pointers. The __thiscall ones are
|
||||
// therefore __thiscall members of the *Thunk types here, and each plain C
|
||||
// name is an /ALTERNATENAME for the member's decorated name (end of file).
|
||||
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons_ext/bson/bson.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
|
||||
namespace jsoncons_glue {
|
||||
using Json = jsoncons::basic_json<char, jsoncons::sorted_policy>;
|
||||
using JsonOptions = jsoncons::basic_json_decode_options<char>;
|
||||
using JsonOptionsCommon = jsoncons::basic_json_options_common<char>;
|
||||
using BsonOptions = jsoncons::bson::bson_decode_options;
|
||||
using JsonHandler = std::function<bool(jsoncons::json_errc, const jsoncons::ser_context&)>;
|
||||
|
||||
static_assert(sizeof(Json) == 0x10);
|
||||
static_assert(sizeof(JsonHandler) == 40);
|
||||
static_assert(sizeof(JsonOptions) <= 248);
|
||||
static_assert(sizeof(BsonOptions) <= 16);
|
||||
|
||||
// Each member runs with the object the loader passes in ECX.
|
||||
struct HandlerThunk : JsonHandler {
|
||||
// fn_00198: std::function<...>(default_json_parsing), constructed in place
|
||||
// (the loader passes the storage twice: this and the source argument).
|
||||
void Construct(void*);
|
||||
};
|
||||
|
||||
struct JsonOptionsThunk : JsonOptions {
|
||||
// fn_00321: constructor; the flag says whether to build the virtual base.
|
||||
JsonOptions* Construct(int);
|
||||
};
|
||||
|
||||
struct JsonOptionsCommonThunk : JsonOptionsCommon {
|
||||
// fn_00368: destructor of the virtual base subobject (loader passes +8).
|
||||
void Destroy();
|
||||
};
|
||||
|
||||
struct BsonOptionsThunk : BsonOptions {
|
||||
// fn_00349: constructor, same convention as fn_00321.
|
||||
BsonOptions* Construct(int);
|
||||
};
|
||||
|
||||
struct JsonThunk : Json {
|
||||
// fn_00367: destructor.
|
||||
void Destroy();
|
||||
|
||||
// fn_00769: swap, used to move the parsed document into place.
|
||||
void Swap(Json* other);
|
||||
};
|
||||
|
||||
void HandlerThunk::Construct(void*) {
|
||||
new (static_cast<JsonHandler*>(this)) JsonHandler(jsoncons::default_json_parsing());
|
||||
}
|
||||
|
||||
JsonOptions* JsonOptionsThunk::Construct(int) {
|
||||
return new (static_cast<JsonOptions*>(this)) JsonOptions();
|
||||
}
|
||||
|
||||
void JsonOptionsCommonThunk::Destroy() {
|
||||
this->JsonOptionsCommon::~JsonOptionsCommon();
|
||||
}
|
||||
|
||||
BsonOptions* BsonOptionsThunk::Construct(int) {
|
||||
return new (static_cast<BsonOptions*>(this)) BsonOptions();
|
||||
}
|
||||
|
||||
void JsonThunk::Destroy() {
|
||||
static_cast<Json*>(this)->~Json();
|
||||
}
|
||||
|
||||
void JsonThunk::Swap(Json* other) {
|
||||
static_cast<Json*>(this)->swap(*other);
|
||||
}
|
||||
}
|
||||
|
||||
using namespace jsoncons_glue;
|
||||
|
||||
extern "C" {
|
||||
|
||||
// fn_00272: bson::decode_bson<json>(std::istream&, const bson_decode_options&).
|
||||
Json* __cdecl fn_00272(Json* out, std::ifstream* file, BsonOptions* options) {
|
||||
return new (out) Json(jsoncons::bson::decode_bson<Json>(*file, *options));
|
||||
}
|
||||
|
||||
// fn_00273: bson::decode_bson<json>(const std::vector<uint8_t>&, const bson_decode_options&).
|
||||
Json* __cdecl fn_00273(Json* out, const std::vector<unsigned char>* buffer, BsonOptions* options) {
|
||||
return new (out) Json(jsoncons::bson::decode_bson<Json>(*buffer, *options));
|
||||
}
|
||||
|
||||
// fn_00733: json::parse(std::istream&, const json_decode_options&, handler).
|
||||
// The handler is passed by value: the callee owns and destroys it.
|
||||
Json* __cdecl fn_00733(Json* out, std::ifstream* file, JsonOptions* options, JsonHandler handler) {
|
||||
return new (out) Json(Json::parse(*file, *options, handler));
|
||||
}
|
||||
|
||||
// fn_00734: json::parse(const char*, const json_decode_options&, handler).
|
||||
Json* __cdecl fn_00734(Json* out, const unsigned char* data, JsonOptions* options, JsonHandler handler) {
|
||||
return new (out) Json(Json::parse(jsoncons::basic_string_view<char>(reinterpret_cast<const char*>(data)), *options, handler));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma comment(linker, "/ALTERNATENAME:_fn_00198=?Construct@HandlerThunk@jsoncons_glue@@QAEXPAX@Z")
|
||||
#pragma comment(linker, "/ALTERNATENAME:_fn_00321=?Construct@JsonOptionsThunk@jsoncons_glue@@QAEPAV?$basic_json_decode_options@D@jsoncons@@H@Z")
|
||||
#pragma comment(linker, "/ALTERNATENAME:_fn_00368=?Destroy@JsonOptionsCommonThunk@jsoncons_glue@@QAEXXZ")
|
||||
#pragma comment(linker, "/ALTERNATENAME:_fn_00349=?Construct@BsonOptionsThunk@jsoncons_glue@@QAEPAVbson_decode_options@bson@jsoncons@@H@Z")
|
||||
#pragma comment(linker, "/ALTERNATENAME:_fn_00367=?Destroy@JsonThunk@jsoncons_glue@@QAEXXZ")
|
||||
#pragma comment(linker, "/ALTERNATENAME:_fn_00769=?Swap@JsonThunk@jsoncons_glue@@QAEXPAV?$basic_json@DUsorted_policy@jsoncons@@V?$allocator@D@std@@@jsoncons@@@Z")
|
||||
28
scripts/exe/jsoncons/LICENSE
Normal file
28
scripts/exe/jsoncons/LICENSE
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright Daniel Parker 2013 - 2020.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
38
scripts/exe/jsoncons/include/jsoncons/allocator_holder.hpp
Normal file
38
scripts/exe/jsoncons/include/jsoncons/allocator_holder.hpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_ALLOCATOR_HOLDER_HPP
|
||||
#define JSONCONS_ALLOCATOR_HOLDER_HPP
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
template <class Allocator>
|
||||
class allocator_holder
|
||||
{
|
||||
public:
|
||||
using allocator_type = Allocator;
|
||||
private:
|
||||
allocator_type alloc_;
|
||||
public:
|
||||
allocator_holder() = default;
|
||||
allocator_holder(const allocator_holder&) = default;
|
||||
allocator_holder(allocator_holder&&) = default;
|
||||
allocator_holder& operator=(const allocator_holder&) = default;
|
||||
allocator_holder& operator=(allocator_holder&&) = default;
|
||||
allocator_holder(const allocator_type& alloc)
|
||||
: alloc_(alloc)
|
||||
{}
|
||||
~allocator_holder() = default;
|
||||
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
return alloc_;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
5917
scripts/exe/jsoncons/include/jsoncons/basic_json.hpp
Normal file
5917
scripts/exe/jsoncons/include/jsoncons/basic_json.hpp
Normal file
File diff suppressed because it is too large
Load diff
1611
scripts/exe/jsoncons/include/jsoncons/bigint.hpp
Normal file
1611
scripts/exe/jsoncons/include/jsoncons/bigint.hpp
Normal file
File diff suppressed because it is too large
Load diff
820
scripts/exe/jsoncons/include/jsoncons/byte_string.hpp
Normal file
820
scripts/exe/jsoncons/include/jsoncons/byte_string.hpp
Normal file
|
|
@ -0,0 +1,820 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BYTE_STRING_HPP
|
||||
#define JSONCONS_BYTE_STRING_HPP
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <cmath>
|
||||
#include <cstring> // std::memcmp
|
||||
#include <memory> // std::allocator
|
||||
#include <iterator>
|
||||
#include <exception>
|
||||
#include <iomanip> // std::setw
|
||||
#include <initializer_list>
|
||||
#include <utility> // std::move
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/conv_error.hpp>
|
||||
#include <jsoncons/extension_traits.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// Algorithms
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class InputIt, class Container>
|
||||
typename std::enable_if<std::is_same<typename std::iterator_traits<InputIt>::value_type,uint8_t>::value,size_t>::type
|
||||
encode_base64_generic(InputIt first, InputIt last, const char alphabet[65], Container& result)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
unsigned char a3[3];
|
||||
unsigned char a4[4];
|
||||
unsigned char fill = alphabet[64];
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
while (first != last)
|
||||
{
|
||||
a3[i++] = *first++;
|
||||
if (i == 3)
|
||||
{
|
||||
a4[0] = (a3[0] & 0xfc) >> 2;
|
||||
a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
|
||||
a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
|
||||
a4[3] = a3[2] & 0x3f;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
result.push_back(alphabet[a4[i]]);
|
||||
++count;
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
for (j = i; j < 3; ++j)
|
||||
{
|
||||
a3[j] = 0;
|
||||
}
|
||||
|
||||
a4[0] = (a3[0] & 0xfc) >> 2;
|
||||
a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
|
||||
a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
|
||||
|
||||
for (j = 0; j < i + 1; ++j)
|
||||
{
|
||||
result.push_back(alphabet[a4[j]]);
|
||||
++count;
|
||||
}
|
||||
|
||||
if (fill != 0)
|
||||
{
|
||||
while (i++ < 3)
|
||||
{
|
||||
result.push_back(fill);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template <class InputIt, class F, class Container>
|
||||
typename std::enable_if<extension_traits::is_back_insertable_byte_container<Container>::value,decode_result<InputIt>>::type
|
||||
decode_base64_generic(InputIt first, InputIt last,
|
||||
const uint8_t reverse_alphabet[256],
|
||||
F f,
|
||||
Container& result)
|
||||
{
|
||||
uint8_t a4[4], a3[3];
|
||||
uint8_t i = 0;
|
||||
uint8_t j = 0;
|
||||
|
||||
while (first != last && *first != '=')
|
||||
{
|
||||
if (!f(*first))
|
||||
{
|
||||
return decode_result<InputIt>{first, conv_errc::conversion_failed};
|
||||
}
|
||||
|
||||
a4[i++] = static_cast<uint8_t>(*first++);
|
||||
if (i == 4)
|
||||
{
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
a4[i] = reverse_alphabet[a4[i]];
|
||||
}
|
||||
|
||||
a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
|
||||
a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
|
||||
a3[2] = ((a4[2] & 0x3) << 6) + a4[3];
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
result.push_back(a3[i]);
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
for (j = 0; j < i; ++j)
|
||||
{
|
||||
a4[j] = reverse_alphabet[a4[j]];
|
||||
}
|
||||
|
||||
a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
|
||||
a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
|
||||
|
||||
for (j = 0; j < i - 1; ++j)
|
||||
{
|
||||
result.push_back(a3[j]);
|
||||
}
|
||||
}
|
||||
return decode_result<InputIt>{last, conv_errc::success};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class InputIt, class Container>
|
||||
typename std::enable_if<std::is_same<typename std::iterator_traits<InputIt>::value_type,uint8_t>::value,size_t>::type
|
||||
encode_base16(InputIt first, InputIt last, Container& result)
|
||||
{
|
||||
static constexpr char characters[] = "0123456789ABCDEF";
|
||||
|
||||
for (auto it = first; it != last; ++it)
|
||||
{
|
||||
uint8_t c = *it;
|
||||
result.push_back(characters[c >> 4]);
|
||||
result.push_back(characters[c & 0xf]);
|
||||
}
|
||||
return (last-first)*2;
|
||||
}
|
||||
|
||||
template <class InputIt, class Container>
|
||||
typename std::enable_if<std::is_same<typename std::iterator_traits<InputIt>::value_type,uint8_t>::value,size_t>::type
|
||||
encode_base64url(InputIt first, InputIt last, Container& result)
|
||||
{
|
||||
static constexpr char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789-_"
|
||||
"\0";
|
||||
return detail::encode_base64_generic(first, last, alphabet, result);
|
||||
}
|
||||
|
||||
template <class InputIt, class Container>
|
||||
typename std::enable_if<std::is_same<typename std::iterator_traits<InputIt>::value_type,uint8_t>::value,size_t>::type
|
||||
encode_base64(InputIt first, InputIt last, Container& result)
|
||||
{
|
||||
static constexpr char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/"
|
||||
"=";
|
||||
return detail::encode_base64_generic(first, last, alphabet, result);
|
||||
}
|
||||
|
||||
template <class Char>
|
||||
bool is_base64(Char c)
|
||||
{
|
||||
return (c >= 0 && c < 128) && (isalnum((int)c) || c == '+' || c == '/');
|
||||
}
|
||||
|
||||
template <class Char>
|
||||
bool is_base64url(Char c)
|
||||
{
|
||||
return (c >= 0 && c < 128) && (isalnum((int)c) || c == '-' || c == '_');
|
||||
}
|
||||
|
||||
inline
|
||||
static bool is_base64url(int c)
|
||||
{
|
||||
return isalnum(c) || c == '-' || c == '_';
|
||||
}
|
||||
|
||||
// decode
|
||||
|
||||
template <class InputIt, class Container>
|
||||
typename std::enable_if<extension_traits::is_back_insertable_byte_container<Container>::value,decode_result<InputIt>>::type
|
||||
decode_base64url(InputIt first, InputIt last, Container& result)
|
||||
{
|
||||
static constexpr uint8_t reverse_alphabet[256] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 62, 0xff, 0xff,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 63,
|
||||
0xff, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
auto retval = jsoncons::detail::decode_base64_generic(first, last, reverse_alphabet,
|
||||
is_base64url<typename std::iterator_traits<InputIt>::value_type>,
|
||||
result);
|
||||
return retval.ec == conv_errc::success ? retval : decode_result<InputIt>{retval.it, conv_errc::not_base64url};
|
||||
}
|
||||
|
||||
template <class InputIt, class Container>
|
||||
typename std::enable_if<extension_traits::is_back_insertable_byte_container<Container>::value,decode_result<InputIt>>::type
|
||||
decode_base64(InputIt first, InputIt last, Container& result)
|
||||
{
|
||||
static constexpr uint8_t reverse_alphabet[256] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
auto retval = jsoncons::detail::decode_base64_generic(first, last, reverse_alphabet,
|
||||
is_base64<typename std::iterator_traits<InputIt>::value_type>,
|
||||
result);
|
||||
return retval.ec == conv_errc::success ? retval : decode_result<InputIt>{retval.it, conv_errc::not_base64};
|
||||
}
|
||||
|
||||
template <class InputIt,class Container>
|
||||
typename std::enable_if<extension_traits::is_back_insertable_byte_container<Container>::value,decode_result<InputIt>>::type
|
||||
decode_base16(InputIt first, InputIt last, Container& result)
|
||||
{
|
||||
std::size_t len = std::distance(first,last);
|
||||
if (len & 1)
|
||||
{
|
||||
return decode_result<InputIt>{first, conv_errc::not_base16};
|
||||
}
|
||||
|
||||
InputIt it = first;
|
||||
while (it != last)
|
||||
{
|
||||
uint8_t val;
|
||||
auto a = *it++;
|
||||
if (a >= '0' && a <= '9')
|
||||
{
|
||||
val = static_cast<uint8_t>(a - '0') << 4;
|
||||
}
|
||||
else if ((a | 0x20) >= 'a' && (a | 0x20) <= 'f')
|
||||
{
|
||||
val = (static_cast<uint8_t>((a | 0x20) - 'a') + 10) << 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return decode_result<InputIt>{first, conv_errc::not_base16};
|
||||
}
|
||||
|
||||
auto b = *it++;
|
||||
if (b >= '0' && b <= '9')
|
||||
{
|
||||
val |= (b - '0');
|
||||
}
|
||||
else if ((b | 0x20) >= 'a' && (b | 0x20) <= 'f')
|
||||
{
|
||||
val |= ((b | 0x20) - 'a' + 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
return decode_result<InputIt>{first, conv_errc::not_base16};
|
||||
}
|
||||
|
||||
result.push_back(val);
|
||||
}
|
||||
return decode_result<InputIt>{last, conv_errc::success};
|
||||
}
|
||||
|
||||
struct byte_traits
|
||||
{
|
||||
using char_type = uint8_t;
|
||||
|
||||
static constexpr int eof()
|
||||
{
|
||||
return std::char_traits<char>::eof();
|
||||
}
|
||||
|
||||
static int compare(const char_type* s1, const char_type* s2, std::size_t count) noexcept
|
||||
{
|
||||
return std::memcmp(s1,s2,count);
|
||||
}
|
||||
};
|
||||
|
||||
// basic_byte_string
|
||||
|
||||
template <class Allocator>
|
||||
class basic_byte_string;
|
||||
|
||||
// byte_string_view
|
||||
class byte_string_view
|
||||
{
|
||||
const uint8_t* data_;
|
||||
std::size_t size_;
|
||||
public:
|
||||
using traits_type = byte_traits;
|
||||
|
||||
using const_iterator = const uint8_t*;
|
||||
using iterator = const_iterator;
|
||||
using size_type = std::size_t;
|
||||
using value_type = uint8_t;
|
||||
using reference = uint8_t&;
|
||||
using const_reference = const uint8_t&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = uint8_t*;
|
||||
using const_pointer = const uint8_t*;
|
||||
|
||||
constexpr byte_string_view() noexcept
|
||||
: data_(nullptr), size_(0)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr byte_string_view(const uint8_t* data, std::size_t length) noexcept
|
||||
: data_(data), size_(length)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
constexpr explicit byte_string_view(const Container& cont,
|
||||
typename std::enable_if<extension_traits::is_byte_sequence<Container>::value,int>::type = 0)
|
||||
: data_(reinterpret_cast<const uint8_t*>(cont.data())), size_(cont.size())
|
||||
{
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
constexpr byte_string_view(const basic_byte_string<Allocator>& bytes);
|
||||
|
||||
constexpr byte_string_view(const byte_string_view&) noexcept = default;
|
||||
|
||||
JSONCONS_CPP14_CONSTEXPR byte_string_view(byte_string_view&& other) noexcept
|
||||
: data_(nullptr), size_(0)
|
||||
{
|
||||
const_pointer temp_data = data_;
|
||||
data_ = other.data_;
|
||||
other.data_ = temp_data;
|
||||
|
||||
size_type temp_size = size_;
|
||||
size_ = other.size_;
|
||||
other.size_ = temp_size;
|
||||
}
|
||||
|
||||
byte_string_view& operator=(const byte_string_view&) = default;
|
||||
|
||||
byte_string_view& operator=(byte_string_view&& other) noexcept
|
||||
{
|
||||
std::swap(data_, other.data_);
|
||||
std::swap(size_, other.size_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr const uint8_t* data() const noexcept
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use size()")
|
||||
std::size_t length() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
#endif
|
||||
constexpr size_t size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
// iterator support
|
||||
constexpr const_iterator begin() const noexcept
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
constexpr const_iterator end() const noexcept
|
||||
{
|
||||
return data_ + size_;
|
||||
}
|
||||
constexpr const_iterator cbegin() const noexcept
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
constexpr const_iterator cend() const noexcept
|
||||
{
|
||||
return data_ + size_;
|
||||
}
|
||||
|
||||
constexpr uint8_t operator[](size_type pos) const
|
||||
{
|
||||
return data_[pos];
|
||||
}
|
||||
|
||||
JSONCONS_CPP14_CONSTEXPR byte_string_view substr(size_type pos) const
|
||||
{
|
||||
if (pos > size_)
|
||||
{
|
||||
JSONCONS_THROW(std::out_of_range("pos exceeds size"));
|
||||
}
|
||||
std::size_t n = size_ - pos;
|
||||
return byte_string_view(data_ + pos, n);
|
||||
}
|
||||
|
||||
byte_string_view substr(size_type pos, size_type n) const
|
||||
{
|
||||
if (pos > size_)
|
||||
{
|
||||
JSONCONS_THROW(std::out_of_range("pos exceeds size"));
|
||||
}
|
||||
if (pos + n > size_)
|
||||
{
|
||||
n = size_ - pos;
|
||||
}
|
||||
return byte_string_view(data_ + pos, n);
|
||||
}
|
||||
|
||||
int compare(const byte_string_view& s) const noexcept
|
||||
{
|
||||
const int rc = traits_type::compare(data_, s.data(), (std::min)(size_, s.size()));
|
||||
return rc != 0 ? rc : (size_ == s.size() ? 0 : size_ < s.size() ? -1 : 1);
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
int compare(const basic_byte_string<Allocator>& s) const noexcept
|
||||
{
|
||||
const int rc = traits_type::compare(data_, s.data(), (std::min)(size_, s.size()));
|
||||
return rc != 0 ? rc : (size_ == s.size() ? 0 : size_ < s.size() ? -1 : 1);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const byte_string_view& bstr)
|
||||
{
|
||||
std::basic_ostringstream<CharT> ss;
|
||||
ss.flags(std::ios::hex);
|
||||
ss.fill('0');
|
||||
|
||||
bool first = true;
|
||||
for (auto b : bstr)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << ',';
|
||||
}
|
||||
ss << std::setw(2) << static_cast<int>(b);
|
||||
}
|
||||
os << ss.str();
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
// basic_byte_string
|
||||
template <class Allocator = std::allocator<uint8_t>>
|
||||
class basic_byte_string
|
||||
{
|
||||
using byte_allocator_type = typename std::allocator_traits<Allocator>:: template rebind_alloc<uint8_t>;
|
||||
std::vector<uint8_t,byte_allocator_type> data_;
|
||||
public:
|
||||
using traits_type = byte_traits;
|
||||
using allocator_type = byte_allocator_type;
|
||||
|
||||
using value_type = typename std::vector<uint8_t,byte_allocator_type>::value_type;
|
||||
using size_type = typename std::vector<uint8_t,byte_allocator_type>::size_type;
|
||||
using difference_type = typename std::vector<uint8_t,byte_allocator_type>::difference_type;
|
||||
using reference = typename std::vector<uint8_t,byte_allocator_type>::reference;
|
||||
using const_reference = typename std::vector<uint8_t,byte_allocator_type>::const_reference;
|
||||
using pointer = typename std::vector<uint8_t,byte_allocator_type>::pointer;
|
||||
using const_pointer = typename std::vector<uint8_t,byte_allocator_type>::const_pointer;
|
||||
using iterator = typename std::vector<uint8_t,byte_allocator_type>::iterator;
|
||||
using const_iterator = typename std::vector<uint8_t,byte_allocator_type>::const_iterator;
|
||||
|
||||
basic_byte_string() = default;
|
||||
|
||||
explicit basic_byte_string(const Allocator& alloc)
|
||||
: data_(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
basic_byte_string(std::initializer_list<uint8_t> init)
|
||||
: data_(std::move(init))
|
||||
{
|
||||
}
|
||||
|
||||
basic_byte_string(std::initializer_list<uint8_t> init, const Allocator& alloc)
|
||||
: data_(std::move(init), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
explicit basic_byte_string(const byte_string_view& v)
|
||||
: data_(v.begin(),v.end())
|
||||
{
|
||||
}
|
||||
|
||||
basic_byte_string(const basic_byte_string<Allocator>& v)
|
||||
: data_(v.data_)
|
||||
{
|
||||
}
|
||||
|
||||
basic_byte_string(basic_byte_string<Allocator>&& v) noexcept
|
||||
: data_(std::move(v.data_))
|
||||
{
|
||||
}
|
||||
|
||||
basic_byte_string(const byte_string_view& v, const Allocator& alloc)
|
||||
: data_(v.begin(),v.end(),alloc)
|
||||
{
|
||||
}
|
||||
|
||||
basic_byte_string(const uint8_t* data, std::size_t length, const Allocator& alloc = Allocator())
|
||||
: data_(data, data+length,alloc)
|
||||
{
|
||||
}
|
||||
|
||||
Allocator get_allocator() const
|
||||
{
|
||||
return data_.get_allocator();
|
||||
}
|
||||
|
||||
basic_byte_string& operator=(const basic_byte_string& s) = default;
|
||||
|
||||
basic_byte_string& operator=(basic_byte_string&& other) noexcept
|
||||
{
|
||||
data_.swap(other.data_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reserve(std::size_t new_cap)
|
||||
{
|
||||
data_.reserve(new_cap);
|
||||
}
|
||||
|
||||
void push_back(uint8_t b)
|
||||
{
|
||||
data_.push_back(b);
|
||||
}
|
||||
|
||||
void assign(const uint8_t* s, std::size_t count)
|
||||
{
|
||||
data_.clear();
|
||||
data_.insert(data_.end(), s, s+count);
|
||||
}
|
||||
|
||||
void append(const uint8_t* s, std::size_t count)
|
||||
{
|
||||
data_.insert(data_.end(), s, s+count);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
data_.clear();
|
||||
}
|
||||
|
||||
uint8_t operator[](size_type pos) const
|
||||
{
|
||||
return data_[pos];
|
||||
}
|
||||
|
||||
// iterator support
|
||||
iterator begin() noexcept
|
||||
{
|
||||
return data_.begin();
|
||||
}
|
||||
iterator end() noexcept
|
||||
{
|
||||
return data_.end();
|
||||
}
|
||||
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
return data_.begin();
|
||||
}
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return data_.end();
|
||||
}
|
||||
|
||||
uint8_t* data()
|
||||
{
|
||||
return data_.data();
|
||||
}
|
||||
|
||||
const uint8_t* data() const
|
||||
{
|
||||
return data_.data();
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return data_.size();
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use size()")
|
||||
std::size_t length() const
|
||||
{
|
||||
return data_.size();
|
||||
}
|
||||
#endif
|
||||
|
||||
int compare(const byte_string_view& s) const noexcept
|
||||
{
|
||||
const int rc = traits_type::compare(data(), s.data(), (std::min)(size(), s.size()));
|
||||
return rc != 0 ? rc : (size() == s.size() ? 0 : size() < s.size() ? -1 : 1);
|
||||
}
|
||||
|
||||
int compare(const basic_byte_string& s) const noexcept
|
||||
{
|
||||
const int rc = traits_type::compare(data(), s.data(), (std::min)(size(), s.size()));
|
||||
return rc != 0 ? rc : (size() == s.size() ? 0 : size() < s.size() ? -1 : 1);
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const basic_byte_string& o)
|
||||
{
|
||||
os << byte_string_view(o);
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
constexpr byte_string_view::byte_string_view(const basic_byte_string<Allocator>& bytes)
|
||||
: data_(bytes.data()), size_(bytes.size())
|
||||
{
|
||||
}
|
||||
|
||||
// ==
|
||||
inline
|
||||
bool operator==(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) == 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator==(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) == 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator==(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) == 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator==(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) == 0;
|
||||
}
|
||||
|
||||
// !=
|
||||
|
||||
inline
|
||||
bool operator!=(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) != 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator!=(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) != 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator!=(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) != 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator!=(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) != 0;
|
||||
}
|
||||
|
||||
// <=
|
||||
|
||||
inline
|
||||
bool operator<=(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) <= 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator<=(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) <= 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator<=(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) >= 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator<=(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) >= 0;
|
||||
}
|
||||
|
||||
// <
|
||||
|
||||
inline
|
||||
bool operator<(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) < 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator<(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) < 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator<(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) > 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator<(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) > 0;
|
||||
}
|
||||
|
||||
// >=
|
||||
|
||||
inline
|
||||
bool operator>=(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) >= 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator>=(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) >= 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator>=(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) <= 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator>=(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) <= 0;
|
||||
}
|
||||
|
||||
// >
|
||||
|
||||
inline
|
||||
bool operator>(const byte_string_view& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) > 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator>(const byte_string_view& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) > 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator>(const basic_byte_string<Allocator>& lhs, const byte_string_view& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) < 0;
|
||||
}
|
||||
template<class Allocator>
|
||||
bool operator>(const basic_byte_string<Allocator>& lhs, const basic_byte_string<Allocator>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) < 0;
|
||||
}
|
||||
|
||||
using byte_string = basic_byte_string<std::allocator<uint8_t>>;
|
||||
|
||||
namespace extension_traits {
|
||||
|
||||
template <typename T>
|
||||
struct is_basic_byte_string
|
||||
: std::false_type
|
||||
{};
|
||||
|
||||
template <typename Allocator>
|
||||
struct is_basic_byte_string<basic_byte_string<Allocator>>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
} // namespace extension_traits
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
226
scripts/exe/jsoncons/include/jsoncons/config/binary_config.hpp
Normal file
226
scripts/exe/jsoncons/include/jsoncons/config/binary_config.hpp
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
// Copyright 2017 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CONFIG_BINARY_CONFIG_HPP
|
||||
#define JSONCONS_CONFIG_BINARY_CONFIG_HPP
|
||||
|
||||
#include <cfloat>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring> // std::memcpy
|
||||
#include <memory>
|
||||
#include <type_traits> // std::enable_if
|
||||
|
||||
// The definitions below follow the definitions in compiler_support_p.h, https://github.com/01org/tinycbor
|
||||
// MIT license
|
||||
|
||||
#ifdef __F16C__
|
||||
# include <immintrin.h>
|
||||
#endif
|
||||
|
||||
#ifndef __has_builtin
|
||||
# define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 403) || (__has_builtin(__builtin_bswap64) && __has_builtin(__builtin_bswap32))
|
||||
# define JSONCONS_BYTE_SWAP_64 __builtin_bswap64
|
||||
# define JSONCONS_BYTE_SWAP_32 __builtin_bswap32
|
||||
# ifdef __INTEL_COMPILER
|
||||
# define JSONCONS_BYTE_SWAP_16 _bswap16
|
||||
# elif (__GNUC__ * 100 + __GNUC_MINOR__ >= 608) || __has_builtin(__builtin_bswap16)
|
||||
# define JSONCONS_BYTE_SWAP_16 __builtin_bswap16
|
||||
# endif
|
||||
#endif
|
||||
#elif defined(__sun)
|
||||
# include <sys/byteorder.h>
|
||||
#elif defined(_MSC_VER)
|
||||
// MSVC, which implies sizeof(long) == 4
|
||||
# define JSONCONS_BYTE_SWAP_64 _byteswap_uint64
|
||||
# define JSONCONS_BYTE_SWAP_32 _byteswap_ulong
|
||||
# define JSONCONS_BYTE_SWAP_16 _byteswap_ushort
|
||||
#endif
|
||||
|
||||
namespace jsoncons {
|
||||
namespace binary {
|
||||
|
||||
struct uint128_holder
|
||||
{
|
||||
uint64_t lo;
|
||||
uint64_t hi;
|
||||
};
|
||||
|
||||
static inline bool add_check_overflow(std::size_t v1, std::size_t v2, std::size_t *r)
|
||||
{
|
||||
#if ((defined(__GNUC__) && (__GNUC__ >= 5)) && !defined(__INTEL_COMPILER)) || __has_builtin(__builtin_add_overflow)
|
||||
return __builtin_add_overflow(v1, v2, r);
|
||||
#else
|
||||
// unsigned additions are well-defined
|
||||
*r = v1 + v2;
|
||||
return v1 > v1 + v2;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__apple_build_version__) && ((__clang_major__ < 8) || ((__clang_major__ == 8) && (__clang_minor__ < 1)))
|
||||
#define APPLE_MISSING_INTRINSICS 1
|
||||
#endif
|
||||
|
||||
inline
|
||||
uint16_t encode_half(double val)
|
||||
{
|
||||
#if defined(__F16C__) && !defined(APPLE_MISSING_INTRINSICS)
|
||||
return _cvtss_sh((float)val, 3);
|
||||
#else
|
||||
uint64_t v;
|
||||
std::memcpy(&v, &val, sizeof(v));
|
||||
int64_t sign = static_cast<int64_t>(v >> 63 << 15);
|
||||
int64_t exp = (v >> 52) & 0x7ff;
|
||||
int64_t mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
|
||||
exp -= 1023;
|
||||
if (exp == 1024) {
|
||||
/* infinity or NaN */
|
||||
exp = 16;
|
||||
mant >>= 1;
|
||||
} else if (exp >= 16) {
|
||||
/* overflow, as largest number */
|
||||
exp = 15;
|
||||
mant = 1023;
|
||||
} else if (exp >= -14) {
|
||||
/* regular normal */
|
||||
} else if (exp >= -24) {
|
||||
/* subnormal */
|
||||
mant |= 1024;
|
||||
mant >>= -(exp + 14);
|
||||
exp = -15;
|
||||
} else {
|
||||
/* underflow, make zero */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* safe cast here as bit operations above guarantee not to overflow */
|
||||
return static_cast<uint16_t>(sign | ((exp + 15) << 10) | mant);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* this function was copied & adapted from RFC 7049 Appendix D */
|
||||
inline
|
||||
double decode_half(uint16_t half)
|
||||
{
|
||||
#if defined(__F16C__) && !defined(APPLE_MISSING_INTRINSICS)
|
||||
return _cvtsh_ss(half);
|
||||
#else
|
||||
int64_t exp = (half >> 10) & 0x1f;
|
||||
int64_t mant = half & 0x3ff;
|
||||
double val;
|
||||
if (exp == 0)
|
||||
{
|
||||
val = ldexp(static_cast<double>(mant), -24);
|
||||
}
|
||||
else if (exp != 31)
|
||||
{
|
||||
val = ldexp(static_cast<double>(mant) + 1024.0, static_cast<int>(exp - 25));
|
||||
}
|
||||
else
|
||||
{
|
||||
val = mant == 0 ? std::numeric_limits<double>::infinity() : std::nan("");
|
||||
}
|
||||
return half & 0x8000 ? -val : val;
|
||||
#endif
|
||||
}
|
||||
|
||||
// byte_swap
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) == sizeof(uint8_t),T>::type
|
||||
byte_swap(T val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) == sizeof(uint16_t),T>::type
|
||||
byte_swap(T val)
|
||||
{
|
||||
#if defined(JSONCONS_BYTE_SWAP_16)
|
||||
return JSONCONS_BYTE_SWAP_16(val);
|
||||
#else
|
||||
return (static_cast<uint16_t>(val) >> 8) | (static_cast<uint16_t>(val) << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) == sizeof(uint32_t),T>::type
|
||||
byte_swap(T val)
|
||||
{
|
||||
#if defined(JSONCONS_BYTE_SWAP_32)
|
||||
return JSONCONS_BYTE_SWAP_32(val);
|
||||
#else
|
||||
uint32_t tmp = ((static_cast<uint32_t>(val) << 8) & 0xff00ff00) | ((static_cast<uint32_t>(val) >> 8) & 0xff00ff);
|
||||
return (tmp << 16) | (tmp >> 16);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_integral<T>::value && sizeof(T) == sizeof(uint64_t),T>::type
|
||||
byte_swap(T val)
|
||||
{
|
||||
#if defined(JSONCONS_BYTE_SWAP_64)
|
||||
return JSONCONS_BYTE_SWAP_64(val);
|
||||
#else
|
||||
uint64_t tmp = ((static_cast<uint64_t>(val) & 0x00000000ffffffffull) << 32) | ((static_cast<uint64_t>(val) & 0xffffffff00000000ull) >> 32);
|
||||
tmp = ((tmp & 0x0000ffff0000ffffull) << 16) | ((tmp & 0xffff0000ffff0000ull) >> 16);
|
||||
return ((tmp & 0x00ff00ff00ff00ffull) << 8) | ((tmp & 0xff00ff00ff00ff00ull) >> 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_floating_point<T>::value && sizeof(T) == sizeof(uint32_t),T>::type
|
||||
byte_swap(T val)
|
||||
{
|
||||
uint32_t x;
|
||||
std::memcpy(&x,&val,sizeof(uint32_t));
|
||||
uint32_t y = byte_swap(x);
|
||||
T val2;
|
||||
std::memcpy(&val2,&y,sizeof(uint32_t));
|
||||
return val2;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_floating_point<T>::value && sizeof(T) == sizeof(uint64_t),T>::type
|
||||
byte_swap(T val)
|
||||
{
|
||||
uint64_t x;
|
||||
std::memcpy(&x,&val,sizeof(uint64_t));
|
||||
uint64_t y = byte_swap(x);
|
||||
T val2;
|
||||
std::memcpy(&val2,&y,sizeof(uint64_t));
|
||||
return val2;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<std::is_floating_point<T>::value && sizeof(T) == 2*sizeof(uint64_t),T>::type
|
||||
byte_swap(T val)
|
||||
{
|
||||
uint128_holder x;
|
||||
uint8_t buf[2*sizeof(uint64_t)];
|
||||
std::memcpy(buf,&val,2*sizeof(uint64_t));
|
||||
std::memcpy(&x.lo,buf,sizeof(uint64_t));
|
||||
std::memcpy(&x.hi,buf+sizeof(uint64_t),sizeof(uint64_t));
|
||||
|
||||
uint128_holder y;
|
||||
y.lo = byte_swap(x.hi);
|
||||
y.hi = byte_swap(x.lo);
|
||||
|
||||
T val2;
|
||||
std::memcpy(&val2,&y,2*sizeof(uint64_t));
|
||||
|
||||
return val2;
|
||||
}
|
||||
|
||||
} // binary
|
||||
} // jsoncons
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,375 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_COMPILER_SUPPORT_HPP
|
||||
#define JSONCONS_COMPILER_SUPPORT_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <exception>
|
||||
#include <ostream>
|
||||
|
||||
#if defined (__clang__)
|
||||
#define JSONCONS_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
|
||||
#endif
|
||||
|
||||
// Uncomment the following line to suppress deprecated names (recommended for new code)
|
||||
//#define JSONCONS_NO_DEPRECATED
|
||||
|
||||
// The definitions below follow the definitions in compiler_support_p.h, https://github.com/01org/tinycbor
|
||||
// MIT license
|
||||
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54577
|
||||
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 9
|
||||
#define JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR 1
|
||||
#define JSONCONS_NO_MAP_CONS_TAKES_ALLOCATOR 1
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# define JSONCONS_FALLTHROUGH [[clang::fallthrough]]
|
||||
#elif defined(__GNUC__) && ((__GNUC__ >= 7))
|
||||
# define JSONCONS_FALLTHROUGH __attribute__((fallthrough))
|
||||
#elif defined (__GNUC__)
|
||||
# define JSONCONS_FALLTHROUGH // FALLTHRU
|
||||
#else
|
||||
# define JSONCONS_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define JSONCONS_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#define JSONCONS_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
#define JSONCONS_UNREACHABLE() __builtin_unreachable()
|
||||
#elif defined(_MSC_VER)
|
||||
#define JSONCONS_LIKELY(x) x
|
||||
#define JSONCONS_UNLIKELY(x) x
|
||||
#define JSONCONS_UNREACHABLE() __assume(0)
|
||||
#else
|
||||
#define JSONCONS_LIKELY(x) x
|
||||
#define JSONCONS_UNLIKELY(x) x
|
||||
#define JSONCONS_UNREACHABLE() do {} while (0)
|
||||
#endif
|
||||
|
||||
// Deprecated symbols markup
|
||||
#if (defined(__cplusplus) && __cplusplus >= 201402L)
|
||||
#define JSONCONS_DEPRECATED_MSG(msg) [[deprecated(msg)]]
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCONS_DEPRECATED_MSG) && defined(__GNUC__) && defined(__has_extension)
|
||||
#if __has_extension(attribute_deprecated_with_message)
|
||||
#define JSONCONS_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCONS_DEPRECATED_MSG) && defined(_MSC_VER)
|
||||
#if (_MSC_VER) >= 1920
|
||||
#define JSONCONS_DEPRECATED_MSG(msg) [[deprecated(msg)]]
|
||||
#else
|
||||
#define JSONCONS_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Following boost/atomic/detail/config.hpp
|
||||
#if !defined(JSONCONS_DEPRECATED_MSG) && (\
|
||||
(defined(__GNUC__) && ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0)) >= 405) ||\
|
||||
(defined(__SUNPRO_CC) && (__SUNPRO_CC + 0) >= 0x5130))
|
||||
#define JSONCONS_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCONS_DEPRECATED_MSG) && defined(__clang__) && defined(__has_extension)
|
||||
#if __has_extension(attribute_deprecated_with_message)
|
||||
#define JSONCONS_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
|
||||
#else
|
||||
#define JSONCONS_DEPRECATED_MSG(msg) __attribute__((deprecated))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCONS_DEPRECATED_MSG)
|
||||
#define JSONCONS_DEPRECATED_MSG(msg)
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID) || defined(__ANDROID__)
|
||||
#if __ANDROID_API__ >= 21
|
||||
#define JSONCONS_HAS_STRTOLD_L
|
||||
#else
|
||||
#define JSONCONS_NO_LOCALECONV
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define JSONCONS_HAS_MSC_STRTOD_L
|
||||
#define JSONCONS_HAS_FOPEN_S
|
||||
#endif
|
||||
|
||||
#ifndef JSONCONS_HAS_CP14
|
||||
#if defined(_MSVC_LANG)
|
||||
#if _MSVC_LANG >= 201402L
|
||||
#define JSONCONS_HAS_CP14
|
||||
#endif
|
||||
#elif __cplusplus >= 201402L
|
||||
#define JSONCONS_HAS_CP14
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(JSONCONS_HAS_STD_FROM_CHARS) && JSONCONS_HAS_STD_FROM_CHARS
|
||||
#include <charconv>
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCONS_HAS_2017)
|
||||
# if defined(__clang__)
|
||||
# if (__cplusplus >= 201703)
|
||||
# define JSONCONS_HAS_2017 1
|
||||
# endif // (__cplusplus >= 201703)
|
||||
# endif // defined(__clang__)
|
||||
# if defined(__GNUC__)
|
||||
# if (__GNUC__ >= 7)
|
||||
# if (__cplusplus >= 201703)
|
||||
# define JSONCONS_HAS_2017 1
|
||||
# endif // (__cplusplus >= 201703)
|
||||
# endif // (__GNUC__ >= 7)
|
||||
# endif // defined(__GNUC__)
|
||||
# if defined(_MSC_VER)
|
||||
# if (_MSC_VER >= 1910 && _MSVC_LANG >= 201703)
|
||||
# define JSONCONS_HAS_2017 1
|
||||
# endif // (_MSC_VER >= 1910 && MSVC_LANG >= 201703)
|
||||
# endif // defined(_MSC_VER)
|
||||
#endif
|
||||
|
||||
#if defined(JSONCONS_HAS_2017)
|
||||
#define JSONCONS_NODISCARD [[nodiscard]]
|
||||
#define JSONCONS_IF_CONSTEXPR if constexpr
|
||||
#else
|
||||
#define JSONCONS_NODISCARD
|
||||
#define JSONCONS_IF_CONSTEXPR if
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCONS_HAS_STD_STRING_VIEW)
|
||||
# if (defined JSONCONS_HAS_2017)
|
||||
# if defined(__clang__)
|
||||
# if __has_include(<string_view>)
|
||||
# define JSONCONS_HAS_STD_STRING_VIEW 1
|
||||
# endif // __has_include(<string_view>)
|
||||
# else
|
||||
# define JSONCONS_HAS_STD_STRING_VIEW 1
|
||||
# endif
|
||||
# endif // defined(JSONCONS_HAS_2017)
|
||||
#endif // !defined(JSONCONS_HAS_STD_STRING_VIEW)
|
||||
|
||||
#if !defined(JSONCONS_HAS_STD_BYTE)
|
||||
# if (defined JSONCONS_HAS_2017)
|
||||
# define JSONCONS_HAS_STD_BYTE 1
|
||||
# endif // defined(JSONCONS_HAS_2017)
|
||||
#endif // !defined(JSONCONS_HAS_STD_BYTE)
|
||||
|
||||
#if !defined(JSONCONS_HAS_STD_OPTIONAL)
|
||||
# if (defined JSONCONS_HAS_2017)
|
||||
# if defined(__clang__)
|
||||
# if __has_include(<optional>)
|
||||
# define JSONCONS_HAS_STD_OPTIONAL 1
|
||||
# endif // __has_include(<string_view>)
|
||||
# else
|
||||
# define JSONCONS_HAS_STD_OPTIONAL 1
|
||||
# endif
|
||||
# endif // defined(JSONCONS_HAS_2017)
|
||||
#endif // !defined(JSONCONS_HAS_STD_OPTIONAL)
|
||||
|
||||
#if !defined(JSONCONS_HAS_STD_VARIANT)
|
||||
# if (defined JSONCONS_HAS_2017)
|
||||
# if defined(__clang__)
|
||||
# if defined(__APPLE__)
|
||||
# if JSONCONS_CLANG_VERSION >= 100001
|
||||
# define JSONCONS_HAS_STD_VARIANT 1
|
||||
# endif
|
||||
# elif __has_include(<variant>)
|
||||
# define JSONCONS_HAS_STD_VARIANT 1
|
||||
# endif // __has_include(<variant>)
|
||||
# else
|
||||
# define JSONCONS_HAS_STD_VARIANT 1
|
||||
# endif
|
||||
# endif // defined(JSONCONS_HAS_2017)
|
||||
#endif // !defined(JSONCONS_HAS_STD_VARIANT)
|
||||
|
||||
#if !defined(JSONCONS_HAS_FILESYSTEM)
|
||||
# if (defined JSONCONS_HAS_2017)
|
||||
# if defined(__clang__)
|
||||
# if __has_include(<filesystem>)
|
||||
# define JSONCONS_HAS_FILESYSTEM 1
|
||||
# endif // __has_include(<filesystem>)
|
||||
# else
|
||||
# define JSONCONS_HAS_FILESYSTEM 1
|
||||
# endif
|
||||
# endif // defined(JSONCONS_HAS_2017)
|
||||
#endif // !defined(JSONCONS_HAS_FILESYSTEM)
|
||||
|
||||
#if (!defined(JSONCONS_NO_EXCEPTIONS))
|
||||
// Check if exceptions are disabled.
|
||||
# if defined( __cpp_exceptions) && __cpp_exceptions == 0
|
||||
# define JSONCONS_NO_EXCEPTIONS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCONS_NO_EXCEPTIONS)
|
||||
|
||||
#if defined(__GNUC__) && !__EXCEPTIONS
|
||||
# define JSONCONS_NO_EXCEPTIONS 1
|
||||
#elif _MSC_VER
|
||||
#if defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS == 0
|
||||
# define JSONCONS_NO_EXCEPTIONS 1
|
||||
#elif !defined(_CPPUNWIND)
|
||||
# define JSONCONS_NO_EXCEPTIONS 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// allow to disable exceptions
|
||||
#if !defined(JSONCONS_NO_EXCEPTIONS)
|
||||
#define JSONCONS_THROW(exception) throw exception
|
||||
#define JSONCONS_RETHROW throw
|
||||
#define JSONCONS_TRY try
|
||||
#define JSONCONS_CATCH(exception) catch(exception)
|
||||
#else
|
||||
#define JSONCONS_THROW(exception) std::terminate()
|
||||
#define JSONCONS_RETHROW std::terminate()
|
||||
#define JSONCONS_TRY if (true)
|
||||
#define JSONCONS_CATCH(exception) if (false)
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCONS_HAS_STD_MAKE_UNIQUE)
|
||||
#if defined(__clang__) && defined(__cplusplus)
|
||||
#if defined(__APPLE__)
|
||||
#if __clang_major__ >= 6 && __cplusplus >= 201402L // Xcode 6
|
||||
#define JSONCONS_HAS_STD_MAKE_UNIQUE
|
||||
#endif
|
||||
#elif ((__clang_major__*100 +__clang_minor__) >= 340) && __cplusplus >= 201402L
|
||||
#define JSONCONS_HAS_STD_MAKE_UNIQUE
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L
|
||||
#define JSONCONS_HAS_STD_MAKE_UNIQUE
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#if _MSC_VER >= 1800
|
||||
#define JSONCONS_HAS_STD_MAKE_UNIQUE
|
||||
#endif
|
||||
#endif
|
||||
#endif // !defined(JSONCONS_HAS_STD_MAKE_UNIQUE)
|
||||
|
||||
#ifndef JSONCONS_HAS_CP14_CONSTEXPR
|
||||
#if defined(_MSC_VER)
|
||||
#if _MSC_VER >= 1910
|
||||
#define JSONCONS_HAS_CP14_CONSTEXPR
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 600 && __cplusplus >= 201402L
|
||||
#define JSONCONS_HAS_CP14_CONSTEXPR
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(JSONCONS_HAS_CP14_CONSTEXPR)
|
||||
# define JSONCONS_CPP14_CONSTEXPR constexpr
|
||||
#else
|
||||
# define JSONCONS_CPP14_CONSTEXPR
|
||||
#endif
|
||||
|
||||
// Follows boost
|
||||
|
||||
// gcc and clang
|
||||
#if (defined(__clang__) || defined(__GNUC__)) && defined(__cplusplus)
|
||||
#if defined(__SIZEOF_INT128__) && !defined(_MSC_VER)
|
||||
# define JSONCONS_HAS_INT128
|
||||
#endif
|
||||
|
||||
#if (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC)
|
||||
#if (__clang_major__ >= 4) && defined(__has_include)
|
||||
#if __has_include(<quadmath.h>)
|
||||
# define JSONCONS_HAS_FLOAT128
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if defined(_GLIBCXX_USE_FLOAT128)
|
||||
# define JSONCONS_HAS_FLOAT128
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
#if (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC)
|
||||
#if (__clang_major__ >= 4) && defined(__has_include)
|
||||
#if __has_include(<quadmath.h>)
|
||||
# define JSONCONS_HAS_FLOAT128
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Follows boost config/detail/suffix.hpp
|
||||
#if defined(JSONCONS_HAS_INT128) && defined(__cplusplus)
|
||||
namespace jsoncons{
|
||||
# ifdef __GNUC__
|
||||
__extension__ typedef __int128 int128_type;
|
||||
__extension__ typedef unsigned __int128 uint128_type;
|
||||
# else
|
||||
typedef __int128 int128_type;
|
||||
typedef unsigned __int128 uint128_type;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
#if defined(JSONCONS_HAS_FLOAT128) && defined(__cplusplus)
|
||||
namespace jsoncons {
|
||||
# ifdef __GNUC__
|
||||
__extension__ typedef __float128 float128_type;
|
||||
# else
|
||||
typedef __float128 float128_type;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1900
|
||||
#define JSONCONS_COPY(first,last,d_first) std::copy(first, last, stdext::make_checked_array_iterator(d_first, static_cast<std::size_t>(std::distance(first, last))))
|
||||
#else
|
||||
#define JSONCONS_COPY(first,last,d_first) std::copy(first, last, d_first)
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1900
|
||||
#define JSONCONS_CONSTEXPR
|
||||
#else
|
||||
#define JSONCONS_CONSTEXPR constexpr
|
||||
#endif
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
class assertion_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
assertion_error(const std::string& s) noexcept
|
||||
: std::runtime_error(s)
|
||||
{
|
||||
}
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return std::runtime_error::what();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#define JSONCONS_STR2(x) #x
|
||||
#define JSONCONS_STR(x) JSONCONS_STR2(x)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define JSONCONS_ASSERT(x) if (!(x)) { \
|
||||
JSONCONS_THROW(jsoncons::assertion_error("assertion '" #x "' failed at " __FILE__ ":" \
|
||||
JSONCONS_STR(__LINE__))); }
|
||||
#else
|
||||
#define JSONCONS_ASSERT(x) if (!(x)) { \
|
||||
JSONCONS_THROW(jsoncons::assertion_error("assertion '" #x "' failed at <> :" \
|
||||
JSONCONS_STR( 0 ))); }
|
||||
#endif // _DEBUG
|
||||
|
||||
#endif // JSONCONS_COMPILER_SUPPORT_HPP
|
||||
313
scripts/exe/jsoncons/include/jsoncons/config/jsoncons_config.hpp
Normal file
313
scripts/exe/jsoncons/include/jsoncons/config/jsoncons_config.hpp
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CONFIG_JSONCONS_CONFIG_HPP
|
||||
#define JSONCONS_CONFIG_JSONCONS_CONFIG_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <jsoncons/config/compiler_support.hpp>
|
||||
#include <jsoncons/config/binary_config.hpp>
|
||||
|
||||
#if !defined(JSONCONS_HAS_STD_STRING_VIEW)
|
||||
#include <jsoncons/detail/string_view.hpp>
|
||||
namespace jsoncons {
|
||||
using jsoncons::detail::basic_string_view;
|
||||
using string_view = basic_string_view<char, std::char_traits<char>>;
|
||||
using wstring_view = basic_string_view<wchar_t, std::char_traits<wchar_t>>;
|
||||
}
|
||||
#else
|
||||
#include <string_view>
|
||||
namespace jsoncons {
|
||||
using std::basic_string_view;
|
||||
using std::string_view;
|
||||
using std::wstring_view;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCONS_HAS_STD_SPAN)
|
||||
#include <jsoncons/detail/span.hpp>
|
||||
namespace jsoncons {
|
||||
using jsoncons::detail::span;
|
||||
}
|
||||
#else
|
||||
#include <span>
|
||||
namespace jsoncons {
|
||||
using std::span;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(JSONCONS_HAS_STD_OPTIONAL)
|
||||
#include <optional>
|
||||
namespace jsoncons {
|
||||
using std::optional;
|
||||
}
|
||||
#elif defined(JSONCONS_HAS_BOOST_OPTIONAL)
|
||||
#include <boost/optional.hpp>
|
||||
namespace jsoncons {
|
||||
using boost::optional;
|
||||
}
|
||||
#else
|
||||
#include <jsoncons/detail/optional.hpp>
|
||||
namespace jsoncons {
|
||||
using jsoncons::detail::optional;
|
||||
}
|
||||
#endif // !defined(JSONCONS_HAS_STD_OPTIONAL)
|
||||
|
||||
#if !defined(JSONCONS_HAS_STD_ENDIAN)
|
||||
#include <jsoncons/detail/endian.hpp>
|
||||
namespace jsoncons {
|
||||
using jsoncons::detail::endian;
|
||||
}
|
||||
#else
|
||||
#include <bit>
|
||||
namespace jsoncons
|
||||
{
|
||||
using std::endian;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(JSONCONS_HAS_STD_MAKE_UNIQUE)
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
template<class T>
|
||||
struct unique_if
|
||||
{
|
||||
using value_is_not_array = std::unique_ptr<T>;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct unique_if<T[]>
|
||||
{
|
||||
typedef std::unique_ptr<T[]> value_is_array_of_unknown_bound;
|
||||
};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct unique_if<T[N]> {
|
||||
using value_is_array_of_known_bound = void;
|
||||
};
|
||||
|
||||
template<class T, class... Args>
|
||||
typename unique_if<T>::value_is_not_array
|
||||
make_unique(Args&&... args)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename unique_if<T>::value_is_array_of_unknown_bound
|
||||
make_unique(std::size_t n)
|
||||
{
|
||||
using U = typename std::remove_extent<T>::type;
|
||||
return std::unique_ptr<T>(new U[n]());
|
||||
}
|
||||
|
||||
template<class T, class... Args>
|
||||
typename unique_if<T>::value_is_array_of_known_bound
|
||||
make_unique(Args&&...) = delete;
|
||||
} // jsoncons
|
||||
|
||||
#else
|
||||
|
||||
#include <memory>
|
||||
namespace jsoncons
|
||||
{
|
||||
using std::make_unique;
|
||||
}
|
||||
|
||||
#endif // !defined(JSONCONS_HAS_STD_MAKE_UNIQUE)
|
||||
|
||||
namespace jsoncons {
|
||||
namespace binary {
|
||||
|
||||
// native_to_big
|
||||
|
||||
template<typename T, class OutputIt, class Endian=endian>
|
||||
typename std::enable_if<Endian::native == Endian::big,void>::type
|
||||
native_to_big(T val, OutputIt d_first)
|
||||
{
|
||||
uint8_t buf[sizeof(T)];
|
||||
std::memcpy(buf, &val, sizeof(T));
|
||||
for (auto item : buf)
|
||||
{
|
||||
*d_first++ = item;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, class OutputIt, class Endian=endian>
|
||||
typename std::enable_if<Endian::native == Endian::little,void>::type
|
||||
native_to_big(T val, OutputIt d_first)
|
||||
{
|
||||
T val2 = byte_swap(val);
|
||||
uint8_t buf[sizeof(T)];
|
||||
std::memcpy(buf, &val2, sizeof(T));
|
||||
for (auto item : buf)
|
||||
{
|
||||
*d_first++ = item;
|
||||
}
|
||||
}
|
||||
|
||||
// native_to_little
|
||||
|
||||
template<typename T, class OutputIt, class Endian = endian>
|
||||
typename std::enable_if<Endian::native == Endian::little,void>::type
|
||||
native_to_little(T val, OutputIt d_first)
|
||||
{
|
||||
uint8_t buf[sizeof(T)];
|
||||
std::memcpy(buf, &val, sizeof(T));
|
||||
for (auto item : buf)
|
||||
{
|
||||
*d_first++ = item;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, class OutputIt, class Endian=endian>
|
||||
typename std::enable_if<Endian::native == Endian::big, void>::type
|
||||
native_to_little(T val, OutputIt d_first)
|
||||
{
|
||||
T val2 = byte_swap(val);
|
||||
uint8_t buf[sizeof(T)];
|
||||
std::memcpy(buf, &val2, sizeof(T));
|
||||
for (auto item : buf)
|
||||
{
|
||||
*d_first++ = item;
|
||||
}
|
||||
}
|
||||
|
||||
// big_to_native
|
||||
|
||||
template<class T,class Endian=endian>
|
||||
typename std::enable_if<Endian::native == Endian::big,T>::type
|
||||
big_to_native(const uint8_t* first, std::size_t count)
|
||||
{
|
||||
if (sizeof(T) > count)
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
T val;
|
||||
std::memcpy(&val,first,sizeof(T));
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T,class Endian=endian>
|
||||
typename std::enable_if<Endian::native == Endian::little,T>::type
|
||||
big_to_native(const uint8_t* first, std::size_t count)
|
||||
{
|
||||
if (sizeof(T) > count)
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
T val;
|
||||
std::memcpy(&val,first,sizeof(T));
|
||||
return byte_swap(val);
|
||||
}
|
||||
|
||||
// little_to_native
|
||||
|
||||
template<class T,class Endian=endian>
|
||||
typename std::enable_if<Endian::native == Endian::little,T>::type
|
||||
little_to_native(const uint8_t* first, std::size_t count)
|
||||
{
|
||||
if (sizeof(T) > count)
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
T val;
|
||||
std::memcpy(&val,first,sizeof(T));
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T,class Endian=endian>
|
||||
typename std::enable_if<Endian::native == Endian::big,T>::type
|
||||
little_to_native(const uint8_t* first, std::size_t count)
|
||||
{
|
||||
if (sizeof(T) > count)
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
T val;
|
||||
std::memcpy(&val,first,sizeof(T));
|
||||
return byte_swap(val);
|
||||
}
|
||||
|
||||
} // binary
|
||||
} // jsoncons
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
template<typename CharT>
|
||||
constexpr const CharT* cstring_constant_of_type(const char* c, const wchar_t* w);
|
||||
|
||||
template<> inline
|
||||
constexpr const char* cstring_constant_of_type<char>(const char* c, const wchar_t*)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
template<> inline
|
||||
constexpr const wchar_t* cstring_constant_of_type<wchar_t>(const char*, const wchar_t* w)
|
||||
{
|
||||
return w;
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
std::basic_string<CharT> string_constant_of_type(const char* c, const wchar_t* w);
|
||||
|
||||
template<> inline
|
||||
std::string string_constant_of_type<char>(const char* c, const wchar_t*)
|
||||
{
|
||||
return std::string(c);
|
||||
}
|
||||
template<> inline
|
||||
std::wstring string_constant_of_type<wchar_t>(const char*, const wchar_t* w)
|
||||
{
|
||||
return std::wstring(w);
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
jsoncons::basic_string_view<CharT> string_view_constant_of_type(const char* c, const wchar_t* w);
|
||||
|
||||
template<> inline
|
||||
jsoncons::string_view string_view_constant_of_type<char>(const char* c, const wchar_t*)
|
||||
{
|
||||
return jsoncons::string_view(c);
|
||||
}
|
||||
template<> inline
|
||||
jsoncons::wstring_view string_view_constant_of_type<wchar_t>(const char*, const wchar_t* w)
|
||||
{
|
||||
return jsoncons::wstring_view(w);
|
||||
}
|
||||
|
||||
} // jsoncons
|
||||
|
||||
#define JSONCONS_EXPAND(X) X
|
||||
#define JSONCONS_QUOTE(Prefix, A) JSONCONS_EXPAND(Prefix ## #A)
|
||||
#define JSONCONS_WIDEN(A) JSONCONS_EXPAND(L ## A)
|
||||
|
||||
#define JSONCONS_CSTRING_CONSTANT(CharT, Str) cstring_constant_of_type<CharT>(Str, JSONCONS_WIDEN(Str))
|
||||
#define JSONCONS_STRING_CONSTANT(CharT, Str) string_constant_of_type<CharT>(Str, JSONCONS_WIDEN(Str))
|
||||
#define JSONCONS_STRING_VIEW_CONSTANT(CharT, Str) string_view_constant_of_type<CharT>(Str, JSONCONS_WIDEN(Str))
|
||||
|
||||
#if defined(__clang__)
|
||||
#define JSONCONS_HAS_STD_REGEX 1
|
||||
#define JSONCONS_HAS_STATEFUL_ALLOCATOR 1
|
||||
#elif (defined(__GNUC__) && (__GNUC__ == 4)) && (defined(__GNUC__) && __GNUC_MINOR__ < 9)
|
||||
// GCC 4.8 has broken regex support: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631
|
||||
// gcc 4.8 basic_string doesn't satisfy C++11 allocator requirements
|
||||
// and gcc doesn't support allocators with no default constructor
|
||||
#else
|
||||
#define JSONCONS_HAS_STD_REGEX 1
|
||||
#define JSONCONS_HAS_STATEFUL_ALLOCATOR 1
|
||||
#endif
|
||||
|
||||
#endif // JSONCONS_CONFIG_JSONCONS_CONFIG_HPP
|
||||
|
||||
|
||||
40
scripts/exe/jsoncons/include/jsoncons/config/version.hpp
Normal file
40
scripts/exe/jsoncons/include/jsoncons/config/version.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_VERSION_HPP
|
||||
#define JSONCONS_VERSION_HPP
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define JSONCONS_VERSION_MAJOR 0
|
||||
#define JSONCONS_VERSION_MINOR 170
|
||||
#define JSONCONS_VERSION_PATCH 2
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
struct versioning_info
|
||||
{
|
||||
unsigned int const major;
|
||||
unsigned int const minor;
|
||||
unsigned int const patch;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const versioning_info& ver)
|
||||
{
|
||||
os << ver.major << '.'
|
||||
<< ver.minor << '.'
|
||||
<< ver.patch;
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr versioning_info version()
|
||||
{
|
||||
return versioning_info{JSONCONS_VERSION_MAJOR, JSONCONS_VERSION_MINOR, JSONCONS_VERSION_PATCH};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
218
scripts/exe/jsoncons/include/jsoncons/conv_error.hpp
Normal file
218
scripts/exe/jsoncons/include/jsoncons/conv_error.hpp
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
/// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CONV_ERROR_HPP
|
||||
#define JSONCONS_CONV_ERROR_HPP
|
||||
|
||||
#include <system_error>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
class conv_error : public std::system_error, public virtual json_exception
|
||||
{
|
||||
std::size_t line_number_;
|
||||
std::size_t column_number_;
|
||||
mutable std::string what_;
|
||||
public:
|
||||
conv_error(std::error_code ec)
|
||||
: std::system_error(ec), line_number_(0), column_number_(0)
|
||||
{
|
||||
}
|
||||
conv_error(std::error_code ec, const std::string& what_arg)
|
||||
: std::system_error(ec, what_arg), line_number_(0), column_number_(0)
|
||||
{
|
||||
}
|
||||
conv_error(std::error_code ec, std::size_t position)
|
||||
: std::system_error(ec), line_number_(0), column_number_(position)
|
||||
{
|
||||
}
|
||||
conv_error(std::error_code ec, std::size_t line, std::size_t column)
|
||||
: std::system_error(ec), line_number_(line), column_number_(column)
|
||||
{
|
||||
}
|
||||
conv_error(const conv_error& other) = default;
|
||||
|
||||
conv_error(conv_error&& other) = default;
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
if (what_.empty())
|
||||
{
|
||||
JSONCONS_TRY
|
||||
{
|
||||
what_.append(std::system_error::what());
|
||||
if (line_number_ != 0 && column_number_ != 0)
|
||||
{
|
||||
what_.append(" at line ");
|
||||
what_.append(std::to_string(line_number_));
|
||||
what_.append(" and column ");
|
||||
what_.append(std::to_string(column_number_));
|
||||
}
|
||||
else if (column_number_ != 0)
|
||||
{
|
||||
what_.append(" at position ");
|
||||
what_.append(std::to_string(column_number_));
|
||||
}
|
||||
return what_.c_str();
|
||||
}
|
||||
JSONCONS_CATCH(...)
|
||||
{
|
||||
return std::system_error::what();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return what_.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t line() const noexcept
|
||||
{
|
||||
return line_number_;
|
||||
}
|
||||
|
||||
std::size_t column() const noexcept
|
||||
{
|
||||
return column_number_;
|
||||
}
|
||||
};
|
||||
|
||||
enum class conv_errc
|
||||
{
|
||||
success = 0,
|
||||
conversion_failed,
|
||||
not_utf8,
|
||||
not_wide_char,
|
||||
not_vector,
|
||||
not_array,
|
||||
not_map,
|
||||
not_pair,
|
||||
not_string,
|
||||
not_string_view,
|
||||
not_byte_string,
|
||||
not_byte_string_view,
|
||||
not_integer,
|
||||
not_signed_integer,
|
||||
not_unsigned_integer,
|
||||
not_bigint,
|
||||
not_double,
|
||||
not_bool,
|
||||
not_variant,
|
||||
not_nullptr,
|
||||
not_jsoncons_null_type,
|
||||
not_bitset,
|
||||
not_base64,
|
||||
not_base64url,
|
||||
not_base16
|
||||
};
|
||||
|
||||
template <class InputIt>
|
||||
struct decode_result
|
||||
{
|
||||
InputIt it;
|
||||
conv_errc ec;
|
||||
};
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use conv_error") typedef conv_error convert_error;
|
||||
#endif
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct is_error_code_enum<jsoncons::conv_errc> : public true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
namespace detail {
|
||||
class conv_error_category_impl
|
||||
: public std::error_category
|
||||
{
|
||||
public:
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "jsoncons/convert";
|
||||
}
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<conv_errc>(ev))
|
||||
{
|
||||
case conv_errc::conversion_failed:
|
||||
return "Unable to convert into the provided type";
|
||||
case conv_errc::not_utf8:
|
||||
return "Cannot convert string to UTF-8";
|
||||
case conv_errc::not_wide_char:
|
||||
return "Cannot convert string to wide characters";
|
||||
case conv_errc::not_vector:
|
||||
return "Cannot convert to vector";
|
||||
case conv_errc::not_array:
|
||||
return "Cannot convert to std::array";
|
||||
case conv_errc::not_map:
|
||||
return "Cannot convert to map";
|
||||
case conv_errc::not_pair:
|
||||
return "Cannot convert to std::pair";
|
||||
case conv_errc::not_string:
|
||||
return "Cannot convert to string";
|
||||
case conv_errc::not_string_view:
|
||||
return "Cannot convert to string_view";
|
||||
case conv_errc::not_byte_string:
|
||||
return "Cannot convert to byte_string";
|
||||
case conv_errc::not_byte_string_view:
|
||||
return "Cannot convert to byte_string_view";
|
||||
case conv_errc::not_integer:
|
||||
return "Cannot convert to integer";
|
||||
case conv_errc::not_signed_integer:
|
||||
return "Cannot convert to signed integer";
|
||||
case conv_errc::not_unsigned_integer:
|
||||
return "Cannot convert to unsigned integer";
|
||||
case conv_errc::not_bigint:
|
||||
return "Cannot convert to bigint";
|
||||
case conv_errc::not_double:
|
||||
return "Cannot convert to double";
|
||||
case conv_errc::not_bool:
|
||||
return "Cannot convert to bool";
|
||||
case conv_errc::not_variant:
|
||||
return "Cannot convert to std::variant";
|
||||
case conv_errc::not_nullptr:
|
||||
return "Cannot convert to std::nullptr_t";
|
||||
case conv_errc::not_jsoncons_null_type:
|
||||
return "Cannot convert to jsoncons::null_type";
|
||||
case conv_errc::not_bitset:
|
||||
return "Cannot convert to std::bitset";
|
||||
case conv_errc::not_base64:
|
||||
return "Input is not a base64 encoded string";
|
||||
case conv_errc::not_base64url:
|
||||
return "Input is not a base64url encoded string";
|
||||
case conv_errc::not_base16:
|
||||
return "Input is not a base16 encoded string";
|
||||
default:
|
||||
return "Unknown conversion error";
|
||||
}
|
||||
}
|
||||
};
|
||||
} // detail
|
||||
|
||||
extern inline
|
||||
const std::error_category& conv_error_category()
|
||||
{
|
||||
static detail::conv_error_category_impl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
inline
|
||||
std::error_code make_error_code(conv_errc result)
|
||||
{
|
||||
return std::error_code(static_cast<int>(result),conv_error_category());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
209
scripts/exe/jsoncons/include/jsoncons/decode_json.hpp
Normal file
209
scripts/exe/jsoncons/include/jsoncons/decode_json.hpp
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_DECODE_JSON_HPP
|
||||
#define JSONCONS_DECODE_JSON_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <memory>
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/decode_traits.hpp>
|
||||
#include <jsoncons/json_cursor.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// decode_json
|
||||
|
||||
template <class T, class Source>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_sequence_of<Source,typename T::char_type>::value,T>::type
|
||||
decode_json(const Source& s,
|
||||
const basic_json_decode_options<typename Source::value_type>& options = basic_json_decode_options<typename Source::value_type>())
|
||||
{
|
||||
using char_type = typename Source::value_type;
|
||||
|
||||
jsoncons::json_decoder<T> decoder;
|
||||
basic_json_reader<char_type, string_source<char_type>> reader(s, decoder, options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template <class T, class Source>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_char_sequence<Source>::value,T>::type
|
||||
decode_json(const Source& s,
|
||||
const basic_json_decode_options<typename Source::value_type>& options = basic_json_decode_options<typename Source::value_type>())
|
||||
{
|
||||
using char_type = typename Source::value_type;
|
||||
|
||||
basic_json_cursor<char_type,string_source<char_type>> cursor(s, options, default_json_parsing());
|
||||
jsoncons::json_decoder<basic_json<char_type>> decoder;
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char_type>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T, class CharT>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_json(std::basic_istream<CharT>& is,
|
||||
const basic_json_decode_options<CharT>& options = basic_json_decode_options<CharT>())
|
||||
{
|
||||
jsoncons::json_decoder<T> decoder;
|
||||
basic_json_reader<CharT, stream_source<CharT>> reader(is, decoder, options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template <class T, class CharT>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_json(std::basic_istream<CharT>& is,
|
||||
const basic_json_decode_options<CharT>& options = basic_json_decode_options<CharT>())
|
||||
{
|
||||
basic_json_cursor<CharT> cursor(is, options, default_json_parsing());
|
||||
json_decoder<basic_json<CharT>> decoder{};
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,CharT>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.line(), cursor.column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T, class InputIt>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_json(InputIt first, InputIt last,
|
||||
const basic_json_decode_options<typename std::iterator_traits<InputIt>::value_type>& options =
|
||||
basic_json_decode_options<typename std::iterator_traits<InputIt>::value_type>())
|
||||
{
|
||||
using char_type = typename std::iterator_traits<InputIt>::value_type;
|
||||
|
||||
jsoncons::json_decoder<T> decoder;
|
||||
basic_json_reader<char_type, iterator_source<InputIt>> reader(iterator_source<InputIt>(first,last), decoder, options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template <class T, class InputIt>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_json(InputIt first, InputIt last,
|
||||
const basic_json_decode_options<typename std::iterator_traits<InputIt>::value_type>& options =
|
||||
basic_json_decode_options<typename std::iterator_traits<InputIt>::value_type>())
|
||||
{
|
||||
using char_type = typename std::iterator_traits<InputIt>::value_type;
|
||||
|
||||
basic_json_cursor<char_type,iterator_source<InputIt>> cursor(iterator_source<InputIt>(first, last), options, default_json_parsing());
|
||||
jsoncons::json_decoder<basic_json<char_type>> decoder;
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char_type>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.line(), cursor.column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// With leading allocator parameter
|
||||
|
||||
template <class T,class Source,class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_sequence_of<Source,typename T::char_type>::value,T>::type
|
||||
decode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const Source& s,
|
||||
const basic_json_decode_options<typename Source::value_type>& options = basic_json_decode_options<typename Source::value_type>())
|
||||
{
|
||||
using char_type = typename Source::value_type;
|
||||
|
||||
json_decoder<T,TempAllocator> decoder(temp_alloc);
|
||||
|
||||
basic_json_reader<char_type, string_source<char_type>,TempAllocator> reader(s, decoder, options, temp_alloc);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template <class T,class Source,class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_char_sequence<Source>::value,T>::type
|
||||
decode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const Source& s,
|
||||
const basic_json_decode_options<typename Source::value_type>& options = basic_json_decode_options<typename Source::value_type>())
|
||||
{
|
||||
using char_type = typename Source::value_type;
|
||||
|
||||
basic_json_cursor<char_type,string_source<char_type>,TempAllocator> cursor(s, options, default_json_parsing(), temp_alloc);
|
||||
json_decoder<basic_json<char_type,sorted_policy,TempAllocator>,TempAllocator> decoder(result_allocator_arg, temp_alloc, temp_alloc);
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char_type>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T,class CharT,class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
std::basic_istream<CharT>& is,
|
||||
const basic_json_decode_options<CharT>& options = basic_json_decode_options<CharT>())
|
||||
{
|
||||
json_decoder<T,TempAllocator> decoder(temp_alloc);
|
||||
|
||||
basic_json_reader<CharT, stream_source<CharT>,TempAllocator> reader(is, decoder, options, temp_alloc);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template <class T,class CharT,class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
std::basic_istream<CharT>& is,
|
||||
const basic_json_decode_options<CharT>& options = basic_json_decode_options<CharT>())
|
||||
{
|
||||
basic_json_cursor<CharT,stream_source<CharT>,TempAllocator> cursor(is, options, default_json_parsing(), temp_alloc);
|
||||
json_decoder<basic_json<CharT,sorted_policy,TempAllocator>,TempAllocator> decoder(result_allocator_arg, temp_alloc,temp_alloc);
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,CharT>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
} // jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
651
scripts/exe/jsoncons/include/jsoncons/decode_traits.hpp
Normal file
651
scripts/exe/jsoncons/include/jsoncons/decode_traits.hpp
Normal file
|
|
@ -0,0 +1,651 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_DECODE_TRAITS_HPP
|
||||
#define JSONCONS_DECODE_TRAITS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <type_traits> // std::enable_if, std::true_type, std::false_type
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/json_decoder.hpp>
|
||||
#include <jsoncons/json_type_traits.hpp>
|
||||
#include <jsoncons/staj_cursor.hpp>
|
||||
#include <jsoncons/conv_error.hpp>
|
||||
#include <jsoncons/extension_traits.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// decode_traits
|
||||
|
||||
template <class T, class CharT, class Enable = void>
|
||||
struct decode_traits
|
||||
{
|
||||
template <class Json,class TempAllocator>
|
||||
static T decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>& decoder,
|
||||
std::error_code& ec)
|
||||
{
|
||||
decoder.reset();
|
||||
cursor.read_to(decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
else if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return decoder.get_result().template as<T>();
|
||||
}
|
||||
};
|
||||
|
||||
// specializations
|
||||
|
||||
// primitive
|
||||
|
||||
template <class T, class CharT>
|
||||
struct decode_traits<T,CharT,
|
||||
typename std::enable_if<extension_traits::is_primitive<T>::value
|
||||
>::type>
|
||||
{
|
||||
template <class Json,class TempAllocator>
|
||||
static T decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
T v = cursor.current().template get<T>(ec);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
// string
|
||||
|
||||
template <class T, class CharT>
|
||||
struct decode_traits<T,CharT,
|
||||
typename std::enable_if<extension_traits::is_string<T>::value &&
|
||||
std::is_same<typename T::value_type,CharT>::value
|
||||
>::type>
|
||||
{
|
||||
template <class Json,class TempAllocator>
|
||||
static T decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
T v = cursor.current().template get<T>(ec);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class CharT>
|
||||
struct decode_traits<T,CharT,
|
||||
typename std::enable_if<extension_traits::is_string<T>::value &&
|
||||
!std::is_same<typename T::value_type,CharT>::value
|
||||
>::type>
|
||||
{
|
||||
template <class Json,class TempAllocator>
|
||||
static T decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
auto val = cursor.current().template get<std::basic_string<CharT>>(ec);
|
||||
T s;
|
||||
if (!ec)
|
||||
{
|
||||
unicode_traits::convert(val.data(), val.size(), s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
// std::pair
|
||||
|
||||
template <class T1, class T2, class CharT>
|
||||
struct decode_traits<std::pair<T1, T2>, CharT>
|
||||
{
|
||||
template <class Json, class TempAllocator>
|
||||
static std::pair<T1, T2> decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json, TempAllocator>& decoder,
|
||||
std::error_code& ec)
|
||||
{
|
||||
using value_type = std::pair<T1, T2>;
|
||||
cursor.array_expected(ec);
|
||||
if (ec)
|
||||
{
|
||||
return value_type{};
|
||||
}
|
||||
if (cursor.current().event_type() != staj_event_type::begin_array)
|
||||
{
|
||||
ec = conv_errc::not_pair;
|
||||
return value_type();
|
||||
}
|
||||
cursor.next(ec); // skip past array
|
||||
if (ec)
|
||||
{
|
||||
return value_type();
|
||||
}
|
||||
|
||||
T1 v1 = decode_traits<T1,CharT>::decode(cursor, decoder, ec);
|
||||
if (ec) {return value_type();}
|
||||
cursor.next(ec);
|
||||
if (ec) {return value_type();}
|
||||
T2 v2 = decode_traits<T2, CharT>::decode(cursor, decoder, ec);
|
||||
if (ec) {return value_type();}
|
||||
cursor.next(ec);
|
||||
|
||||
if (cursor.current().event_type() != staj_event_type::end_array)
|
||||
{
|
||||
ec = conv_errc::not_pair;
|
||||
return value_type();
|
||||
}
|
||||
return std::make_pair(v1, v2);
|
||||
}
|
||||
};
|
||||
|
||||
// vector like
|
||||
template <class T, class CharT>
|
||||
struct decode_traits<T,CharT,
|
||||
typename std::enable_if<!is_json_type_traits_declared<T>::value &&
|
||||
extension_traits::is_list_like<T>::value &&
|
||||
extension_traits::is_back_insertable<T>::value &&
|
||||
!extension_traits::is_typed_array<T>::value
|
||||
>::type>
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
|
||||
template <class Json,class TempAllocator>
|
||||
static T decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>& decoder,
|
||||
std::error_code& ec)
|
||||
{
|
||||
T v;
|
||||
|
||||
cursor.array_expected(ec);
|
||||
if (ec)
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
if (cursor.current().event_type() != staj_event_type::begin_array)
|
||||
{
|
||||
ec = conv_errc::not_vector;
|
||||
return v;
|
||||
}
|
||||
cursor.next(ec);
|
||||
while (cursor.current().event_type() != staj_event_type::end_array && !ec)
|
||||
{
|
||||
v.push_back(decode_traits<value_type,CharT>::decode(cursor, decoder, ec));
|
||||
if (ec) {return T{};}
|
||||
cursor.next(ec);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct typed_array_visitor : public default_json_visitor
|
||||
{
|
||||
T& v_;
|
||||
int level_;
|
||||
public:
|
||||
using value_type = typename T::value_type;
|
||||
|
||||
typed_array_visitor(T& v)
|
||||
: default_json_visitor(false,conv_errc::not_vector), v_(v), level_(0)
|
||||
{
|
||||
}
|
||||
private:
|
||||
bool visit_begin_array(semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (++level_ != 1)
|
||||
{
|
||||
ec = conv_errc::not_vector;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_begin_array(std::size_t size,
|
||||
semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (++level_ != 1)
|
||||
{
|
||||
ec = conv_errc::not_vector;
|
||||
return false;
|
||||
}
|
||||
if (size > 0)
|
||||
{
|
||||
reserve_storage(typename std::integral_constant<bool, extension_traits::has_reserve<T>::value>::type(), v_, size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_end_array(const ser_context&,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (level_ != 1)
|
||||
{
|
||||
ec = conv_errc::not_vector;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool visit_uint64(uint64_t value,
|
||||
semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
v_.push_back(static_cast<value_type>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_int64(int64_t value,
|
||||
semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
v_.push_back(static_cast<value_type>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_half(uint16_t value,
|
||||
semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
return visit_half_(typename std::integral_constant<bool, std::is_integral<value_type>::value>::type(), value);
|
||||
}
|
||||
|
||||
bool visit_half_(std::true_type, uint16_t value)
|
||||
{
|
||||
v_.push_back(static_cast<value_type>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_half_(std::false_type, uint16_t value)
|
||||
{
|
||||
v_.push_back(static_cast<value_type>(binary::decode_half(value)));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_double(double value,
|
||||
semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
v_.push_back(static_cast<value_type>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const value_type>& data,
|
||||
semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
v_ = std::vector<value_type>(data.begin(),data.end());
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
void reserve_storage(std::true_type, T& v, std::size_t new_cap)
|
||||
{
|
||||
v.reserve(new_cap);
|
||||
}
|
||||
|
||||
static
|
||||
void reserve_storage(std::false_type, T&, std::size_t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class CharT>
|
||||
struct decode_traits<T,CharT,
|
||||
typename std::enable_if<!is_json_type_traits_declared<T>::value &&
|
||||
extension_traits::is_list_like<T>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<T>::value &&
|
||||
extension_traits::is_typed_array<T>::value
|
||||
>::type>
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
|
||||
template <class Json,class TempAllocator>
|
||||
static T decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
cursor.array_expected(ec);
|
||||
if (ec)
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
switch (cursor.current().event_type())
|
||||
{
|
||||
case staj_event_type::byte_string_value:
|
||||
{
|
||||
auto bytes = cursor.current().template get<byte_string_view>(ec);
|
||||
if (!ec)
|
||||
{
|
||||
T v;
|
||||
if (cursor.current().size() > 0)
|
||||
{
|
||||
reserve_storage(typename std::integral_constant<bool, extension_traits::has_reserve<T>::value>::type(), v, cursor.current().size());
|
||||
}
|
||||
for (auto ch : bytes)
|
||||
{
|
||||
v.push_back(static_cast<value_type>(ch));
|
||||
}
|
||||
cursor.next(ec);
|
||||
return v;
|
||||
}
|
||||
else
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
}
|
||||
case staj_event_type::begin_array:
|
||||
{
|
||||
T v;
|
||||
if (cursor.current().size() > 0)
|
||||
{
|
||||
reserve_storage(typename std::integral_constant<bool, extension_traits::has_reserve<T>::value>::type(), v, cursor.current().size());
|
||||
}
|
||||
typed_array_visitor<T> visitor(v);
|
||||
cursor.read_to(visitor, ec);
|
||||
return v;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ec = conv_errc::not_vector;
|
||||
return T{};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reserve_storage(std::true_type, T& v, std::size_t new_cap)
|
||||
{
|
||||
v.reserve(new_cap);
|
||||
}
|
||||
|
||||
static void reserve_storage(std::false_type, T&, std::size_t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class CharT>
|
||||
struct decode_traits<T,CharT,
|
||||
typename std::enable_if<!is_json_type_traits_declared<T>::value &&
|
||||
extension_traits::is_list_like<T>::value &&
|
||||
extension_traits::is_back_insertable<T>::value &&
|
||||
!extension_traits::is_back_insertable_byte_container<T>::value &&
|
||||
extension_traits::is_typed_array<T>::value
|
||||
>::type>
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
|
||||
template <class Json,class TempAllocator>
|
||||
static T decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
cursor.array_expected(ec);
|
||||
if (ec)
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
switch (cursor.current().event_type())
|
||||
{
|
||||
case staj_event_type::begin_array:
|
||||
{
|
||||
T v;
|
||||
if (cursor.current().size() > 0)
|
||||
{
|
||||
reserve_storage(typename std::integral_constant<bool, extension_traits::has_reserve<T>::value>::type(), v, cursor.current().size());
|
||||
}
|
||||
typed_array_visitor<T> visitor(v);
|
||||
cursor.read_to(visitor, ec);
|
||||
return v;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ec = conv_errc::not_vector;
|
||||
return T{};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reserve_storage(std::true_type, T& v, std::size_t new_cap)
|
||||
{
|
||||
v.reserve(new_cap);
|
||||
}
|
||||
|
||||
static void reserve_storage(std::false_type, T&, std::size_t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// set like
|
||||
template <class T, class CharT>
|
||||
struct decode_traits<T,CharT,
|
||||
typename std::enable_if<!is_json_type_traits_declared<T>::value &&
|
||||
extension_traits::is_list_like<T>::value &&
|
||||
!extension_traits::is_back_insertable<T>::value &&
|
||||
extension_traits::is_insertable<T>::value
|
||||
>::type>
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
|
||||
template <class Json,class TempAllocator>
|
||||
static T decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>& decoder,
|
||||
std::error_code& ec)
|
||||
{
|
||||
T v;
|
||||
|
||||
cursor.array_expected(ec);
|
||||
if (ec)
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
if (cursor.current().event_type() != staj_event_type::begin_array)
|
||||
{
|
||||
ec = conv_errc::not_vector;
|
||||
return v;
|
||||
}
|
||||
if (cursor.current().size() > 0)
|
||||
{
|
||||
reserve_storage(typename std::integral_constant<bool, extension_traits::has_reserve<T>::value>::type(), v, cursor.current().size());
|
||||
}
|
||||
cursor.next(ec);
|
||||
while (cursor.current().event_type() != staj_event_type::end_array && !ec)
|
||||
{
|
||||
v.insert(decode_traits<value_type,CharT>::decode(cursor, decoder, ec));
|
||||
if (ec) {return T{};}
|
||||
cursor.next(ec);
|
||||
if (ec) {return T{};}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static void reserve_storage(std::true_type, T& v, std::size_t new_cap)
|
||||
{
|
||||
v.reserve(new_cap);
|
||||
}
|
||||
|
||||
static void reserve_storage(std::false_type, T&, std::size_t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// std::array
|
||||
|
||||
template <class T, class CharT, std::size_t N>
|
||||
struct decode_traits<std::array<T,N>,CharT>
|
||||
{
|
||||
using value_type = typename std::array<T,N>::value_type;
|
||||
|
||||
template <class Json,class TempAllocator>
|
||||
static std::array<T, N> decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>& decoder,
|
||||
std::error_code& ec)
|
||||
{
|
||||
std::array<T,N> v;
|
||||
cursor.array_expected(ec);
|
||||
if (ec)
|
||||
{
|
||||
v.fill(T());
|
||||
return v;
|
||||
}
|
||||
v.fill(T{});
|
||||
if (cursor.current().event_type() != staj_event_type::begin_array)
|
||||
{
|
||||
ec = conv_errc::not_vector;
|
||||
return v;
|
||||
}
|
||||
cursor.next(ec);
|
||||
for (std::size_t i = 0; i < N && cursor.current().event_type() != staj_event_type::end_array && !ec; ++i)
|
||||
{
|
||||
v[i] = decode_traits<value_type,CharT>::decode(cursor, decoder, ec);
|
||||
if (ec) {return v;}
|
||||
cursor.next(ec);
|
||||
if (ec) {return v;}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
// map like
|
||||
|
||||
template <class T, class CharT>
|
||||
struct decode_traits<T,CharT,
|
||||
typename std::enable_if<!is_json_type_traits_declared<T>::value &&
|
||||
extension_traits::is_map_like<T>::value &&
|
||||
extension_traits::is_constructible_from_const_pointer_and_size<typename T::key_type>::value
|
||||
>::type>
|
||||
{
|
||||
using mapped_type = typename T::mapped_type;
|
||||
using value_type = typename T::value_type;
|
||||
using key_type = typename T::key_type;
|
||||
|
||||
template <class Json,class TempAllocator>
|
||||
static T decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>& decoder,
|
||||
std::error_code& ec)
|
||||
{
|
||||
T val;
|
||||
if (cursor.current().event_type() != staj_event_type::begin_object)
|
||||
{
|
||||
ec = conv_errc::not_map;
|
||||
return val;
|
||||
}
|
||||
if (cursor.current().size() > 0)
|
||||
{
|
||||
reserve_storage(typename std::integral_constant<bool, extension_traits::has_reserve<T>::value>::type(), val, cursor.current().size());
|
||||
}
|
||||
cursor.next(ec);
|
||||
|
||||
while (cursor.current().event_type() != staj_event_type::end_object && !ec)
|
||||
{
|
||||
if (cursor.current().event_type() != staj_event_type::key)
|
||||
{
|
||||
ec = json_errc::expected_key;
|
||||
return val;
|
||||
}
|
||||
auto key = cursor.current().template get<key_type>(ec);
|
||||
if (ec) return val;
|
||||
cursor.next(ec);
|
||||
if (ec) return val;
|
||||
val.emplace(std::move(key),decode_traits<mapped_type,CharT>::decode(cursor, decoder, ec));
|
||||
if (ec) {return val;}
|
||||
cursor.next(ec);
|
||||
if (ec) {return val;}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void reserve_storage(std::true_type, T& v, std::size_t new_cap)
|
||||
{
|
||||
v.reserve(new_cap);
|
||||
}
|
||||
|
||||
static void reserve_storage(std::false_type, T&, std::size_t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class CharT>
|
||||
struct decode_traits<T,CharT,
|
||||
typename std::enable_if<!is_json_type_traits_declared<T>::value &&
|
||||
extension_traits::is_map_like<T>::value &&
|
||||
std::is_integral<typename T::key_type>::value
|
||||
>::type>
|
||||
{
|
||||
using mapped_type = typename T::mapped_type;
|
||||
using value_type = typename T::value_type;
|
||||
using key_type = typename T::key_type;
|
||||
|
||||
template <class Json,class TempAllocator>
|
||||
static T decode(basic_staj_cursor<CharT>& cursor,
|
||||
json_decoder<Json,TempAllocator>& decoder,
|
||||
std::error_code& ec)
|
||||
{
|
||||
T val;
|
||||
if (cursor.current().event_type() != staj_event_type::begin_object)
|
||||
{
|
||||
ec = conv_errc::not_map;
|
||||
return val;
|
||||
}
|
||||
if (cursor.current().size() > 0)
|
||||
{
|
||||
reserve_storage(typename std::integral_constant<bool, extension_traits::has_reserve<T>::value>::type(), val, cursor.current().size());
|
||||
}
|
||||
cursor.next(ec);
|
||||
|
||||
while (cursor.current().event_type() != staj_event_type::end_object && !ec)
|
||||
{
|
||||
if (cursor.current().event_type() != staj_event_type::key)
|
||||
{
|
||||
ec = json_errc::expected_key;
|
||||
return val;
|
||||
}
|
||||
auto s = cursor.current().template get<jsoncons::basic_string_view<typename Json::char_type>>(ec);
|
||||
if (ec) return val;
|
||||
key_type n{0};
|
||||
auto r = jsoncons::detail::to_integer(s.data(), s.size(), n);
|
||||
if (r.ec != jsoncons::detail::to_integer_errc())
|
||||
{
|
||||
ec = json_errc::invalid_number;
|
||||
return val;
|
||||
}
|
||||
cursor.next(ec);
|
||||
if (ec) return val;
|
||||
val.emplace(n, decode_traits<mapped_type,CharT>::decode(cursor, decoder, ec));
|
||||
if (ec) {return val;}
|
||||
cursor.next(ec);
|
||||
if (ec) {return val;}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void reserve_storage(std::true_type, T& v, std::size_t new_cap)
|
||||
{
|
||||
v.reserve(new_cap);
|
||||
}
|
||||
|
||||
static void reserve_storage(std::false_type, T&, std::size_t)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
44
scripts/exe/jsoncons/include/jsoncons/detail/endian.hpp
Normal file
44
scripts/exe/jsoncons/include/jsoncons/detail/endian.hpp
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_DETAIL_ENDIAN_HPP
|
||||
#define JSONCONS_DETAIL_ENDIAN_HPP
|
||||
|
||||
#if defined(__sun)
|
||||
# include <sys/byteorder.h>
|
||||
#endif
|
||||
|
||||
namespace jsoncons {
|
||||
namespace detail {
|
||||
|
||||
enum class endian
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
// MSVC, which implies Windows, which implies little-endian
|
||||
little = 0,
|
||||
big = 1,
|
||||
native = little
|
||||
#elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__)
|
||||
little = __ORDER_LITTLE_ENDIAN__,
|
||||
big = __ORDER_BIG_ENDIAN__,
|
||||
native = __BYTE_ORDER__
|
||||
#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
|
||||
little = 0,
|
||||
big = 1,
|
||||
native = big
|
||||
#elif !defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
|
||||
little = 0,
|
||||
big = 1,
|
||||
native = little
|
||||
#else
|
||||
#error "Unable to determine byte order!"
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
312
scripts/exe/jsoncons/include/jsoncons/detail/grisu3.hpp
Normal file
312
scripts/exe/jsoncons/include/jsoncons/detail/grisu3.hpp
Normal file
File diff suppressed because one or more lines are too long
379
scripts/exe/jsoncons/include/jsoncons/detail/heap_string.hpp
Normal file
379
scripts/exe/jsoncons/include/jsoncons/detail/heap_string.hpp
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_DETAIL_STRING_WRAPPER_HPP
|
||||
#define JSONCONS_DETAIL_STRING_WRAPPER_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <ostream>
|
||||
#include <cstring> // std::memcpy
|
||||
#include <memory> // std::allocator
|
||||
#include <jsoncons/config/compiler_support.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace detail {
|
||||
|
||||
template<std::size_t Len, std::size_t Align>
|
||||
struct jsoncons_aligned_storage
|
||||
{
|
||||
struct type
|
||||
{
|
||||
alignas(Align) unsigned char data[Len];
|
||||
};
|
||||
};
|
||||
|
||||
// From boost 1_71
|
||||
template <class T, class U>
|
||||
T launder_cast(U* u)
|
||||
{
|
||||
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
|
||||
return std::launder(reinterpret_cast<T>(u));
|
||||
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) > 800
|
||||
return __builtin_launder(reinterpret_cast<T>(u));
|
||||
#else
|
||||
return reinterpret_cast<T>(u);
|
||||
#endif
|
||||
}
|
||||
|
||||
// string_wrapper
|
||||
|
||||
template <class CharT,class Allocator>
|
||||
class string_wrapper
|
||||
{
|
||||
public:
|
||||
using char_type = CharT;
|
||||
private:
|
||||
struct str_base_t
|
||||
{
|
||||
Allocator alloc_;
|
||||
|
||||
Allocator& get_allocator()
|
||||
{
|
||||
return alloc_;
|
||||
}
|
||||
|
||||
const Allocator& get_allocator() const
|
||||
{
|
||||
return alloc_;
|
||||
}
|
||||
|
||||
str_base_t(const Allocator& alloc)
|
||||
: alloc_(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
~str_base_t() noexcept = default;
|
||||
};
|
||||
|
||||
struct str_t : public str_base_t
|
||||
{
|
||||
typedef typename std::allocator_traits<Allocator>::template rebind_alloc<CharT> allocator_type;
|
||||
using allocator_traits_type = std::allocator_traits<allocator_type>;
|
||||
using pointer = typename allocator_traits_type::pointer;
|
||||
|
||||
pointer p_;
|
||||
std::size_t length_;
|
||||
|
||||
~str_t() noexcept = default;
|
||||
|
||||
const char_type* c_str() const { return extension_traits::to_plain_pointer(p_); }
|
||||
const char_type* data() const { return extension_traits::to_plain_pointer(p_); }
|
||||
std::size_t length() const { return length_; }
|
||||
|
||||
str_t(const Allocator& alloc)
|
||||
: str_base_t(alloc), p_(nullptr), length_(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
str_t(const str_t&) = delete;
|
||||
str_t& operator=(const str_t&) = delete;
|
||||
|
||||
};
|
||||
|
||||
typedef typename std::allocator_traits<Allocator>::template rebind_alloc<char> byte_allocator_type;
|
||||
using byte_pointer = typename std::allocator_traits<byte_allocator_type>::pointer;
|
||||
|
||||
typedef typename std::allocator_traits<Allocator>::template rebind_alloc<str_t> string_allocator_type;
|
||||
using string_pointer = typename std::allocator_traits<string_allocator_type>::pointer;
|
||||
|
||||
struct storage_t
|
||||
{
|
||||
str_t data;
|
||||
char_type c[1];
|
||||
};
|
||||
typedef typename jsoncons_aligned_storage<sizeof(storage_t), alignof(storage_t)>::type json_storage_kind;
|
||||
|
||||
string_pointer ptr_;
|
||||
public:
|
||||
string_wrapper() = default;
|
||||
|
||||
string_wrapper(string_pointer ptr)
|
||||
: ptr_(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
string_wrapper(const char_type* data, std::size_t length, const Allocator& a)
|
||||
{
|
||||
ptr_ = create(data,length,a);
|
||||
}
|
||||
|
||||
string_wrapper(const string_wrapper& val)
|
||||
{
|
||||
ptr_ = create(val.data(),val.length(),val.get_allocator());
|
||||
}
|
||||
|
||||
string_wrapper(const string_wrapper& val, const Allocator& a)
|
||||
{
|
||||
ptr_ = create(val.data(),val.length(),a);
|
||||
}
|
||||
|
||||
~string_wrapper() noexcept
|
||||
{
|
||||
if (ptr_ != nullptr)
|
||||
{
|
||||
destroy(ptr_);
|
||||
}
|
||||
}
|
||||
|
||||
void swap(string_wrapper& other) noexcept
|
||||
{
|
||||
std::swap(ptr_,other.ptr_);
|
||||
}
|
||||
|
||||
const char_type* data() const
|
||||
{
|
||||
return ptr_->data();
|
||||
}
|
||||
|
||||
const char_type* c_str() const
|
||||
{
|
||||
return ptr_->c_str();
|
||||
}
|
||||
|
||||
std::size_t length() const
|
||||
{
|
||||
return ptr_->length();
|
||||
}
|
||||
|
||||
Allocator get_allocator() const
|
||||
{
|
||||
return ptr_->get_allocator();
|
||||
}
|
||||
private:
|
||||
static size_t aligned_size(std::size_t n)
|
||||
{
|
||||
return sizeof(json_storage_kind) + n;
|
||||
}
|
||||
|
||||
static string_pointer create(const char_type* s, std::size_t length, const Allocator& alloc)
|
||||
{
|
||||
std::size_t mem_size = aligned_size(length*sizeof(char_type));
|
||||
|
||||
byte_allocator_type byte_alloc(alloc);
|
||||
byte_pointer ptr = byte_alloc.allocate(mem_size);
|
||||
|
||||
char* storage = extension_traits::to_plain_pointer(ptr);
|
||||
str_t* ps = new(storage)str_t(byte_alloc);
|
||||
|
||||
auto psa = launder_cast<storage_t*>(storage);
|
||||
|
||||
CharT* p = new(&psa->c)char_type[length + 1];
|
||||
std::memcpy(p, s, length*sizeof(char_type));
|
||||
p[length] = 0;
|
||||
ps->p_ = std::pointer_traits<typename str_t::pointer>::pointer_to(*p);
|
||||
ps->length_ = length;
|
||||
return std::pointer_traits<string_pointer>::pointer_to(*ps);
|
||||
}
|
||||
|
||||
static void destroy(string_pointer ptr)
|
||||
{
|
||||
str_t* rawp = extension_traits::to_plain_pointer(ptr);
|
||||
|
||||
char* p = launder_cast<char*>(rawp);
|
||||
|
||||
std::size_t mem_size = aligned_size(ptr->length_*sizeof(char_type));
|
||||
byte_allocator_type byte_alloc(ptr->get_allocator());
|
||||
byte_alloc.deallocate(p,mem_size);
|
||||
}
|
||||
};
|
||||
|
||||
// tagged_string_wrapper
|
||||
|
||||
template <class CharT,class Allocator>
|
||||
class tagged_string_wrapper
|
||||
{
|
||||
public:
|
||||
using char_type = CharT;
|
||||
private:
|
||||
struct str_base_t
|
||||
{
|
||||
Allocator alloc_;
|
||||
|
||||
Allocator& get_allocator()
|
||||
{
|
||||
return alloc_;
|
||||
}
|
||||
|
||||
const Allocator& get_allocator() const
|
||||
{
|
||||
return alloc_;
|
||||
}
|
||||
|
||||
str_base_t(const Allocator& alloc)
|
||||
: alloc_(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
~str_base_t() noexcept = default;
|
||||
};
|
||||
|
||||
struct str_t : public str_base_t
|
||||
{
|
||||
typedef typename std::allocator_traits<Allocator>::template rebind_alloc<CharT> allocator_type;
|
||||
using allocator_traits_type = std::allocator_traits<allocator_type>;
|
||||
using pointer = typename allocator_traits_type::pointer;
|
||||
|
||||
pointer p_;
|
||||
std::size_t length_;
|
||||
uint64_t tag_;
|
||||
|
||||
~str_t() noexcept = default;
|
||||
|
||||
const char_type* c_str() const { return extension_traits::to_plain_pointer(p_); }
|
||||
const char_type* data() const { return extension_traits::to_plain_pointer(p_); }
|
||||
std::size_t length() const { return length_; }
|
||||
uint64_t tag() const { return tag_; }
|
||||
|
||||
str_t(uint64_t tag, const Allocator& alloc)
|
||||
: str_base_t(alloc), p_(nullptr), length_(0), tag_(tag)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
str_t(const str_t&) = delete;
|
||||
str_t& operator=(const str_t&) = delete;
|
||||
|
||||
};
|
||||
|
||||
typedef typename std::allocator_traits<Allocator>::template rebind_alloc<char> byte_allocator_type;
|
||||
using byte_pointer = typename std::allocator_traits<byte_allocator_type>::pointer;
|
||||
|
||||
typedef typename std::allocator_traits<Allocator>::template rebind_alloc<str_t> string_allocator_type;
|
||||
using string_pointer = typename std::allocator_traits<string_allocator_type>::pointer;
|
||||
|
||||
struct storage_t
|
||||
{
|
||||
str_t data;
|
||||
char_type c[1];
|
||||
};
|
||||
typedef typename jsoncons_aligned_storage<sizeof(storage_t), alignof(storage_t)>::type json_storage_kind;
|
||||
|
||||
string_pointer ptr_;
|
||||
public:
|
||||
tagged_string_wrapper() = default;
|
||||
|
||||
tagged_string_wrapper(string_pointer ptr)
|
||||
: ptr_(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
tagged_string_wrapper(const char_type* data, std::size_t length, uint64_t tag, const Allocator& alloc)
|
||||
{
|
||||
ptr_ = create(data, length, tag, alloc);
|
||||
}
|
||||
|
||||
tagged_string_wrapper(const tagged_string_wrapper& val)
|
||||
{
|
||||
ptr_ = create(val.data(), val.length(), val.tag(), val.get_allocator());
|
||||
}
|
||||
|
||||
tagged_string_wrapper(const tagged_string_wrapper& val, const Allocator& alloc)
|
||||
{
|
||||
ptr_ = create(val.data(), val.length(), val.tag(), alloc);
|
||||
}
|
||||
|
||||
~tagged_string_wrapper() noexcept
|
||||
{
|
||||
if (ptr_ != nullptr)
|
||||
{
|
||||
destroy(ptr_);
|
||||
}
|
||||
}
|
||||
|
||||
void swap(tagged_string_wrapper& other) noexcept
|
||||
{
|
||||
std::swap(ptr_,other.ptr_);
|
||||
}
|
||||
|
||||
const char_type* data() const
|
||||
{
|
||||
return ptr_->data();
|
||||
}
|
||||
|
||||
const char_type* c_str() const
|
||||
{
|
||||
return ptr_->c_str();
|
||||
}
|
||||
|
||||
std::size_t length() const
|
||||
{
|
||||
return ptr_->length();
|
||||
}
|
||||
|
||||
uint64_t tag() const
|
||||
{
|
||||
return ptr_->tag();
|
||||
}
|
||||
|
||||
Allocator get_allocator() const
|
||||
{
|
||||
return ptr_->get_allocator();
|
||||
}
|
||||
private:
|
||||
static size_t aligned_size(std::size_t n)
|
||||
{
|
||||
return sizeof(json_storage_kind) + n;
|
||||
}
|
||||
|
||||
static string_pointer create(const char_type* s, std::size_t length, uint64_t tag, const Allocator& alloc)
|
||||
{
|
||||
std::size_t mem_size = aligned_size(length*sizeof(char_type));
|
||||
|
||||
byte_allocator_type byte_alloc(alloc);
|
||||
byte_pointer ptr = byte_alloc.allocate(mem_size);
|
||||
|
||||
char* storage = extension_traits::to_plain_pointer(ptr);
|
||||
str_t* ps = new(storage)str_t(tag, byte_alloc);
|
||||
|
||||
auto psa = launder_cast<storage_t*>(storage);
|
||||
|
||||
CharT* p = new(&psa->c)char_type[length + 1];
|
||||
std::memcpy(p, s, length*sizeof(char_type));
|
||||
p[length] = 0;
|
||||
ps->p_ = std::pointer_traits<typename str_t::pointer>::pointer_to(*p);
|
||||
ps->length_ = length;
|
||||
return std::pointer_traits<string_pointer>::pointer_to(*ps);
|
||||
}
|
||||
|
||||
static void destroy(string_pointer ptr)
|
||||
{
|
||||
str_t* rawp = extension_traits::to_plain_pointer(ptr);
|
||||
|
||||
char* p = launder_cast<char*>(rawp);
|
||||
|
||||
std::size_t mem_size = aligned_size(ptr->length_*sizeof(char_type));
|
||||
byte_allocator_type byte_alloc(ptr->get_allocator());
|
||||
byte_alloc.deallocate(p,mem_size);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
483
scripts/exe/jsoncons/include/jsoncons/detail/optional.hpp
Normal file
483
scripts/exe/jsoncons/include/jsoncons/detail/optional.hpp
Normal file
|
|
@ -0,0 +1,483 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_DETAIL_OPTIONAL_HPP
|
||||
#define JSONCONS_DETAIL_OPTIONAL_HPP
|
||||
|
||||
#include <new> // placement new
|
||||
#include <memory>
|
||||
#include <utility> // std::swap
|
||||
#include <type_traits>
|
||||
#include <jsoncons/config/compiler_support.hpp>
|
||||
|
||||
namespace jsoncons
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
class optional;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct is_constructible_or_convertible_from_optional
|
||||
: std::integral_constant<
|
||||
bool, std::is_constructible<T1, optional<T2>&>::value ||
|
||||
std::is_constructible<T1, optional<T2>&&>::value ||
|
||||
std::is_constructible<T1, const optional<T2>&>::value ||
|
||||
std::is_constructible<T1, const optional<T2>&&>::value ||
|
||||
std::is_convertible<optional<T2>&, T1>::value ||
|
||||
std::is_convertible<optional<T2>&&, T1>::value ||
|
||||
std::is_convertible<const optional<T2>&, T1>::value ||
|
||||
std::is_convertible<const optional<T2>&&, T1>::value> {};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct is_constructible_convertible_or_assignable_from_optional
|
||||
: std::integral_constant<
|
||||
bool, is_constructible_or_convertible_from_optional<T1, T2>::value ||
|
||||
std::is_assignable<T1&, optional<T2>&>::value ||
|
||||
std::is_assignable<T1&, optional<T2>&&>::value ||
|
||||
std::is_assignable<T1&, const optional<T2>&>::value ||
|
||||
std::is_assignable<T1&, const optional<T2>&&>::value> {};
|
||||
|
||||
template <typename T>
|
||||
class optional
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
private:
|
||||
bool has_value_;
|
||||
union {
|
||||
char dummy_;
|
||||
T value_;
|
||||
};
|
||||
public:
|
||||
constexpr optional() noexcept
|
||||
: has_value_(false), dummy_{}
|
||||
{
|
||||
}
|
||||
|
||||
// copy constructors
|
||||
optional(const optional<T>& other)
|
||||
: has_value_(false), dummy_{}
|
||||
{
|
||||
if (other)
|
||||
{
|
||||
construct(*other);
|
||||
}
|
||||
}
|
||||
|
||||
// converting
|
||||
template <class U,
|
||||
typename std::enable_if<!std::is_same<T,U>::value &&
|
||||
std::is_constructible<T, const U&>::value &&
|
||||
std::is_convertible<const U&,T>::value &&
|
||||
!is_constructible_or_convertible_from_optional<T,U>::value &&
|
||||
std::is_copy_constructible<typename std::decay<U>::type>::value,int>::type = 0>
|
||||
optional(const optional<U>& other)
|
||||
: has_value_(false), dummy_{}
|
||||
{
|
||||
if (other)
|
||||
{
|
||||
construct(*other);
|
||||
}
|
||||
}
|
||||
|
||||
template <class U,
|
||||
typename std::enable_if<!std::is_same<T,U>::value &&
|
||||
std::is_constructible<T, const U&>::value &&
|
||||
!std::is_convertible<const U&,T>::value &&
|
||||
!is_constructible_or_convertible_from_optional<T,U>::value &&
|
||||
std::is_copy_constructible<typename std::decay<U>::type>::value,int>::type = 0>
|
||||
explicit optional(const optional<U>& other)
|
||||
: has_value_(false), dummy_{}
|
||||
{
|
||||
if (other)
|
||||
{
|
||||
construct(*other);
|
||||
}
|
||||
}
|
||||
|
||||
// move constructors
|
||||
template <class T2 = T>
|
||||
optional(optional<T>&& other,
|
||||
typename std::enable_if<std::is_move_constructible<typename std::decay<T2>::type>::value>::type* = 0)
|
||||
: has_value_(false), dummy_{}
|
||||
{
|
||||
if (other)
|
||||
{
|
||||
construct(std::move(other.value_));
|
||||
}
|
||||
}
|
||||
|
||||
// converting
|
||||
template <class U>
|
||||
optional(optional<U>&& value,
|
||||
typename std::enable_if<!std::is_same<T,U>::value &&
|
||||
std::is_constructible<T, U&&>::value &&
|
||||
!is_constructible_or_convertible_from_optional<T,U>::value &&
|
||||
std::is_convertible<U&&,T>::value,int>::type = 0) // (8)
|
||||
: has_value_(true), value_(std::forward<U>(value))
|
||||
{
|
||||
}
|
||||
|
||||
template <class U>
|
||||
explicit optional(optional<U>&& value,
|
||||
typename std::enable_if<!std::is_same<T,U>::value &&
|
||||
std::is_constructible<T, U&&>::value &&
|
||||
!is_constructible_or_convertible_from_optional<T,U>::value &&
|
||||
!std::is_convertible<U&&,T>::value,int>::type = 0) // (8)
|
||||
: has_value_(true), value_(std::forward<U>(value))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// value constructors
|
||||
template <class T2>
|
||||
optional(T2&& value,
|
||||
typename std::enable_if<!std::is_same<optional<T>,typename std::decay<T2>::type>::value &&
|
||||
std::is_constructible<T, T2>::value &&
|
||||
std::is_convertible<T2,T>::value,int>::type = 0) // (8)
|
||||
: has_value_(true), value_(std::forward<T2>(value))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T2>
|
||||
explicit optional(T2&& value,
|
||||
typename std::enable_if<!std::is_same<optional<T>,typename std::decay<T2>::type>::value &&
|
||||
std::is_constructible<T, T2>::value &&
|
||||
!std::is_convertible<T2,T>::value,int>::type = 0) // (8)
|
||||
: has_value_(true), value_(std::forward<T2>(value))
|
||||
{
|
||||
}
|
||||
|
||||
~optional() noexcept
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
optional& operator=(const optional& other)
|
||||
{
|
||||
if (other)
|
||||
{
|
||||
assign(*other);
|
||||
}
|
||||
else
|
||||
{
|
||||
reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
optional& operator=(optional&& other )
|
||||
{
|
||||
if (other)
|
||||
{
|
||||
assign(std::move(*other));
|
||||
}
|
||||
else
|
||||
{
|
||||
reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
typename std::enable_if<!std::is_same<optional<T>, U>::value &&
|
||||
std::is_constructible<T, const U&>::value &&
|
||||
!is_constructible_convertible_or_assignable_from_optional<T,U>::value &&
|
||||
std::is_assignable<T&, const U&>::value,
|
||||
optional&>::type
|
||||
operator=(const optional<U>& other)
|
||||
{
|
||||
if (other)
|
||||
{
|
||||
assign(*other);
|
||||
}
|
||||
else
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
typename std::enable_if<!std::is_same<optional<T>, U>::value &&
|
||||
std::is_constructible<T, U>::value &&
|
||||
!is_constructible_convertible_or_assignable_from_optional<T,U>::value &&
|
||||
std::is_assignable<T&, U>::value,
|
||||
optional&>::type
|
||||
operator=(optional<U>&& other)
|
||||
{
|
||||
if (other)
|
||||
{
|
||||
assign(std::move(*other));
|
||||
}
|
||||
else
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// value assignment
|
||||
template <typename T2>
|
||||
typename std::enable_if<!std::is_same<optional<T>, typename std::decay<T2>::type>::value &&
|
||||
std::is_constructible<T, T2>::value &&
|
||||
std::is_assignable<T&, T2>::value &&
|
||||
!(std::is_scalar<T>::value && std::is_same<T, typename std::decay<T2>::type>::value),
|
||||
optional&>::type
|
||||
operator=(T2&& v)
|
||||
{
|
||||
assign(std::forward<T2>(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const noexcept
|
||||
{
|
||||
return has_value_;
|
||||
}
|
||||
constexpr bool has_value() const noexcept
|
||||
{
|
||||
return has_value_;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4702)
|
||||
#endif // _MSC_VER
|
||||
|
||||
T& value() &
|
||||
{
|
||||
return static_cast<bool>(*this)
|
||||
? get()
|
||||
: JSONCONS_THROW(std::runtime_error("Bad optional access")), get();
|
||||
}
|
||||
|
||||
constexpr const T& value() const &
|
||||
{
|
||||
return static_cast<bool>(*this)
|
||||
? get()
|
||||
: JSONCONS_THROW(std::runtime_error("Bad optional access")), get();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
constexpr T value_or(U&& default_value) const &
|
||||
{
|
||||
static_assert(std::is_copy_constructible<T>::value,
|
||||
"get_value_or: T must be copy constructible");
|
||||
static_assert(std::is_convertible<U&&, T>::value,
|
||||
"get_value_or: U must be convertible to T");
|
||||
return static_cast<bool>(*this)
|
||||
? **this
|
||||
: static_cast<T>(std::forward<U>(default_value));
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
T value_or(U&& default_value) &&
|
||||
{
|
||||
static_assert(std::is_move_constructible<T>::value,
|
||||
"get_value_or: T must be move constructible");
|
||||
static_assert(std::is_convertible<U&&, T>::value,
|
||||
"get_value_or: U must be convertible to T");
|
||||
return static_cast<bool>(*this) ? std::move(**this)
|
||||
: static_cast<T>(std::forward<U>(default_value));
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
const T* operator->() const
|
||||
{
|
||||
return std::addressof(this->value_);
|
||||
}
|
||||
|
||||
T* operator->()
|
||||
{
|
||||
return std::addressof(this->value_);
|
||||
}
|
||||
|
||||
constexpr const T& operator*() const&
|
||||
{
|
||||
return value();
|
||||
}
|
||||
|
||||
T& operator*() &
|
||||
{
|
||||
return value();
|
||||
}
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void swap(optional& other) noexcept(std::is_nothrow_move_constructible<T>::value /*&&
|
||||
std::is_nothrow_swappable<T>::value*/)
|
||||
{
|
||||
const bool contains_a_value = has_value();
|
||||
if (contains_a_value == other.has_value())
|
||||
{
|
||||
if (contains_a_value)
|
||||
{
|
||||
using std::swap;
|
||||
swap(**this, *other);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
optional& source = contains_a_value ? *this : other;
|
||||
optional& target = contains_a_value ? other : *this;
|
||||
target = optional<T>(*source);
|
||||
source.reset();
|
||||
}
|
||||
}
|
||||
private:
|
||||
constexpr const T& get() const { return this->value_; }
|
||||
T& get() { return this->value_; }
|
||||
|
||||
template <typename... Args>
|
||||
void construct(Args&&... args)
|
||||
{
|
||||
::new (static_cast<void*>(&this->value_)) T(std::forward<Args>(args)...);
|
||||
has_value_ = true;
|
||||
}
|
||||
|
||||
void destroy() noexcept
|
||||
{
|
||||
if (has_value_)
|
||||
{
|
||||
value_.~T();
|
||||
has_value_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void assign(U&& u)
|
||||
{
|
||||
if (has_value_)
|
||||
{
|
||||
value_ = std::forward<U>(u);
|
||||
}
|
||||
else
|
||||
{
|
||||
construct(std::forward<U>(u));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_nothrow_move_constructible<T>::value,void>::type
|
||||
swap(optional<T>& lhs, optional<T>& rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator==(const optional<T1>& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return lhs.has_value() == rhs.has_value() && (!lhs.has_value() || *lhs == *rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator!=(const optional<T1>& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return lhs.has_value() != rhs.has_value() || (lhs.has_value() && *lhs != *rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator<(const optional<T1>& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator>(const optional<T1>& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator<=(const optional<T1>& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator>=(const optional<T1>& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator==(const optional<T1>& lhs, const T2& rhs) noexcept
|
||||
{
|
||||
return lhs ? *lhs == rhs : false;
|
||||
}
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator==(const T1& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return rhs ? lhs == *rhs : false;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator!=(const optional<T1>& lhs, const T2& rhs) noexcept
|
||||
{
|
||||
return lhs ? *lhs != rhs : true;
|
||||
}
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator!=(const T1& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return rhs ? lhs != *rhs : true;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator<(const optional<T1>& lhs, const T2& rhs) noexcept
|
||||
{
|
||||
return lhs ? *lhs < rhs : true;
|
||||
}
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator<(const T1& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return rhs ? lhs < *rhs : false;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator<=(const optional<T1>& lhs, const T2& rhs) noexcept
|
||||
{
|
||||
return lhs ? *lhs <= rhs : true;
|
||||
}
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator<=(const T1& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return rhs ? lhs <= *rhs : false;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator>(const optional<T1>& lhs, const T2& rhs) noexcept
|
||||
{
|
||||
return lhs ? *lhs > rhs : false;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator>(const T1& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return rhs ? lhs > *rhs : true;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator>=(const optional<T1>& lhs, const T2& rhs) noexcept
|
||||
{
|
||||
return lhs ? *lhs >= rhs : false;
|
||||
}
|
||||
template <class T1, class T2>
|
||||
constexpr bool operator>=(const T1& lhs, const optional<T2>& rhs) noexcept
|
||||
{
|
||||
return rhs ? lhs >= *rhs : true;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
1133
scripts/exe/jsoncons/include/jsoncons/detail/parse_number.hpp
Normal file
1133
scripts/exe/jsoncons/include/jsoncons/detail/parse_number.hpp
Normal file
File diff suppressed because it is too large
Load diff
188
scripts/exe/jsoncons/include/jsoncons/detail/span.hpp
Normal file
188
scripts/exe/jsoncons/include/jsoncons/detail/span.hpp
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
#ifndef JSONCONS_DETAIL_SPAN_HPP
|
||||
#define JSONCONS_DETAIL_SPAN_HPP
|
||||
|
||||
#include <utility> // std::swap
|
||||
#include <memory> // std::addressof
|
||||
#include <type_traits> // std::enable_if, std::true_type, std::false_type
|
||||
#include <jsoncons/config/compiler_support.hpp>
|
||||
#include <jsoncons/extension_traits.hpp>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
namespace jsoncons
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
constexpr std::size_t dynamic_extent = (std::numeric_limits<std::size_t>::max)();
|
||||
|
||||
template< class T, std::size_t Extent = dynamic_extent>
|
||||
class span;
|
||||
|
||||
template<class T>
|
||||
struct is_span : std::false_type{};
|
||||
|
||||
template< class T>
|
||||
struct is_span<span<T>> : std::true_type{};
|
||||
|
||||
template<
|
||||
class T,
|
||||
std::size_t Extent
|
||||
> class span
|
||||
{
|
||||
public:
|
||||
using element_type = T;
|
||||
using value_type = typename std::remove_volatile<typename std::remove_const<T>::type>::type;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
private:
|
||||
pointer data_;
|
||||
size_type size_;
|
||||
public:
|
||||
static constexpr std::size_t extent = Extent;
|
||||
|
||||
constexpr span() noexcept
|
||||
: data_(nullptr), size_(0)
|
||||
{
|
||||
}
|
||||
constexpr span(pointer data, size_type size)
|
||||
: data_(data), size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
constexpr span(C& c,
|
||||
typename std::enable_if<!is_span<C>::value && !extension_traits::is_std_array<C>::value && extension_traits::is_compatible_element<C,element_type>::value && extension_traits::has_data_and_size<C>::value>::type* = 0)
|
||||
: data_(c.data()), size_(c.size())
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
span(element_type (&arr)[N]) noexcept
|
||||
: data_(std::addressof(arr[0])), size_(N)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
span(std::array<value_type, N>& arr,
|
||||
typename std::enable_if<(extent == dynamic_extent || extent == N)>::type* = 0) noexcept
|
||||
: data_(arr.data()), size_(arr.size())
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
span(const std::array<value_type, N>& arr,
|
||||
typename std::enable_if<(extent == dynamic_extent || extent == N)>::type* = 0) noexcept
|
||||
: data_(arr.data()), size_(arr.size())
|
||||
{
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
constexpr span(const C& c,
|
||||
typename std::enable_if<!is_span<C>::value && !extension_traits::is_std_array<C>::value && extension_traits::is_compatible_element<C,element_type>::value && extension_traits::has_data_and_size<C>::value>::type* = 0)
|
||||
: data_(c.data()), size_(c.size())
|
||||
{
|
||||
}
|
||||
|
||||
template <class U, std::size_t N>
|
||||
constexpr span(const span<U, N>& s,
|
||||
typename std::enable_if<(N == dynamic_extent || N == extent) && std::is_convertible<U(*)[], element_type(*)[]>::value>::type* = 0) noexcept
|
||||
: data_(s.data()), size_(s.size())
|
||||
{
|
||||
}
|
||||
|
||||
constexpr span(const span& other) noexcept = default;
|
||||
|
||||
span& operator=( const span& other ) noexcept = default;
|
||||
|
||||
constexpr pointer data() const noexcept
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
constexpr size_type size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept
|
||||
{
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
constexpr reference operator[](size_type index) const
|
||||
{
|
||||
return data_[index];
|
||||
}
|
||||
|
||||
// iterator support
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return data_ + size_;
|
||||
}
|
||||
const_iterator cbegin() const noexcept
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return data_ + size_;
|
||||
}
|
||||
const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
span<element_type, dynamic_extent>
|
||||
first(std::size_t count) const
|
||||
{
|
||||
JSONCONS_ASSERT(count <= size());
|
||||
|
||||
return span< element_type, dynamic_extent >( data(), count );
|
||||
}
|
||||
|
||||
span<element_type, dynamic_extent>
|
||||
last(std::size_t count) const
|
||||
{
|
||||
JSONCONS_ASSERT(count <= size());
|
||||
|
||||
return span<element_type, dynamic_extent>(data() + ( size() - count ), count);
|
||||
}
|
||||
|
||||
span<element_type, dynamic_extent>
|
||||
subspan(std::size_t offset, std::size_t count = dynamic_extent) const
|
||||
{
|
||||
//JSONCONS_ASSERT((offset <= size() && (count == dynamic_extent || (offset + count <= size()))));
|
||||
|
||||
return span<element_type, dynamic_extent>(
|
||||
data() + offset, count == dynamic_extent ? size() - offset : count );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
537
scripts/exe/jsoncons/include/jsoncons/detail/string_view.hpp
Normal file
537
scripts/exe/jsoncons/include/jsoncons/detail/string_view.hpp
Normal file
|
|
@ -0,0 +1,537 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_STRING_VIEW_HPP
|
||||
#define JSONCONS_STRING_VIEW_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <cmath>
|
||||
#include <algorithm> // std::find, std::min, std::reverse
|
||||
#include <memory>
|
||||
#include <iterator>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/config/compiler_support.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace detail {
|
||||
|
||||
template <class CharT, class Traits = std::char_traits<CharT>>
|
||||
class basic_string_view
|
||||
{
|
||||
private:
|
||||
const CharT* data_;
|
||||
std::size_t length_;
|
||||
public:
|
||||
using value_type = CharT;
|
||||
using const_reference = const CharT&;
|
||||
using traits_type = Traits;
|
||||
using size_type = std::size_t;
|
||||
static constexpr size_type npos = size_type(-1);
|
||||
using const_iterator = const CharT*;
|
||||
using iterator = const CharT*;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
constexpr basic_string_view() noexcept
|
||||
: data_(nullptr), length_(0)
|
||||
{
|
||||
}
|
||||
constexpr basic_string_view(const CharT* data, std::size_t length)
|
||||
: data_(data), length_(length)
|
||||
{
|
||||
}
|
||||
|
||||
basic_string_view(const CharT* data)
|
||||
: data_(data), length_(Traits::length(data))
|
||||
{
|
||||
}
|
||||
constexpr basic_string_view(const basic_string_view& other) noexcept = default;
|
||||
|
||||
template <class Tr, class Allocator>
|
||||
JSONCONS_CPP14_CONSTEXPR basic_string_view(const std::basic_string<CharT,Tr,Allocator>& s) noexcept
|
||||
: data_(s.data()), length_(s.length())
|
||||
{
|
||||
}
|
||||
|
||||
JSONCONS_CPP14_CONSTEXPR basic_string_view& operator=( const basic_string_view& view ) noexcept
|
||||
{
|
||||
data_ = view.data();
|
||||
length_ = view.length();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
explicit operator std::basic_string<CharT,Traits,Allocator>() const
|
||||
{
|
||||
return std::basic_string<CharT,Traits,Allocator>(data_,length_);
|
||||
}
|
||||
|
||||
// iterator support
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return data_ + length_;
|
||||
}
|
||||
const_iterator cbegin() const noexcept
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return data_ + length_;
|
||||
}
|
||||
const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
// capacity
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return length_;
|
||||
}
|
||||
|
||||
std::size_t length() const
|
||||
{
|
||||
return length_;
|
||||
}
|
||||
size_type max_size() const noexcept
|
||||
{
|
||||
return length_;
|
||||
}
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return length_ == 0;
|
||||
}
|
||||
|
||||
// element access
|
||||
|
||||
const_reference operator[](size_type pos) const
|
||||
{
|
||||
return data_[pos];
|
||||
}
|
||||
|
||||
const_reference at(std::size_t pos) const
|
||||
{
|
||||
if (pos >= length_)
|
||||
{
|
||||
JSONCONS_THROW(std::out_of_range("pos exceeds length"));
|
||||
}
|
||||
return data_[pos];
|
||||
}
|
||||
|
||||
const_reference front() const
|
||||
{
|
||||
return data_[0];
|
||||
}
|
||||
const_reference back() const
|
||||
{
|
||||
return data_[length_-1];
|
||||
}
|
||||
|
||||
const CharT* data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
// string operations
|
||||
|
||||
basic_string_view substr(size_type pos, size_type n=npos) const
|
||||
{
|
||||
if (pos > length_)
|
||||
{
|
||||
JSONCONS_THROW(std::out_of_range("pos exceeds size"));
|
||||
}
|
||||
if (n == npos || pos + n > length_)
|
||||
{
|
||||
n = length_ - pos;
|
||||
}
|
||||
return basic_string_view(data_ + pos, n);
|
||||
}
|
||||
|
||||
int compare(const basic_string_view& s) const noexcept
|
||||
{
|
||||
const int rc = Traits::compare(data_, s.data_, (std::min)(length_, s.length_));
|
||||
return rc != 0 ? rc : (length_ == s.length_ ? 0 : length_ < s.length_ ? -1 : 1);
|
||||
}
|
||||
|
||||
int compare(const CharT* data) const noexcept
|
||||
{
|
||||
const size_t length = Traits::length(data);
|
||||
const int rc = Traits::compare(data_, data, (std::min)(length_, length));
|
||||
return rc != 0 ? rc : (length_ == length? 0 : length_ < length? -1 : 1);
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
int compare(const std::basic_string<CharT,Traits,Allocator>& s) const noexcept
|
||||
{
|
||||
const int rc = Traits::compare(data_, s.data(), (std::min)(length_, s.length()));
|
||||
return rc != 0 ? rc : (length_ == s.length() ? 0 : length_ < s.length() ? -1 : 1);
|
||||
}
|
||||
|
||||
size_type find(basic_string_view s, size_type pos = 0) const noexcept
|
||||
{
|
||||
if (pos > length_)
|
||||
{
|
||||
return npos;
|
||||
}
|
||||
if (s.length_ == 0)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
const_iterator it = std::search(cbegin() + pos, cend(),
|
||||
s.cbegin(), s.cend(), Traits::eq);
|
||||
return it == cend() ? npos : std::distance(cbegin(), it);
|
||||
}
|
||||
size_type find(CharT ch, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find(basic_string_view(&ch, 1), pos);
|
||||
}
|
||||
size_type find(const CharT* s, size_type pos, size_type n) const noexcept
|
||||
{
|
||||
return find(basic_string_view(s, n), pos);
|
||||
}
|
||||
size_type find(const CharT* s, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find(basic_string_view(s), pos);
|
||||
}
|
||||
|
||||
size_type rfind(basic_string_view s, size_type pos = npos) const noexcept
|
||||
{
|
||||
if (length_ < s.length_)
|
||||
{
|
||||
return npos;
|
||||
}
|
||||
if (pos > length_ - s.length_)
|
||||
{
|
||||
pos = length_ - s.length_;
|
||||
}
|
||||
if (s.length_ == 0)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
for (const CharT* p = data_ + pos; true; --p)
|
||||
{
|
||||
if (Traits::compare(p, s.data_, s.length_) == 0)
|
||||
{
|
||||
return p - data_;
|
||||
}
|
||||
if (p == data_)
|
||||
{
|
||||
return npos;
|
||||
}
|
||||
};
|
||||
}
|
||||
size_type rfind(CharT ch, size_type pos = npos) const noexcept
|
||||
{
|
||||
return rfind(basic_string_view(&ch, 1), pos);
|
||||
}
|
||||
size_type rfind(const CharT* s, size_type pos, size_type n) const noexcept
|
||||
{
|
||||
return rfind(basic_string_view(s, n), pos);
|
||||
}
|
||||
size_type rfind(const CharT* s, size_type pos = npos) const noexcept
|
||||
{
|
||||
return rfind(basic_string_view(s), pos);
|
||||
}
|
||||
|
||||
size_type find_first_of(basic_string_view s, size_type pos = 0) const noexcept
|
||||
{
|
||||
if (pos >= length_ || s.length_ == 0)
|
||||
{
|
||||
return npos;
|
||||
}
|
||||
const_iterator it = std::find_first_of
|
||||
(cbegin() + pos, cend(), s.cbegin(), s.cend(), Traits::eq);
|
||||
return it == cend() ? npos : std::distance (cbegin(), it);
|
||||
}
|
||||
size_type find_first_of(CharT ch, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_of(basic_string_view(&ch, 1), pos);
|
||||
}
|
||||
size_type find_first_of(const CharT* s, size_type pos, size_type n) const noexcept
|
||||
{
|
||||
return find_first_of(basic_string_view(s, n), pos);
|
||||
}
|
||||
size_type find_first_of(const CharT* s, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_of(basic_string_view(s), pos);
|
||||
}
|
||||
|
||||
size_type find_last_of(basic_string_view s, size_type pos = npos) const noexcept
|
||||
{
|
||||
if (s.length_ == 0)
|
||||
{
|
||||
return npos;
|
||||
}
|
||||
if (pos >= length_)
|
||||
{
|
||||
pos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = length_ - (pos+1);
|
||||
}
|
||||
const_reverse_iterator it = std::find_first_of
|
||||
(crbegin() + pos, crend(), s.cbegin(), s.cend(), Traits::eq);
|
||||
return it == crend() ? npos : (length_ - 1 - std::distance(crbegin(), it));
|
||||
}
|
||||
size_type find_last_of(CharT ch, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_of(basic_string_view(&ch, 1), pos);
|
||||
}
|
||||
size_type find_last_of(const CharT* s, size_type pos, size_type n) const noexcept
|
||||
{
|
||||
return find_last_of(basic_string_view(s, n), pos);
|
||||
}
|
||||
size_type find_last_of(const CharT* s, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_of(basic_string_view(s), pos);
|
||||
}
|
||||
|
||||
size_type find_first_not_of(basic_string_view s, size_type pos = 0) const noexcept
|
||||
{
|
||||
if (pos >= length_)
|
||||
return npos;
|
||||
if (s.length_ == 0)
|
||||
return pos;
|
||||
|
||||
const_iterator it = cend();
|
||||
for (auto p = cbegin()+pos; p != cend(); ++p)
|
||||
{
|
||||
if (Traits::find(s.data_, s.length_, *p) == 0)
|
||||
{
|
||||
it = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return it == cend() ? npos : std::distance (cbegin(), it);
|
||||
}
|
||||
size_type find_first_not_of(CharT ch, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_not_of(basic_string_view(&ch, 1), pos);
|
||||
}
|
||||
size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const noexcept
|
||||
{
|
||||
return find_first_not_of(basic_string_view(s, n), pos);
|
||||
}
|
||||
size_type find_first_not_of(const CharT* s, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_not_of(basic_string_view(s), pos);
|
||||
}
|
||||
|
||||
size_type find_last_not_of(basic_string_view s, size_type pos = npos) const noexcept
|
||||
{
|
||||
if (pos >= length_)
|
||||
{
|
||||
pos = length_ - 1;
|
||||
}
|
||||
if (s.length_ == 0)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
pos = length_ - (pos+1);
|
||||
|
||||
const_iterator it = crend();
|
||||
for (auto p = crbegin()+pos; p != crend(); ++p)
|
||||
{
|
||||
if (Traits::find(s.data_, s.length_, *p) == 0)
|
||||
{
|
||||
it = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return it == crend() ? npos : (length_ - 1 - std::distance(crbegin(), it));
|
||||
}
|
||||
size_type find_last_not_of(CharT ch, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_not_of(basic_string_view(&ch, 1), pos);
|
||||
}
|
||||
size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const noexcept
|
||||
{
|
||||
return find_last_not_of(basic_string_view(s, n), pos);
|
||||
}
|
||||
size_type find_last_not_of(const CharT* s, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_not_of(basic_string_view(s), pos);
|
||||
}
|
||||
|
||||
friend std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, const basic_string_view& sv)
|
||||
{
|
||||
os.write(sv.data_,sv.length_);
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
// ==
|
||||
template<class CharT,class Traits>
|
||||
bool operator==(const basic_string_view<CharT,Traits>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) == 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator==(const basic_string_view<CharT,Traits>& lhs,
|
||||
const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) == 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator==(const std::basic_string<CharT,Traits,Allocator>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) == 0;
|
||||
}
|
||||
template<class CharT,class Traits>
|
||||
bool operator==(const basic_string_view<CharT,Traits>& lhs,
|
||||
const CharT* rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) == 0;
|
||||
}
|
||||
template<class CharT,class Traits>
|
||||
bool operator==(const CharT* lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) == 0;
|
||||
}
|
||||
|
||||
// !=
|
||||
template<class CharT,class Traits>
|
||||
bool operator!=(const basic_string_view<CharT,Traits>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) != 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator!=(const basic_string_view<CharT,Traits>& lhs,
|
||||
const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) != 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator!=(const std::basic_string<CharT,Traits,Allocator>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) != 0;
|
||||
}
|
||||
template<class CharT,class Traits>
|
||||
bool operator!=(const basic_string_view<CharT,Traits>& lhs,
|
||||
const CharT* rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) != 0;
|
||||
}
|
||||
template<class CharT,class Traits>
|
||||
bool operator!=(const CharT* lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) != 0;
|
||||
}
|
||||
|
||||
// <=
|
||||
template<class CharT,class Traits>
|
||||
bool operator<=(const basic_string_view<CharT,Traits>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) <= 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator<=(const basic_string_view<CharT,Traits>& lhs,
|
||||
const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) <= 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator<=(const std::basic_string<CharT,Traits,Allocator>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) >= 0;
|
||||
}
|
||||
|
||||
// <
|
||||
template<class CharT,class Traits>
|
||||
bool operator<(const basic_string_view<CharT,Traits>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) < 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator<(const basic_string_view<CharT,Traits>& lhs,
|
||||
const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) < 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator<(const std::basic_string<CharT,Traits,Allocator>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) > 0;
|
||||
}
|
||||
|
||||
// >=
|
||||
template<class CharT,class Traits>
|
||||
bool operator>=(const basic_string_view<CharT,Traits>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) >= 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator>=(const basic_string_view<CharT,Traits>& lhs,
|
||||
const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) >= 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator>=(const std::basic_string<CharT,Traits,Allocator>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) <= 0;
|
||||
}
|
||||
|
||||
// >
|
||||
template<class CharT,class Traits>
|
||||
bool operator>(const basic_string_view<CharT,Traits>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) > 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator>(const basic_string_view<CharT,Traits>& lhs,
|
||||
const std::basic_string<CharT,Traits,Allocator>& rhs) noexcept
|
||||
{
|
||||
return lhs.compare(rhs) > 0;
|
||||
}
|
||||
template<class CharT,class Traits,class Allocator>
|
||||
bool operator>(const std::basic_string<CharT,Traits,Allocator>& lhs,
|
||||
const basic_string_view<CharT,Traits>& rhs) noexcept
|
||||
{
|
||||
return rhs.compare(lhs) < 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
566
scripts/exe/jsoncons/include/jsoncons/detail/write_number.hpp
Normal file
566
scripts/exe/jsoncons/include/jsoncons/detail/write_number.hpp
Normal file
|
|
@ -0,0 +1,566 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_DETAIL_WRITE_NUMBER_HPP
|
||||
#define JSONCONS_DETAIL_WRITE_NUMBER_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <locale>
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <exception>
|
||||
#include <stdio.h> // snprintf
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/json_options.hpp>
|
||||
#include <jsoncons/detail/grisu3.hpp>
|
||||
#include <jsoncons/detail/parse_number.hpp>
|
||||
#include <jsoncons/extension_traits.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace detail {
|
||||
|
||||
inline
|
||||
char to_hex_character(uint8_t c)
|
||||
{
|
||||
return (char)((c < 10) ? ('0' + c) : ('A' - 10 + c));
|
||||
}
|
||||
|
||||
// from_integer
|
||||
|
||||
template<class Integer,class Result>
|
||||
typename std::enable_if<extension_traits::is_integer<Integer>::value,std::size_t>::type
|
||||
from_integer(Integer value, Result& result)
|
||||
{
|
||||
using char_type = typename Result::value_type;
|
||||
|
||||
char_type buf[255];
|
||||
char_type *p = buf;
|
||||
const char_type* last = buf+255;
|
||||
|
||||
bool is_negative = value < 0;
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
*p++ = static_cast<char_type>(48 - (value % 10));
|
||||
}
|
||||
while ((value /= 10) && (p < last));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
do
|
||||
{
|
||||
*p++ = static_cast<char_type>(48 + value % 10);
|
||||
}
|
||||
while ((value /= 10) && (p < last));
|
||||
}
|
||||
JSONCONS_ASSERT(p != last);
|
||||
|
||||
std::size_t count = (p - buf);
|
||||
if (is_negative)
|
||||
{
|
||||
result.push_back('-');
|
||||
++count;
|
||||
}
|
||||
while (--p >= buf)
|
||||
{
|
||||
result.push_back(*p);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// integer_to_string_hex
|
||||
|
||||
template<class Integer,class Result>
|
||||
typename std::enable_if<extension_traits::is_integer<Integer>::value,std::size_t>::type
|
||||
integer_to_string_hex(Integer value, Result& result)
|
||||
{
|
||||
using char_type = typename Result::value_type;
|
||||
|
||||
char_type buf[255];
|
||||
char_type *p = buf;
|
||||
const char_type* last = buf+255;
|
||||
|
||||
bool is_negative = value < 0;
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
*p++ = to_hex_character(0-(value % 16));
|
||||
}
|
||||
while ((value /= 16) && (p < last));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
do
|
||||
{
|
||||
*p++ = to_hex_character(value % 16);
|
||||
}
|
||||
while ((value /= 16) && (p < last));
|
||||
}
|
||||
JSONCONS_ASSERT(p != last);
|
||||
|
||||
std::size_t count = (p - buf);
|
||||
if (is_negative)
|
||||
{
|
||||
result.push_back('-');
|
||||
++count;
|
||||
}
|
||||
while (--p >= buf)
|
||||
{
|
||||
result.push_back(*p);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// write_double
|
||||
|
||||
// fast exponent
|
||||
template <class Result>
|
||||
void fill_exponent(int K, Result& result)
|
||||
{
|
||||
if (K < 0)
|
||||
{
|
||||
result.push_back('-');
|
||||
K = -K;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back('+'); // compatibility with sprintf
|
||||
}
|
||||
|
||||
if (K < 10)
|
||||
{
|
||||
result.push_back('0'); // compatibility with sprintf
|
||||
result.push_back((char)('0' + K));
|
||||
}
|
||||
else if (K < 100)
|
||||
{
|
||||
result.push_back((char)('0' + K / 10)); K %= 10;
|
||||
result.push_back((char)('0' + K));
|
||||
}
|
||||
else if (K < 1000)
|
||||
{
|
||||
result.push_back((char)('0' + K / 100)); K %= 100;
|
||||
result.push_back((char)('0' + K / 10)); K %= 10;
|
||||
result.push_back((char)('0' + K));
|
||||
}
|
||||
else
|
||||
{
|
||||
jsoncons::detail::from_integer(K, result);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Result>
|
||||
void prettify_string(const char *buffer, std::size_t length, int k, int min_exp, int max_exp, Result& result)
|
||||
{
|
||||
int nb_digits = (int)length;
|
||||
int offset;
|
||||
/* v = buffer * 10^k
|
||||
kk is such that 10^(kk-1) <= v < 10^kk
|
||||
this way kk gives the position of the decimal point.
|
||||
*/
|
||||
int kk = nb_digits + k;
|
||||
|
||||
if (nb_digits <= kk && kk <= max_exp)
|
||||
{
|
||||
/* the first digits are already in. Add some 0s and call it a day. */
|
||||
/* the max_exp is a personal choice. Only 16 digits could possibly be relevant.
|
||||
* Basically we want to print 12340000000 rather than 1234.0e7 or 1.234e10 */
|
||||
for (int i = 0; i < nb_digits; ++i)
|
||||
{
|
||||
result.push_back(buffer[i]);
|
||||
}
|
||||
for (int i = nb_digits; i < kk; ++i)
|
||||
{
|
||||
result.push_back('0');
|
||||
}
|
||||
result.push_back('.');
|
||||
result.push_back('0');
|
||||
}
|
||||
else if (0 < kk && kk <= max_exp)
|
||||
{
|
||||
/* comma number. Just insert a '.' at the correct location. */
|
||||
for (int i = 0; i < kk; ++i)
|
||||
{
|
||||
result.push_back(buffer[i]);
|
||||
}
|
||||
result.push_back('.');
|
||||
for (int i = kk; i < nb_digits; ++i)
|
||||
{
|
||||
result.push_back(buffer[i]);
|
||||
}
|
||||
}
|
||||
else if (min_exp < kk && kk <= 0)
|
||||
{
|
||||
offset = 2 - kk;
|
||||
|
||||
result.push_back('0');
|
||||
result.push_back('.');
|
||||
for (int i = 2; i < offset; ++i)
|
||||
result.push_back('0');
|
||||
for (int i = 0; i < nb_digits; ++i)
|
||||
{
|
||||
result.push_back(buffer[i]);
|
||||
}
|
||||
}
|
||||
else if (nb_digits == 1)
|
||||
{
|
||||
result.push_back(buffer[0]);
|
||||
result.push_back('e');
|
||||
fill_exponent(kk - 1, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(buffer[0]);
|
||||
result.push_back('.');
|
||||
for (int i = 1; i < nb_digits; ++i)
|
||||
{
|
||||
result.push_back(buffer[i]);
|
||||
}
|
||||
result.push_back('e');
|
||||
fill_exponent(kk - 1, result);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Result>
|
||||
void dump_buffer(const char *buffer, std::size_t length, char decimal_point, Result& result)
|
||||
{
|
||||
const char *sbeg = buffer;
|
||||
const char *send = sbeg + length;
|
||||
|
||||
if (sbeg != send)
|
||||
{
|
||||
bool needs_dot = true;
|
||||
for (const char* q = sbeg; q < send; ++q)
|
||||
{
|
||||
switch (*q)
|
||||
{
|
||||
case '-':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '+':
|
||||
result.push_back(*q);
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
result.push_back('e');
|
||||
needs_dot = false;
|
||||
break;
|
||||
default:
|
||||
if (*q == decimal_point)
|
||||
{
|
||||
needs_dot = false;
|
||||
result.push_back('.');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (needs_dot)
|
||||
{
|
||||
result.push_back('.');
|
||||
result.push_back('0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Result>
|
||||
bool dtoa_scientific(double val, char decimal_point, Result& result)
|
||||
{
|
||||
if (val == 0)
|
||||
{
|
||||
result.push_back('0');
|
||||
result.push_back('.');
|
||||
result.push_back('0');
|
||||
return true;
|
||||
}
|
||||
|
||||
jsoncons::detail::chars_to to_double_;
|
||||
|
||||
char buffer[100];
|
||||
int precision = std::numeric_limits<double>::digits10;
|
||||
int length = snprintf(buffer, sizeof(buffer), "%1.*e", precision, val);
|
||||
if (length < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (to_double_(buffer, sizeof(buffer)) != val)
|
||||
{
|
||||
const int precision2 = std::numeric_limits<double>::max_digits10;
|
||||
length = snprintf(buffer, sizeof(buffer), "%1.*e", precision2, val);
|
||||
if (length < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
dump_buffer(buffer, static_cast<std::size_t>(length), decimal_point, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Result>
|
||||
bool dtoa_general(double val, char decimal_point, Result& result, std::false_type)
|
||||
{
|
||||
if (val == 0)
|
||||
{
|
||||
result.push_back('0');
|
||||
result.push_back('.');
|
||||
result.push_back('0');
|
||||
return true;
|
||||
}
|
||||
|
||||
jsoncons::detail::chars_to to_double_;
|
||||
|
||||
char buffer[100];
|
||||
int precision = std::numeric_limits<double>::digits10;
|
||||
int length = snprintf(buffer, sizeof(buffer), "%1.*g", precision, val);
|
||||
if (length < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (to_double_(buffer, sizeof(buffer)) != val)
|
||||
{
|
||||
const int precision2 = std::numeric_limits<double>::max_digits10;
|
||||
length = snprintf(buffer, sizeof(buffer), "%1.*g", precision2, val);
|
||||
if (length < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
dump_buffer(buffer, length, decimal_point, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Result>
|
||||
bool dtoa_general(double v, char decimal_point, Result& result, std::true_type)
|
||||
{
|
||||
if (v == 0)
|
||||
{
|
||||
result.push_back('0');
|
||||
result.push_back('.');
|
||||
result.push_back('0');
|
||||
return true;
|
||||
}
|
||||
|
||||
int length = 0;
|
||||
int k;
|
||||
|
||||
char buffer[100];
|
||||
|
||||
double u = std::signbit(v) ? -v : v;
|
||||
if (jsoncons::detail::grisu3(u, buffer, &length, &k))
|
||||
{
|
||||
if (std::signbit(v))
|
||||
{
|
||||
result.push_back('-');
|
||||
}
|
||||
// min exp: -4 is consistent with sprintf
|
||||
// max exp: std::numeric_limits<double>::max_digits10
|
||||
jsoncons::detail::prettify_string(buffer, length, k, -4, std::numeric_limits<double>::max_digits10, result);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dtoa_general(v, decimal_point, result, std::false_type());
|
||||
}
|
||||
}
|
||||
|
||||
template<class Result>
|
||||
bool dtoa_fixed(double val, char decimal_point, Result& result, std::false_type)
|
||||
{
|
||||
if (val == 0)
|
||||
{
|
||||
result.push_back('0');
|
||||
result.push_back('.');
|
||||
result.push_back('0');
|
||||
return true;
|
||||
}
|
||||
|
||||
jsoncons::detail::chars_to to_double_;
|
||||
|
||||
char buffer[100];
|
||||
int precision = std::numeric_limits<double>::digits10;
|
||||
int length = snprintf(buffer, sizeof(buffer), "%1.*f", precision, val);
|
||||
if (length < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (to_double_(buffer, sizeof(buffer)) != val)
|
||||
{
|
||||
const int precision2 = std::numeric_limits<double>::max_digits10;
|
||||
length = snprintf(buffer, sizeof(buffer), "%1.*f", precision2, val);
|
||||
if (length < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
dump_buffer(buffer, length, decimal_point, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Result>
|
||||
bool dtoa_fixed(double v, char decimal_point, Result& result, std::true_type)
|
||||
{
|
||||
if (v == 0)
|
||||
{
|
||||
result.push_back('0');
|
||||
result.push_back('.');
|
||||
result.push_back('0');
|
||||
return true;
|
||||
}
|
||||
|
||||
int length = 0;
|
||||
int k;
|
||||
|
||||
char buffer[100];
|
||||
|
||||
double u = std::signbit(v) ? -v : v;
|
||||
if (jsoncons::detail::grisu3(u, buffer, &length, &k))
|
||||
{
|
||||
if (std::signbit(v))
|
||||
{
|
||||
result.push_back('-');
|
||||
}
|
||||
jsoncons::detail::prettify_string(buffer, length, k, std::numeric_limits<int>::lowest(), (std::numeric_limits<int>::max)(), result);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dtoa_fixed(v, decimal_point, result, std::false_type());
|
||||
}
|
||||
}
|
||||
|
||||
template<class Result>
|
||||
bool dtoa_fixed(double v, char decimal_point, Result& result)
|
||||
{
|
||||
return dtoa_fixed(v, decimal_point, result, std::integral_constant<bool, std::numeric_limits<double>::is_iec559>());
|
||||
}
|
||||
|
||||
template<class Result>
|
||||
bool dtoa_general(double v, char decimal_point, Result& result)
|
||||
{
|
||||
return dtoa_general(v, decimal_point, result, std::integral_constant<bool, std::numeric_limits<double>::is_iec559>());
|
||||
}
|
||||
|
||||
class write_double
|
||||
{
|
||||
private:
|
||||
chars_to to_double_;
|
||||
float_chars_format float_format_;
|
||||
int precision_;
|
||||
char decimal_point_;
|
||||
public:
|
||||
write_double(float_chars_format float_format, int precision)
|
||||
: float_format_(float_format), precision_(precision), decimal_point_('.')
|
||||
{
|
||||
#if !defined(JSONCONS_NO_LOCALECONV)
|
||||
struct lconv *lc = localeconv();
|
||||
if (lc != nullptr && lc->decimal_point[0] != 0)
|
||||
{
|
||||
decimal_point_ = lc->decimal_point[0];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
write_double(const write_double&) = default;
|
||||
|
||||
write_double& operator=(const write_double&) = default;
|
||||
|
||||
template<class Result>
|
||||
std::size_t operator()(double val, Result& result)
|
||||
{
|
||||
std::size_t count = 0;
|
||||
|
||||
char number_buffer[200];
|
||||
int length = 0;
|
||||
|
||||
switch (float_format_)
|
||||
{
|
||||
case float_chars_format::fixed:
|
||||
{
|
||||
if (precision_ > 0)
|
||||
{
|
||||
length = snprintf(number_buffer, sizeof(number_buffer), "%1.*f", precision_, val);
|
||||
if (length < 0)
|
||||
{
|
||||
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
||||
}
|
||||
dump_buffer(number_buffer, length, decimal_point_, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!dtoa_fixed(val, decimal_point_, result))
|
||||
{
|
||||
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case float_chars_format::scientific:
|
||||
{
|
||||
if (precision_ > 0)
|
||||
{
|
||||
length = snprintf(number_buffer, sizeof(number_buffer), "%1.*e", precision_, val);
|
||||
if (length < 0)
|
||||
{
|
||||
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
||||
}
|
||||
dump_buffer(number_buffer, length, decimal_point_, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!dtoa_scientific(val, decimal_point_, result))
|
||||
{
|
||||
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case float_chars_format::general:
|
||||
{
|
||||
if (precision_ > 0)
|
||||
{
|
||||
length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision_, val);
|
||||
if (length < 0)
|
||||
{
|
||||
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
||||
}
|
||||
dump_buffer(number_buffer, length, decimal_point_, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!dtoa_general(val, decimal_point_, result))
|
||||
{
|
||||
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
||||
break;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
315
scripts/exe/jsoncons/include/jsoncons/encode_json.hpp
Normal file
315
scripts/exe/jsoncons/include/jsoncons/encode_json.hpp
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_ENCODE_JSON_HPP
|
||||
#define JSONCONS_ENCODE_JSON_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <memory>
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/encode_traits.hpp>
|
||||
#include <jsoncons/json_cursor.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// to string
|
||||
|
||||
template <class T, class Container>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_char_container<Container>::value>::type
|
||||
encode_json(const T& val,
|
||||
Container& s,
|
||||
const basic_json_encode_options<typename Container::value_type>& options =
|
||||
basic_json_encode_options<typename Container::value_type>())
|
||||
{
|
||||
using char_type = typename Container::value_type;
|
||||
|
||||
basic_compact_json_encoder<char_type, jsoncons::string_sink<Container>> encoder(s, options);
|
||||
val.dump(encoder);
|
||||
}
|
||||
|
||||
template <class T, class Container>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_char_container<Container>::value>::type
|
||||
encode_json(const T& val,
|
||||
Container& s,
|
||||
const basic_json_encode_options<typename Container::value_type>& options = basic_json_encode_options<typename Container::value_type>())
|
||||
{
|
||||
using char_type = typename Container::value_type;
|
||||
|
||||
basic_compact_json_encoder<char_type, jsoncons::string_sink<Container>> encoder(s, options);
|
||||
encode_json(val, encoder);
|
||||
}
|
||||
|
||||
// to stream
|
||||
|
||||
template <class T, class CharT>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value>::type
|
||||
encode_json(const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
const basic_json_encode_options<CharT>& options = basic_json_encode_options<CharT>())
|
||||
{
|
||||
basic_compact_json_encoder<CharT> encoder(os, options);
|
||||
val.dump(encoder);
|
||||
}
|
||||
|
||||
template <class T, class CharT>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value>::type
|
||||
encode_json(const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
const basic_json_encode_options<CharT>& options = basic_json_encode_options<CharT>())
|
||||
{
|
||||
basic_compact_json_encoder<CharT> encoder(os, options);
|
||||
encode_json(val, encoder);
|
||||
}
|
||||
|
||||
// encode_json_pretty
|
||||
|
||||
template <class T, class Container>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_char_container<Container>::value>::type
|
||||
encode_json_pretty(const T& val,
|
||||
Container& s,
|
||||
const basic_json_encode_options<typename Container::value_type>& options = basic_json_encode_options<typename Container::value_type>())
|
||||
{
|
||||
using char_type = typename Container::value_type;
|
||||
|
||||
basic_json_encoder<char_type,jsoncons::string_sink<Container>> encoder(s, options);
|
||||
val.dump(encoder);
|
||||
}
|
||||
|
||||
template <class T, class Container>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_char_container<Container>::value>::type
|
||||
encode_json_pretty(const T& val,
|
||||
Container& s,
|
||||
const basic_json_encode_options<typename Container::value_type>& options = basic_json_encode_options<typename Container::value_type>())
|
||||
{
|
||||
using char_type = typename Container::value_type;
|
||||
basic_json_encoder<char_type,jsoncons::string_sink<Container>> encoder(s, options);
|
||||
encode_json(val, encoder);
|
||||
}
|
||||
|
||||
template <class T, class CharT>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value>::type
|
||||
encode_json_pretty(const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
const basic_json_encode_options<CharT>& options = basic_json_encode_options<CharT>())
|
||||
{
|
||||
basic_json_encoder<CharT> encoder(os, options);
|
||||
val.dump(encoder);
|
||||
}
|
||||
|
||||
template <class T, class CharT>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value>::type
|
||||
encode_json_pretty(const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
const basic_json_encode_options<CharT>& options = basic_json_encode_options<CharT>())
|
||||
{
|
||||
basic_json_encoder<CharT> encoder(os, options);
|
||||
encode_json(val, encoder);
|
||||
}
|
||||
|
||||
template <class T, class CharT>
|
||||
void encode_json(const T& val, basic_json_visitor<CharT>& encoder)
|
||||
{
|
||||
std::error_code ec;
|
||||
encode_traits<T,CharT>::encode(val, encoder, basic_json<CharT>(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
encoder.flush();
|
||||
}
|
||||
|
||||
template <class T, class Container, class TempAllocator>
|
||||
void encode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
Container& s,
|
||||
indenting line_indent = indenting::no_indent)
|
||||
{
|
||||
encode_json(temp_allocator_arg, temp_alloc, val, s, basic_json_encode_options<typename Container::value_type>(), line_indent);
|
||||
}
|
||||
|
||||
// legacy
|
||||
|
||||
template <class T, class Container>
|
||||
void encode_json(const T& val, Container& s, indenting line_indent)
|
||||
{
|
||||
if (line_indent == indenting::indent)
|
||||
{
|
||||
encode_json_pretty(val,s);
|
||||
}
|
||||
else
|
||||
{
|
||||
encode_json(val,s);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Container>
|
||||
void encode_json(const T& val,
|
||||
Container& s,
|
||||
const basic_json_encode_options<typename Container::value_type>& options,
|
||||
indenting line_indent)
|
||||
{
|
||||
if (line_indent == indenting::indent)
|
||||
{
|
||||
encode_json_pretty(val,s,options);
|
||||
}
|
||||
else
|
||||
{
|
||||
encode_json(val,s,options);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class CharT>
|
||||
void encode_json(const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
indenting line_indent)
|
||||
{
|
||||
if (line_indent == indenting::indent)
|
||||
{
|
||||
encode_json_pretty(val, os);
|
||||
}
|
||||
else
|
||||
{
|
||||
encode_json(val, os);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class CharT>
|
||||
void encode_json(const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
const basic_json_encode_options<CharT>& options,
|
||||
indenting line_indent)
|
||||
{
|
||||
if (line_indent == indenting::indent)
|
||||
{
|
||||
encode_json_pretty(val, os, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
encode_json(val, os, options);
|
||||
}
|
||||
}
|
||||
|
||||
//end legacy
|
||||
|
||||
template <class T, class Container, class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_char_container<Container>::value>::type
|
||||
encode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
Container& s,
|
||||
const basic_json_encode_options<typename Container::value_type>& options,
|
||||
indenting line_indent = indenting::no_indent)
|
||||
{
|
||||
using char_type = typename Container::value_type;
|
||||
if (line_indent == indenting::indent)
|
||||
{
|
||||
basic_json_encoder<char_type,jsoncons::string_sink<Container>,TempAllocator> encoder(s, options, temp_alloc);
|
||||
val.dump(encoder);
|
||||
}
|
||||
else
|
||||
{
|
||||
basic_compact_json_encoder<char_type, jsoncons::string_sink<Container>,TempAllocator> encoder(s, options, temp_alloc);
|
||||
val.dump(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Container, class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_char_container<Container>::value>::type
|
||||
encode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
Container& s,
|
||||
const basic_json_encode_options<typename Container::value_type>& options,
|
||||
indenting line_indent)
|
||||
{
|
||||
using char_type = typename Container::value_type;
|
||||
if (line_indent == indenting::indent)
|
||||
{
|
||||
basic_json_encoder<char_type,jsoncons::string_sink<Container>,TempAllocator> encoder(s, options, temp_alloc);
|
||||
encode_json(temp_allocator_arg, temp_alloc, val, encoder);
|
||||
}
|
||||
else
|
||||
{
|
||||
basic_compact_json_encoder<char_type,jsoncons::string_sink<Container>,TempAllocator> encoder(s, options, temp_alloc);
|
||||
encode_json(temp_allocator_arg, temp_alloc, val, encoder);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class CharT, class TempAllocator>
|
||||
void encode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
indenting line_indent = indenting::no_indent)
|
||||
{
|
||||
encode_json(temp_allocator_arg, temp_alloc, val, os, basic_json_encode_options<CharT>(), line_indent);
|
||||
}
|
||||
|
||||
template <class T, class CharT, class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value>::type
|
||||
encode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
const basic_json_encode_options<CharT>& options,
|
||||
indenting line_indent = indenting::no_indent)
|
||||
{
|
||||
if (line_indent == indenting::indent)
|
||||
{
|
||||
basic_json_encoder<CharT,jsoncons::stream_sink<CharT>,TempAllocator> encoder(os, options, temp_alloc);
|
||||
val.dump(encoder);
|
||||
}
|
||||
else
|
||||
{
|
||||
basic_compact_json_encoder<CharT,jsoncons::stream_sink<CharT>,TempAllocator> encoder(os, options, temp_alloc);
|
||||
val.dump(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class CharT, class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value>::type
|
||||
encode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
std::basic_ostream<CharT>& os,
|
||||
const basic_json_encode_options<CharT>& options,
|
||||
indenting line_indent)
|
||||
{
|
||||
if (line_indent == indenting::indent)
|
||||
{
|
||||
basic_json_encoder<CharT> encoder(os, options);
|
||||
encode_json(temp_allocator_arg, temp_alloc, val, encoder);
|
||||
}
|
||||
else
|
||||
{
|
||||
basic_compact_json_encoder<CharT> encoder(os, options);
|
||||
encode_json(temp_allocator_arg, temp_alloc, val, encoder);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class CharT, class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value>::type
|
||||
encode_json(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
basic_json_visitor<CharT>& encoder)
|
||||
{
|
||||
std::error_code ec;
|
||||
basic_json<CharT,sorted_policy,TempAllocator> proto(temp_alloc);
|
||||
encode_traits<T,CharT>::encode(val, encoder, proto, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
encoder.flush();
|
||||
}
|
||||
|
||||
} // jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
378
scripts/exe/jsoncons/include/jsoncons/encode_traits.hpp
Normal file
378
scripts/exe/jsoncons/include/jsoncons/encode_traits.hpp
Normal file
|
|
@ -0,0 +1,378 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_ENCODE_TRAITS_HPP
|
||||
#define JSONCONS_ENCODE_TRAITS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <type_traits> // std::enable_if, std::true_type, std::false_type
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/json_decoder.hpp>
|
||||
#include <jsoncons/json_options.hpp>
|
||||
#include <jsoncons/json_encoder.hpp>
|
||||
#include <jsoncons/json_type_traits.hpp>
|
||||
#include <jsoncons/conv_error.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// encode_traits
|
||||
|
||||
template <class T, class CharT, class Enable = void>
|
||||
struct encode_traits
|
||||
{
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json& proto,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encode(std::integral_constant<bool, extension_traits::is_stateless<typename Json::allocator_type>::value>(),
|
||||
val, encoder, proto, ec);
|
||||
}
|
||||
private:
|
||||
template <class Json>
|
||||
static void encode(std::true_type,
|
||||
const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json& /*proto*/,
|
||||
std::error_code& ec)
|
||||
{
|
||||
auto j = json_type_traits<Json,T>::to_json(val);
|
||||
j.dump(encoder, ec);
|
||||
}
|
||||
template <class Json>
|
||||
static void encode(std::false_type,
|
||||
const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json& proto,
|
||||
std::error_code& ec)
|
||||
{
|
||||
auto j = json_type_traits<Json,T>::to_json(val, proto.get_allocator());
|
||||
j.dump(encoder, ec);
|
||||
}
|
||||
};
|
||||
|
||||
// specializations
|
||||
|
||||
// bool
|
||||
template <class T, class CharT>
|
||||
struct encode_traits<T,CharT,
|
||||
typename std::enable_if<extension_traits::is_bool<T>::value
|
||||
>::type>
|
||||
{
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.bool_value(val,semantic_tag::none,ser_context(),ec);
|
||||
}
|
||||
};
|
||||
|
||||
// uint
|
||||
template <class T, class CharT>
|
||||
struct encode_traits<T,CharT,
|
||||
typename std::enable_if<extension_traits::is_u8_u16_u32_or_u64<T>::value
|
||||
>::type>
|
||||
{
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.uint64_value(val,semantic_tag::none,ser_context(),ec);
|
||||
}
|
||||
};
|
||||
|
||||
// int
|
||||
template <class T, class CharT>
|
||||
struct encode_traits<T,CharT,
|
||||
typename std::enable_if<extension_traits::is_i8_i16_i32_or_i64<T>::value
|
||||
>::type>
|
||||
{
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.int64_value(val,semantic_tag::none,ser_context(),ec);
|
||||
}
|
||||
};
|
||||
|
||||
// float or double
|
||||
template <class T, class CharT>
|
||||
struct encode_traits<T,CharT,
|
||||
typename std::enable_if<extension_traits::is_float_or_double<T>::value
|
||||
>::type>
|
||||
{
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.double_value(val,semantic_tag::none,ser_context(),ec);
|
||||
}
|
||||
};
|
||||
|
||||
// string
|
||||
template <class T, class CharT>
|
||||
struct encode_traits<T,CharT,
|
||||
typename std::enable_if<extension_traits::is_string<T>::value &&
|
||||
std::is_same<typename T::value_type,CharT>::value
|
||||
>::type>
|
||||
{
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.string_value(val,semantic_tag::none,ser_context(),ec);
|
||||
}
|
||||
};
|
||||
template <class T, class CharT>
|
||||
struct encode_traits<T,CharT,
|
||||
typename std::enable_if<extension_traits::is_string<T>::value &&
|
||||
!std::is_same<typename T::value_type,CharT>::value
|
||||
>::type>
|
||||
{
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
std::basic_string<CharT> s;
|
||||
unicode_traits::convert(val.data(), val.size(), s);
|
||||
encoder.string_value(s,semantic_tag::none,ser_context(),ec);
|
||||
}
|
||||
};
|
||||
|
||||
// std::pair
|
||||
|
||||
template <class T1, class T2, class CharT>
|
||||
struct encode_traits<std::pair<T1, T2>, CharT>
|
||||
{
|
||||
using value_type = std::pair<T1, T2>;
|
||||
|
||||
template <class Json>
|
||||
static void encode(const value_type& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json& proto,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.begin_array(2,semantic_tag::none,ser_context(),ec);
|
||||
if (ec) return;
|
||||
encode_traits<T1,CharT>::encode(val.first, encoder, proto, ec);
|
||||
if (ec) return;
|
||||
encode_traits<T2,CharT>::encode(val.second, encoder, proto, ec);
|
||||
if (ec) return;
|
||||
encoder.end_array(ser_context(),ec);
|
||||
}
|
||||
};
|
||||
|
||||
// std::tuple
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<size_t Pos, std::size_t Size, class Json, class Tuple>
|
||||
struct json_serialize_tuple_helper
|
||||
{
|
||||
using char_type = typename Json::char_type;
|
||||
using element_type = typename std::tuple_element<Size-Pos, Tuple>::type;
|
||||
using next = json_serialize_tuple_helper<Pos-1, Size, Json, Tuple>;
|
||||
|
||||
static void encode(const Tuple& tuple,
|
||||
basic_json_visitor<char_type>& encoder,
|
||||
const Json& proto,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encode_traits<element_type,char_type>::encode(std::get<Size-Pos>(tuple), encoder, proto, ec);
|
||||
if (ec) return;
|
||||
next::encode(tuple, encoder, proto, ec);
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t Size, class Json, class Tuple>
|
||||
struct json_serialize_tuple_helper<0, Size, Json, Tuple>
|
||||
{
|
||||
using char_type = typename Json::char_type;
|
||||
static void encode(const Tuple&,
|
||||
basic_json_visitor<char_type>&,
|
||||
const Json&,
|
||||
std::error_code&)
|
||||
{
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
|
||||
template <class CharT, typename... E>
|
||||
struct encode_traits<std::tuple<E...>, CharT>
|
||||
{
|
||||
using value_type = std::tuple<E...>;
|
||||
static constexpr std::size_t size = sizeof...(E);
|
||||
|
||||
template <class Json>
|
||||
static void encode(const value_type& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json& proto,
|
||||
std::error_code& ec)
|
||||
{
|
||||
using helper = jsoncons::detail::json_serialize_tuple_helper<size, size, Json, std::tuple<E...>>;
|
||||
encoder.begin_array(size,semantic_tag::none,ser_context(),ec);
|
||||
if (ec) return;
|
||||
helper::encode(val, encoder, proto, ec);
|
||||
if (ec) return;
|
||||
encoder.end_array(ser_context(),ec);
|
||||
}
|
||||
};
|
||||
|
||||
// vector like
|
||||
template <class T, class CharT>
|
||||
struct encode_traits<T,CharT,
|
||||
typename std::enable_if<!is_json_type_traits_declared<T>::value &&
|
||||
extension_traits::is_list_like<T>::value &&
|
||||
!extension_traits::is_typed_array<T>::value
|
||||
>::type>
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json& proto,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.begin_array(val.size(),semantic_tag::none,ser_context(),ec);
|
||||
if (ec) return;
|
||||
for (auto it = std::begin(val); it != std::end(val); ++it)
|
||||
{
|
||||
encode_traits<value_type,CharT>::encode(*it, encoder, proto, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
encoder.end_array(ser_context(), ec);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class CharT>
|
||||
struct encode_traits<T,CharT,
|
||||
typename std::enable_if<!is_json_type_traits_declared<T>::value &&
|
||||
extension_traits::is_list_like<T>::value &&
|
||||
extension_traits::is_typed_array<T>::value
|
||||
>::type>
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json&,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.typed_array(jsoncons::span<const value_type>(val), semantic_tag::none, ser_context(), ec);
|
||||
}
|
||||
};
|
||||
|
||||
// std::array
|
||||
|
||||
template <class T, class CharT, std::size_t N>
|
||||
struct encode_traits<std::array<T,N>,CharT>
|
||||
{
|
||||
using value_type = typename std::array<T,N>::value_type;
|
||||
|
||||
template <class Json>
|
||||
static void encode(const std::array<T, N>& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json& proto,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.begin_array(val.size(),semantic_tag::none,ser_context(),ec);
|
||||
if (ec) return;
|
||||
for (auto it = std::begin(val); it != std::end(val); ++it)
|
||||
{
|
||||
encode_traits<value_type,CharT>::encode(*it, encoder, proto, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
encoder.end_array(ser_context(),ec);
|
||||
}
|
||||
};
|
||||
|
||||
// map like
|
||||
|
||||
template <class T, class CharT>
|
||||
struct encode_traits<T,CharT,
|
||||
typename std::enable_if<!is_json_type_traits_declared<T>::value &&
|
||||
extension_traits::is_map_like<T>::value &&
|
||||
extension_traits::is_constructible_from_const_pointer_and_size<typename T::key_type>::value
|
||||
>::type>
|
||||
{
|
||||
using mapped_type = typename T::mapped_type;
|
||||
using value_type = typename T::value_type;
|
||||
using key_type = typename T::key_type;
|
||||
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json& proto,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.begin_object(val.size(), semantic_tag::none, ser_context(), ec);
|
||||
if (ec) return;
|
||||
for (auto it = std::begin(val); it != std::end(val); ++it)
|
||||
{
|
||||
encoder.key(it->first);
|
||||
encode_traits<mapped_type,CharT>::encode(it->second, encoder, proto, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
encoder.end_object(ser_context(), ec);
|
||||
if (ec) return;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class CharT>
|
||||
struct encode_traits<T,CharT,
|
||||
typename std::enable_if<!is_json_type_traits_declared<T>::value &&
|
||||
extension_traits::is_map_like<T>::value &&
|
||||
std::is_integral<typename T::key_type>::value
|
||||
>::type>
|
||||
{
|
||||
using mapped_type = typename T::mapped_type;
|
||||
using value_type = typename T::value_type;
|
||||
using key_type = typename T::key_type;
|
||||
|
||||
template <class Json>
|
||||
static void encode(const T& val,
|
||||
basic_json_visitor<CharT>& encoder,
|
||||
const Json& proto,
|
||||
std::error_code& ec)
|
||||
{
|
||||
encoder.begin_object(val.size(), semantic_tag::none, ser_context(), ec);
|
||||
if (ec) return;
|
||||
for (auto it = std::begin(val); it != std::end(val); ++it)
|
||||
{
|
||||
std::basic_string<typename Json::char_type> s;
|
||||
jsoncons::detail::from_integer(it->first,s);
|
||||
encoder.key(s);
|
||||
encode_traits<mapped_type,CharT>::encode(it->second, encoder, proto, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
encoder.end_object(ser_context(), ec);
|
||||
if (ec) return;
|
||||
}
|
||||
};
|
||||
|
||||
} // jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
884
scripts/exe/jsoncons/include/jsoncons/extension_traits.hpp
Normal file
884
scripts/exe/jsoncons/include/jsoncons/extension_traits.hpp
Normal file
|
|
@ -0,0 +1,884 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_TRAITS_EXTENSION_HPP
|
||||
#define JSONCONS_TRAITS_EXTENSION_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <type_traits> // std::enable_if, std::true_type
|
||||
#include <memory>
|
||||
#include <iterator> // std::iterator_traits
|
||||
#include <exception>
|
||||
#include <array> // std::array
|
||||
#include <cstddef> // std::byte
|
||||
#include <utility> // std::declval
|
||||
#include <climits> // CHAR_BIT
|
||||
#include <jsoncons/config/compiler_support.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace extension_traits {
|
||||
|
||||
// is_char8
|
||||
template <typename CharT, typename Enable=void>
|
||||
struct is_char8 : std::false_type {};
|
||||
|
||||
template <typename CharT>
|
||||
struct is_char8<CharT, typename std::enable_if<std::is_integral<CharT>::value &&
|
||||
!std::is_same<CharT,bool>::value &&
|
||||
sizeof(uint8_t) == sizeof(CharT)>::type> : std::true_type {};
|
||||
|
||||
// is_char16
|
||||
template <typename CharT, typename Enable=void>
|
||||
struct is_char16 : std::false_type {};
|
||||
|
||||
template <typename CharT>
|
||||
struct is_char16<CharT, typename std::enable_if<std::is_integral<CharT>::value &&
|
||||
!std::is_same<CharT,bool>::value &&
|
||||
(std::is_same<CharT,char16_t>::value || sizeof(uint16_t) == sizeof(CharT))>::type> : std::true_type {};
|
||||
|
||||
// is_char32
|
||||
template <typename CharT, typename Enable=void>
|
||||
struct is_char32 : std::false_type {};
|
||||
|
||||
template <typename CharT>
|
||||
struct is_char32<CharT, typename std::enable_if<std::is_integral<CharT>::value &&
|
||||
!std::is_same<CharT,bool>::value &&
|
||||
(std::is_same<CharT,char32_t>::value || (!std::is_same<CharT,char16_t>::value && sizeof(uint32_t) == sizeof(CharT)))>::type> : std::true_type {};
|
||||
|
||||
// is_int128
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_int128_type : std::false_type {};
|
||||
|
||||
#if defined(JSONCONS_HAS_INT128)
|
||||
template <class T>
|
||||
struct is_int128_type<T,typename std::enable_if<std::is_same<T,int128_type>::value>::type> : std::true_type {};
|
||||
#endif
|
||||
|
||||
// is_unsigned_integer
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_uint128_type : std::false_type {};
|
||||
|
||||
#if defined (JSONCONS_HAS_INT128)
|
||||
template <class T>
|
||||
struct is_uint128_type<T,typename std::enable_if<std::is_same<T,uint128_type>::value>::type> : std::true_type {};
|
||||
#endif
|
||||
|
||||
template <class T, class Enable = void>
|
||||
class integer_limits
|
||||
{
|
||||
public:
|
||||
static constexpr bool is_specialized = false;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class integer_limits<T,typename std::enable_if<std::is_integral<T>::value && !std::is_same<T,bool>::value>::type>
|
||||
{
|
||||
public:
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = std::numeric_limits<T>::is_signed;
|
||||
static constexpr int digits = std::numeric_limits<T>::digits;
|
||||
static constexpr std::size_t buffer_size = static_cast<std::size_t>(sizeof(T)*CHAR_BIT*0.302) + 3;
|
||||
|
||||
static constexpr T(max)() noexcept
|
||||
{
|
||||
return (std::numeric_limits<T>::max)();
|
||||
}
|
||||
static constexpr T(min)() noexcept
|
||||
{
|
||||
return (std::numeric_limits<T>::min)();
|
||||
}
|
||||
static constexpr T lowest() noexcept
|
||||
{
|
||||
return std::numeric_limits<T>::lowest();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class integer_limits<T,typename std::enable_if<!std::is_integral<T>::value && is_int128_type<T>::value>::type>
|
||||
{
|
||||
public:
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr int digits = sizeof(T)*CHAR_BIT - 1;
|
||||
static constexpr std::size_t buffer_size = (sizeof(T)*CHAR_BIT*0.302) + 3;
|
||||
|
||||
static constexpr T(max)() noexcept
|
||||
{
|
||||
return (((((T)1 << (digits - 1)) - 1) << 1) + 1);
|
||||
}
|
||||
static constexpr T(min)() noexcept
|
||||
{
|
||||
return -(max)() - 1;
|
||||
}
|
||||
static constexpr T lowest() noexcept
|
||||
{
|
||||
return (min)();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class integer_limits<T,typename std::enable_if<!std::is_integral<T>::value && is_uint128_type<T>::value>::type>
|
||||
{
|
||||
public:
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr int digits = sizeof(T)*CHAR_BIT;
|
||||
|
||||
static constexpr T(max)() noexcept
|
||||
{
|
||||
return T(T(~0));
|
||||
}
|
||||
static constexpr T(min)() noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static constexpr T lowest() noexcept
|
||||
{
|
||||
return std::numeric_limits<T>::lowest();
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef JSONCONS_HAS_VOID_T
|
||||
// follows https://en.cppreference.com/w/cpp/types/void_t
|
||||
template<typename... Ts> struct make_void { typedef void type;};
|
||||
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
|
||||
#else
|
||||
using void_t = std::void_t;
|
||||
#endif
|
||||
|
||||
// follows http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4436.pdf
|
||||
|
||||
// detector
|
||||
|
||||
// primary template handles all types not supporting the archetypal Op
|
||||
template<
|
||||
class Default,
|
||||
class, // always void; supplied externally
|
||||
template<class...> class Op,
|
||||
class... Args
|
||||
>
|
||||
struct detector
|
||||
{
|
||||
constexpr static auto value = false;
|
||||
using type = Default;
|
||||
};
|
||||
|
||||
// specialization recognizes and handles only types supporting Op
|
||||
template<
|
||||
class Default,
|
||||
template<class...> class Op,
|
||||
class... Args
|
||||
>
|
||||
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
|
||||
{
|
||||
constexpr static auto value = true;
|
||||
using type = Op<Args...>;
|
||||
};
|
||||
|
||||
// is_detected, is_detected_t
|
||||
|
||||
template< template<class...> class Op, class... Args >
|
||||
using
|
||||
is_detected = detector<void, void, Op, Args...>;
|
||||
|
||||
template< template<class...> class Op, class... Args >
|
||||
using
|
||||
is_detected_t = typename is_detected<Op, Args...>::type;
|
||||
|
||||
// detected_or, detected_or_t
|
||||
|
||||
template< class Default, template<class...> class Op, class... Args >
|
||||
using
|
||||
detected_or = detector<Default, void, Op, Args...>;
|
||||
|
||||
template< class Default, template<class...> class Op, class... Args >
|
||||
using
|
||||
detected_or_t = typename detected_or<Default, Op, Args...>::type;
|
||||
|
||||
// is_detected_exact
|
||||
|
||||
template< class Expected, template<class...> class Op, class... Args >
|
||||
using
|
||||
is_detected_exact = std::is_same< Expected, is_detected_t<Op, Args...> >;
|
||||
|
||||
// is_detected_convertible
|
||||
|
||||
template< class To, template<class...> class Op, class... Args >
|
||||
using
|
||||
is_detected_convertible = std::is_convertible< is_detected_t<Op, Args...>, To >;
|
||||
|
||||
template <typename T>
|
||||
struct is_stateless
|
||||
: public std::integral_constant<bool,
|
||||
(std::is_default_constructible<T>::value &&
|
||||
std::is_empty<T>::value)>
|
||||
{};
|
||||
|
||||
// to_plain_pointer
|
||||
|
||||
template<class Pointer> inline
|
||||
typename std::pointer_traits<Pointer>::element_type* to_plain_pointer(Pointer ptr)
|
||||
{
|
||||
return (std::addressof(*ptr));
|
||||
}
|
||||
|
||||
template<class T> inline
|
||||
T * to_plain_pointer(T * ptr)
|
||||
{
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
// is_std_byte
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_std_byte : std::false_type {};
|
||||
#if defined(JSONCONS_HAS_STD_BYTE)
|
||||
template <class T>
|
||||
struct is_std_byte<T,
|
||||
typename std::enable_if<std::is_same<T,std::byte>::value
|
||||
>::type> : std::true_type {};
|
||||
#endif
|
||||
// is_byte
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_byte : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_byte<T,
|
||||
typename std::enable_if<std::is_same<T,char>::value ||
|
||||
std::is_same<T,signed char>::value ||
|
||||
std::is_same<T,unsigned char>::value ||
|
||||
is_std_byte<T>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_character
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_character : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_character<T,
|
||||
typename std::enable_if<std::is_same<T,char>::value ||
|
||||
std::is_same<T,wchar_t>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_narrow_character
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_narrow_character : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_narrow_character<T,
|
||||
typename std::enable_if<is_character<T>::value && (sizeof(T) == sizeof(char))
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_wide_character
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_wide_character : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_wide_character<T,
|
||||
typename std::enable_if<is_character<T>::value && (sizeof(T) != sizeof(char))
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// From boost
|
||||
namespace ut_detail {
|
||||
|
||||
template<typename T>
|
||||
struct is_cstring_impl : public std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct is_cstring_impl<T const*> : public is_cstring_impl<T*> {};
|
||||
|
||||
template<typename T>
|
||||
struct is_cstring_impl<T const* const> : public is_cstring_impl<T*> {};
|
||||
|
||||
template<>
|
||||
struct is_cstring_impl<char*> : public std::true_type {};
|
||||
|
||||
template<>
|
||||
struct is_cstring_impl<wchar_t*> : public std::true_type {};
|
||||
|
||||
} // namespace ut_detail
|
||||
|
||||
template<typename T>
|
||||
struct is_cstring : public ut_detail::is_cstring_impl<typename std::decay<T>::type> {};
|
||||
|
||||
// is_bool
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_bool : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_bool<T,
|
||||
typename std::enable_if<std::is_same<T,bool>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_u8_u16_u32_or_u64
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_u8_u16_u32_or_u64 : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_u8_u16_u32_or_u64<T,
|
||||
typename std::enable_if<std::is_same<T,uint8_t>::value ||
|
||||
std::is_same<T,uint16_t>::value ||
|
||||
std::is_same<T,uint32_t>::value ||
|
||||
std::is_same<T,uint64_t>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_int
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_i8_i16_i32_or_i64 : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_i8_i16_i32_or_i64<T,
|
||||
typename std::enable_if<std::is_same<T,int8_t>::value ||
|
||||
std::is_same<T,int16_t>::value ||
|
||||
std::is_same<T,int32_t>::value ||
|
||||
std::is_same<T,int64_t>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_float_or_double
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_float_or_double : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_float_or_double<T,
|
||||
typename std::enable_if<std::is_same<T,float>::value ||
|
||||
std::is_same<T,double>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// make_unsigned
|
||||
template <class T>
|
||||
struct make_unsigned_impl {using type = typename std::make_unsigned<T>::type;};
|
||||
|
||||
#if defined(JSONCONS_HAS_INT128)
|
||||
template <>
|
||||
struct make_unsigned_impl<int128_type> {using type = uint128_type;};
|
||||
template <>
|
||||
struct make_unsigned_impl<uint128_type> {using type = uint128_type;};
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
struct make_unsigned
|
||||
: make_unsigned_impl<typename std::remove_cv<T>::type>
|
||||
{};
|
||||
|
||||
// is_integer
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_integer : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_integer<T,typename std::enable_if<integer_limits<T>::is_specialized>::type> : std::true_type {};
|
||||
|
||||
// is_signed_integer
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_signed_integer : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_signed_integer<T, typename std::enable_if<integer_limits<T>::is_specialized &&
|
||||
integer_limits<T>::is_signed>::type> : std::true_type {};
|
||||
|
||||
// is_unsigned_integer
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_unsigned_integer : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_unsigned_integer<T,
|
||||
typename std::enable_if<integer_limits<T>::is_specialized &&
|
||||
!integer_limits<T>::is_signed>::type> : std::true_type {};
|
||||
|
||||
// is_primitive
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_primitive : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_primitive<T,
|
||||
typename std::enable_if<is_integer<T>::value ||
|
||||
is_bool<T>::value ||
|
||||
std::is_floating_point<T>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// Containers
|
||||
|
||||
template <class Container>
|
||||
using
|
||||
container_npos_t = decltype(Container::npos);
|
||||
|
||||
template <class Container>
|
||||
using
|
||||
container_allocator_type_t = typename Container::allocator_type;
|
||||
|
||||
template <class Container>
|
||||
using
|
||||
container_mapped_type_t = typename Container::mapped_type;
|
||||
|
||||
template <class Container>
|
||||
using
|
||||
container_key_type_t = typename Container::key_type;
|
||||
|
||||
template <class Container>
|
||||
using
|
||||
container_value_type_t = typename std::iterator_traits<typename Container::iterator>::value_type;
|
||||
|
||||
template <class Container>
|
||||
using
|
||||
container_char_traits_t = typename Container::traits_type::char_type;
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
container_push_back_t = decltype(std::declval<Container>().push_back(std::declval<typename Container::value_type>()));
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
container_push_front_t = decltype(std::declval<Container>().push_front(std::declval<typename Container::value_type>()));
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
container_insert_t = decltype(std::declval<Container>().insert(std::declval<typename Container::value_type>()));
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
container_reserve_t = decltype(std::declval<Container>().reserve(typename Container::size_type()));
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
container_data_t = decltype(std::declval<Container>().data());
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
container_size_t = decltype(std::declval<Container>().size());
|
||||
|
||||
// has_allocator_type
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct has_allocator_type : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct has_allocator_type<T,
|
||||
typename std::enable_if<is_detected<container_allocator_type_t,T>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_string_or_string_view
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_string_or_string_view : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_string_or_string_view<T,
|
||||
typename std::enable_if<is_character<typename T::value_type>::value &&
|
||||
is_detected_exact<typename T::value_type,container_char_traits_t,T>::value &&
|
||||
is_detected<container_npos_t,T>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_string
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_string : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_string<T,
|
||||
typename std::enable_if<is_string_or_string_view<T>::value &&
|
||||
has_allocator_type<T>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_string_view
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_string_view : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_string_view<T,
|
||||
typename std::enable_if<is_string_or_string_view<T>::value &&
|
||||
!is_detected<container_allocator_type_t,T>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_map_like
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_map_like : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_map_like<T,
|
||||
typename std::enable_if<is_detected<container_mapped_type_t,T>::value &&
|
||||
is_detected<container_allocator_type_t,T>::value &&
|
||||
is_detected<container_key_type_t,T>::value &&
|
||||
is_detected<container_value_type_t,T>::value
|
||||
>::type>
|
||||
: std::true_type {};
|
||||
|
||||
// is_std_array
|
||||
template<class T>
|
||||
struct is_std_array : std::false_type {};
|
||||
|
||||
template<class E, std::size_t N>
|
||||
struct is_std_array<std::array<E, N>> : std::true_type {};
|
||||
|
||||
// is_list_like
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_list_like : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_list_like<T,
|
||||
typename std::enable_if<is_detected<container_value_type_t,T>::value &&
|
||||
is_detected<container_allocator_type_t,T>::value &&
|
||||
!is_std_array<T>::value &&
|
||||
!is_detected_exact<typename T::value_type,container_char_traits_t,T>::value &&
|
||||
!is_map_like<T>::value
|
||||
>::type>
|
||||
: std::true_type {};
|
||||
|
||||
// is_constructible_from_const_pointer_and_size
|
||||
|
||||
template <class T, class Enable=void>
|
||||
struct is_constructible_from_const_pointer_and_size : std::false_type {};
|
||||
|
||||
template <class T>
|
||||
struct is_constructible_from_const_pointer_and_size<T,
|
||||
typename std::enable_if<std::is_constructible<T,typename T::const_pointer,typename T::size_type>::value
|
||||
>::type>
|
||||
: std::true_type {};
|
||||
|
||||
// has_reserve
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
has_reserve = is_detected<container_reserve_t, Container>;
|
||||
|
||||
// is_back_insertable
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
is_back_insertable = is_detected<container_push_back_t, Container>;
|
||||
|
||||
// is_front_insertable
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
is_front_insertable = is_detected<container_push_front_t, Container>;
|
||||
|
||||
// is_insertable
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
is_insertable = is_detected<container_insert_t, Container>;
|
||||
|
||||
// has_data, has_data_exact
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
has_data = is_detected<container_data_t, Container>;
|
||||
|
||||
template<class Ret, class Container>
|
||||
using
|
||||
has_data_exact = is_detected_exact<Ret, container_data_t, Container>;
|
||||
|
||||
// has_size
|
||||
|
||||
template<class Container>
|
||||
using
|
||||
has_size = is_detected<container_size_t, Container>;
|
||||
|
||||
// has_data_and_size
|
||||
|
||||
template<class Container>
|
||||
struct has_data_and_size
|
||||
{
|
||||
static constexpr bool value = has_data<Container>::value && has_size<Container>::value;
|
||||
};
|
||||
|
||||
// is_byte_sequence
|
||||
|
||||
template <class Container, class Enable=void>
|
||||
struct is_byte_sequence : std::false_type {};
|
||||
|
||||
template <class Container>
|
||||
struct is_byte_sequence<Container,
|
||||
typename std::enable_if<has_data_exact<const typename Container::value_type*,const Container>::value &&
|
||||
has_size<Container>::value &&
|
||||
is_byte<typename Container::value_type>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_char_sequence
|
||||
|
||||
template <class Container, class Enable=void>
|
||||
struct is_char_sequence : std::false_type {};
|
||||
|
||||
template <class Container>
|
||||
struct is_char_sequence<Container,
|
||||
typename std::enable_if<has_data_exact<const typename Container::value_type*,const Container>::value &&
|
||||
has_size<Container>::value &&
|
||||
is_character<typename Container::value_type>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_sequence_of
|
||||
|
||||
template <class Container, class ValueT, class Enable=void>
|
||||
struct is_sequence_of : std::false_type {};
|
||||
|
||||
template <class Container, class ValueT>
|
||||
struct is_sequence_of<Container,ValueT,
|
||||
typename std::enable_if<has_data_exact<const typename Container::value_type*,const Container>::value &&
|
||||
has_size<Container>::value &&
|
||||
std::is_same<typename Container::value_type,ValueT>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_back_insertable_byte_container
|
||||
|
||||
template <class Container, class Enable=void>
|
||||
struct is_back_insertable_byte_container : std::false_type {};
|
||||
|
||||
template <class Container>
|
||||
struct is_back_insertable_byte_container<Container,
|
||||
typename std::enable_if<is_back_insertable<Container>::value &&
|
||||
is_byte<typename Container::value_type>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_back_insertable_char_container
|
||||
|
||||
template <class Container, class Enable=void>
|
||||
struct is_back_insertable_char_container : std::false_type {};
|
||||
|
||||
template <class Container>
|
||||
struct is_back_insertable_char_container<Container,
|
||||
typename std::enable_if<is_back_insertable<Container>::value &&
|
||||
is_character<typename Container::value_type>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_back_insertable_container_of
|
||||
|
||||
template <class Container, class ValueT, class Enable=void>
|
||||
struct is_back_insertable_container_of : std::false_type {};
|
||||
|
||||
template <class Container, class ValueT>
|
||||
struct is_back_insertable_container_of<Container, ValueT,
|
||||
typename std::enable_if<is_back_insertable<Container>::value &&
|
||||
std::is_same<typename Container::value_type,ValueT>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
// is_c_array
|
||||
|
||||
template<class T>
|
||||
struct is_c_array : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_c_array<T[]> : std::true_type {};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct is_c_array<T[N]> : std::true_type {};
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<class C, class Enable=void>
|
||||
struct is_typed_array : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_typed_array
|
||||
<
|
||||
T,
|
||||
typename std::enable_if<is_list_like<T>::value &&
|
||||
(std::is_same<typename std::decay<typename T::value_type>::type,uint8_t>::value ||
|
||||
std::is_same<typename std::decay<typename T::value_type>::type,uint16_t>::value ||
|
||||
std::is_same<typename std::decay<typename T::value_type>::type,uint32_t>::value ||
|
||||
std::is_same<typename std::decay<typename T::value_type>::type,uint64_t>::value ||
|
||||
std::is_same<typename std::decay<typename T::value_type>::type,int8_t>::value ||
|
||||
std::is_same<typename std::decay<typename T::value_type>::type,int16_t>::value ||
|
||||
std::is_same<typename std::decay<typename T::value_type>::type,int32_t>::value ||
|
||||
std::is_same<typename std::decay<typename T::value_type>::type,int64_t>::value ||
|
||||
std::is_same<typename std::decay<typename T::value_type>::type,float_t>::value ||
|
||||
std::is_same<typename std::decay<typename T::value_type>::type,double_t>::value)>::type
|
||||
> : std::true_type{};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <typename T>
|
||||
using is_typed_array = impl::is_typed_array<typename std::decay<T>::type>;
|
||||
|
||||
// is_compatible_element
|
||||
|
||||
template<class Container, class Element, class Enable=void>
|
||||
struct is_compatible_element : std::false_type {};
|
||||
|
||||
template<class Container, class Element>
|
||||
struct is_compatible_element
|
||||
<
|
||||
Container, Element,
|
||||
typename std::enable_if<has_data<Container>::value>::type>
|
||||
: std::is_convertible< typename std::remove_pointer<decltype(std::declval<Container>().data() )>::type(*)[], Element(*)[]>
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
using
|
||||
construct_from_string_t = decltype(T(std::string{}));
|
||||
|
||||
|
||||
template<class T>
|
||||
using
|
||||
is_constructible_from_string = is_detected<construct_from_string_t,T>;
|
||||
|
||||
template<typename T, typename Data, typename Size>
|
||||
using
|
||||
construct_from_data_size_t = decltype(T(static_cast<Data>(nullptr),Size{}));
|
||||
|
||||
|
||||
template<class T, typename Data, typename Size>
|
||||
using
|
||||
is_constructible_from_data_size = is_detected<construct_from_data_size_t,T,Data,Size>;
|
||||
|
||||
// is_unary_function_object
|
||||
// is_unary_function_object_exact
|
||||
|
||||
template<class FunctionObject, class Arg>
|
||||
using
|
||||
unary_function_object_t = decltype(std::declval<FunctionObject>()(std::declval<Arg>()));
|
||||
|
||||
template<class FunctionObject, class Arg>
|
||||
using
|
||||
is_unary_function_object = is_detected<unary_function_object_t, FunctionObject, Arg>;
|
||||
|
||||
template<class FunctionObject, class T, class Arg>
|
||||
using
|
||||
is_unary_function_object_exact = is_detected_exact<T,unary_function_object_t, FunctionObject, Arg>;
|
||||
|
||||
// is_binary_function_object
|
||||
// is_binary_function_object_exact
|
||||
|
||||
template<class FunctionObject, class Arg1, class Arg2>
|
||||
using
|
||||
binary_function_object_t = decltype(std::declval<FunctionObject>()(std::declval<Arg1>(),std::declval<Arg2>()));
|
||||
|
||||
template<class FunctionObject, class Arg1, class Arg2>
|
||||
using
|
||||
is_binary_function_object = is_detected<binary_function_object_t, FunctionObject, Arg1, Arg2>;
|
||||
|
||||
template<class FunctionObject, class T, class Arg1, class Arg2>
|
||||
using
|
||||
is_binary_function_object_exact = is_detected_exact<T,binary_function_object_t, FunctionObject, Arg1, Arg2>;
|
||||
|
||||
template <class Source, class Enable=void>
|
||||
struct is_convertible_to_string_view : std::false_type {};
|
||||
|
||||
template <class Source>
|
||||
struct is_convertible_to_string_view<Source,typename std::enable_if<is_string_or_string_view<Source>::value ||
|
||||
is_cstring<Source>::value
|
||||
>::type> : std::true_type {};
|
||||
|
||||
#if defined(JSONCONS_HAS_2017)
|
||||
template <typename T>
|
||||
using is_nothrow_swappable = std::is_nothrow_swappable<T>;
|
||||
#else
|
||||
template <typename T>
|
||||
struct is_nothrow_swappable {
|
||||
static const bool value = noexcept(swap(std::declval<T&>(), std::declval<T&>()));
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(JSONCONS_HAS_2014)
|
||||
template <class T>
|
||||
using alignment_of = std::alignment_of<T>;
|
||||
|
||||
template< class T, T... Ints >
|
||||
using integer_sequence = std::integer_sequence<T,Ints...>;
|
||||
|
||||
template <T ... Inds>
|
||||
using index_sequence = std::index_sequence<Inds...>;
|
||||
|
||||
template <class T, T N>
|
||||
using make_integer_sequence = std::make_integer_sequence<T,N>;
|
||||
|
||||
template <std::size_t N>
|
||||
using make_index_sequence = std::make_index_sequence<N>;
|
||||
|
||||
template<class... T>
|
||||
using index_sequence_for = std::index_sequence_for<T...>;
|
||||
|
||||
#else
|
||||
template <class T>
|
||||
struct alignment_of
|
||||
: std::integral_constant<std::size_t, alignof(typename std::remove_all_extents<T>::type)> {};
|
||||
|
||||
template <class T, T... Ints>
|
||||
class integer_sequence
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
static_assert(std::is_integral<value_type>::value, "not integral type");
|
||||
static constexpr std::size_t size() noexcept
|
||||
{
|
||||
return sizeof...(Ints);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t... Inds>
|
||||
using index_sequence = integer_sequence<std::size_t, Inds...>;
|
||||
namespace detail_ {
|
||||
template <class T, T Begin, T End, bool>
|
||||
struct IntSeqImpl {
|
||||
using TValue = T;
|
||||
static_assert(std::is_integral<TValue>::value, "not integral type");
|
||||
static_assert(Begin >= 0 && Begin < End, "unexpected argument (Begin<0 || Begin<=End)");
|
||||
|
||||
template <class, class>
|
||||
struct IntSeqCombiner;
|
||||
|
||||
template <TValue... Inds0, TValue... Inds1>
|
||||
struct IntSeqCombiner<integer_sequence<TValue, Inds0...>, integer_sequence<TValue, Inds1...>> {
|
||||
using TResult = integer_sequence<TValue, Inds0..., Inds1...>;
|
||||
};
|
||||
|
||||
using TResult =
|
||||
typename IntSeqCombiner<typename IntSeqImpl<TValue, Begin, Begin + (End - Begin) / 2,
|
||||
(End - Begin) / 2 == 1>::TResult,
|
||||
typename IntSeqImpl<TValue, Begin + (End - Begin) / 2, End,
|
||||
(End - Begin + 1) / 2 == 1>::TResult>::TResult;
|
||||
};
|
||||
|
||||
template <class T, T Begin>
|
||||
struct IntSeqImpl<T, Begin, Begin, false> {
|
||||
using TValue = T;
|
||||
static_assert(std::is_integral<TValue>::value, "not integral type");
|
||||
static_assert(Begin >= 0, "unexpected argument (Begin<0)");
|
||||
using TResult = integer_sequence<TValue>;
|
||||
};
|
||||
|
||||
template <class T, T Begin, T End>
|
||||
struct IntSeqImpl<T, Begin, End, true> {
|
||||
using TValue = T;
|
||||
static_assert(std::is_integral<TValue>::value, "not integral type");
|
||||
static_assert(Begin >= 0, "unexpected argument (Begin<0)");
|
||||
using TResult = integer_sequence<TValue, Begin>;
|
||||
};
|
||||
} // namespace detail_
|
||||
|
||||
template <class T, T N>
|
||||
using make_integer_sequence = typename detail_::IntSeqImpl<T, 0, N, (N - 0) == 1>::TResult;
|
||||
|
||||
template <std::size_t N>
|
||||
using make_index_sequence = make_integer_sequence<std::size_t, N>;
|
||||
|
||||
template <class... T>
|
||||
using index_sequence_for = make_index_sequence<sizeof...(T)>;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
} // extension_traits
|
||||
} // jsoncons
|
||||
|
||||
#endif
|
||||
1189
scripts/exe/jsoncons/include/jsoncons/item_event_reader.hpp
Normal file
1189
scripts/exe/jsoncons/include/jsoncons/item_event_reader.hpp
Normal file
File diff suppressed because it is too large
Load diff
2071
scripts/exe/jsoncons/include/jsoncons/item_event_visitor.hpp
Normal file
2071
scripts/exe/jsoncons/include/jsoncons/item_event_visitor.hpp
Normal file
File diff suppressed because it is too large
Load diff
18
scripts/exe/jsoncons/include/jsoncons/json.hpp
Normal file
18
scripts/exe/jsoncons/include/jsoncons/json.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_HPP
|
||||
#define JSONCONS_JSON_HPP
|
||||
|
||||
#include <jsoncons/basic_json.hpp>
|
||||
#include <jsoncons/encode_json.hpp>
|
||||
#include <jsoncons/decode_json.hpp>
|
||||
#include <jsoncons/json_traits_macros.hpp>
|
||||
#include <jsoncons/json_traits_macros_deprecated.hpp>
|
||||
#include <jsoncons/staj_iterator.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
324
scripts/exe/jsoncons/include/jsoncons/json_array.hpp
Normal file
324
scripts/exe/jsoncons/include/jsoncons/json_array.hpp
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_ARRAY_HPP
|
||||
#define JSONCONS_JSON_ARRAY_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <exception>
|
||||
#include <cstring>
|
||||
#include <algorithm> // std::sort, std::stable_sort, std::lower_bound, std::unique
|
||||
#include <utility>
|
||||
#include <initializer_list>
|
||||
#include <iterator> // std::iterator_traits
|
||||
#include <memory> // std::allocator
|
||||
#include <utility> // std::move
|
||||
#include <cassert> // assert
|
||||
#include <type_traits> // std::enable_if
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/allocator_holder.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// json_array
|
||||
|
||||
template <class Json,template<typename,typename> class SequenceContainer = std::vector>
|
||||
class json_array : public allocator_holder<typename Json::allocator_type>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename Json::allocator_type;
|
||||
using value_type = Json;
|
||||
private:
|
||||
using value_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<value_type>;
|
||||
using value_container_type = SequenceContainer<value_type,value_allocator_type>;
|
||||
value_container_type elements_;
|
||||
public:
|
||||
using iterator = typename value_container_type::iterator;
|
||||
using const_iterator = typename value_container_type::const_iterator;
|
||||
using reference = typename std::iterator_traits<iterator>::reference;
|
||||
using const_reference = typename std::iterator_traits<const_iterator>::reference;
|
||||
|
||||
using allocator_holder<allocator_type>::get_allocator;
|
||||
|
||||
json_array()
|
||||
{
|
||||
}
|
||||
|
||||
explicit json_array(const allocator_type& alloc)
|
||||
: allocator_holder<allocator_type>(alloc),
|
||||
elements_(value_allocator_type(alloc))
|
||||
{
|
||||
}
|
||||
|
||||
explicit json_array(std::size_t n,
|
||||
const allocator_type& alloc = allocator_type())
|
||||
: allocator_holder<allocator_type>(alloc),
|
||||
elements_(n,Json(),value_allocator_type(alloc))
|
||||
{
|
||||
}
|
||||
|
||||
explicit json_array(std::size_t n,
|
||||
const Json& value,
|
||||
const allocator_type& alloc = allocator_type())
|
||||
: allocator_holder<allocator_type>(alloc),
|
||||
elements_(n,value,value_allocator_type(alloc))
|
||||
{
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
json_array(InputIterator begin, InputIterator end, const allocator_type& alloc = allocator_type())
|
||||
: allocator_holder<allocator_type>(alloc),
|
||||
elements_(begin,end,value_allocator_type(alloc))
|
||||
{
|
||||
}
|
||||
json_array(const json_array& val)
|
||||
: allocator_holder<allocator_type>(val.get_allocator()),
|
||||
elements_(val.elements_)
|
||||
{
|
||||
}
|
||||
json_array(const json_array& val, const allocator_type& alloc)
|
||||
: allocator_holder<allocator_type>(alloc),
|
||||
elements_(val.elements_,value_allocator_type(alloc))
|
||||
{
|
||||
}
|
||||
|
||||
json_array(json_array&& val) noexcept
|
||||
: allocator_holder<allocator_type>(val.get_allocator()),
|
||||
elements_(std::move(val.elements_))
|
||||
{
|
||||
}
|
||||
json_array(json_array&& val, const allocator_type& alloc)
|
||||
: allocator_holder<allocator_type>(alloc),
|
||||
elements_(std::move(val.elements_),value_allocator_type(alloc))
|
||||
{
|
||||
}
|
||||
|
||||
json_array(const std::initializer_list<Json>& init,
|
||||
const allocator_type& alloc = allocator_type())
|
||||
: allocator_holder<allocator_type>(alloc),
|
||||
elements_(init,value_allocator_type(alloc))
|
||||
{
|
||||
}
|
||||
~json_array() noexcept
|
||||
{
|
||||
flatten_and_destroy();
|
||||
}
|
||||
|
||||
reference back()
|
||||
{
|
||||
return elements_.back();
|
||||
}
|
||||
|
||||
const_reference back() const
|
||||
{
|
||||
return elements_.back();
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
elements_.pop_back();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return elements_.empty();
|
||||
}
|
||||
|
||||
void swap(json_array& val) noexcept
|
||||
{
|
||||
elements_.swap(val.elements_);
|
||||
}
|
||||
|
||||
std::size_t size() const {return elements_.size();}
|
||||
|
||||
std::size_t capacity() const {return elements_.capacity();}
|
||||
|
||||
void clear() {elements_.clear();}
|
||||
|
||||
void shrink_to_fit()
|
||||
{
|
||||
for (std::size_t i = 0; i < elements_.size(); ++i)
|
||||
{
|
||||
elements_[i].shrink_to_fit();
|
||||
}
|
||||
elements_.shrink_to_fit();
|
||||
}
|
||||
|
||||
void reserve(std::size_t n) {elements_.reserve(n);}
|
||||
|
||||
void resize(std::size_t n) {elements_.resize(n);}
|
||||
|
||||
void resize(std::size_t n, const Json& val) {elements_.resize(n,val);}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use erase(const_iterator, const_iterator)")
|
||||
void remove_range(std::size_t from_index, std::size_t to_index)
|
||||
{
|
||||
JSONCONS_ASSERT(from_index <= to_index);
|
||||
JSONCONS_ASSERT(to_index <= elements_.size());
|
||||
elements_.erase(elements_.cbegin()+from_index,elements_.cbegin()+to_index);
|
||||
}
|
||||
#endif
|
||||
|
||||
iterator erase(const_iterator pos)
|
||||
{
|
||||
#if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
|
||||
iterator it = elements_.begin() + (pos - elements_.begin());
|
||||
return elements_.erase(it);
|
||||
#else
|
||||
return elements_.erase(pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
#if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
|
||||
iterator it1 = elements_.begin() + (first - elements_.begin());
|
||||
iterator it2 = elements_.begin() + (last - elements_.begin());
|
||||
return elements_.erase(it1,it2);
|
||||
#else
|
||||
return elements_.erase(first,last);
|
||||
#endif
|
||||
}
|
||||
|
||||
Json& operator[](std::size_t i) {return elements_[i];}
|
||||
|
||||
const Json& operator[](std::size_t i) const {return elements_[i];}
|
||||
|
||||
// push_back
|
||||
|
||||
template <class T, class A=allocator_type>
|
||||
typename std::enable_if<extension_traits::is_stateless<A>::value,void>::type
|
||||
push_back(T&& value)
|
||||
{
|
||||
elements_.emplace_back(std::forward<T>(value));
|
||||
}
|
||||
|
||||
template <class T, class A=allocator_type>
|
||||
typename std::enable_if<!extension_traits::is_stateless<A>::value,void>::type
|
||||
push_back(T&& value)
|
||||
{
|
||||
elements_.emplace_back(std::forward<T>(value),get_allocator());
|
||||
}
|
||||
|
||||
template <class T, class A=allocator_type>
|
||||
typename std::enable_if<extension_traits::is_stateless<A>::value,iterator>::type
|
||||
insert(const_iterator pos, T&& value)
|
||||
{
|
||||
#if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
|
||||
iterator it = elements_.begin() + (pos - elements_.begin());
|
||||
return elements_.emplace(it, std::forward<T>(value));
|
||||
#else
|
||||
return elements_.emplace(pos, std::forward<T>(value));
|
||||
#endif
|
||||
}
|
||||
template <class T, class A=allocator_type>
|
||||
typename std::enable_if<!extension_traits::is_stateless<A>::value,iterator>::type
|
||||
insert(const_iterator pos, T&& value)
|
||||
{
|
||||
#if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
|
||||
iterator it = elements_.begin() + (pos - elements_.begin());
|
||||
return elements_.emplace(it, std::forward<T>(value), get_allocator());
|
||||
#else
|
||||
return elements_.emplace(pos, std::forward<T>(value), get_allocator());
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
iterator insert(const_iterator pos, InputIt first, InputIt last)
|
||||
{
|
||||
#if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
|
||||
iterator it = elements_.begin() + (pos - elements_.begin());
|
||||
elements_.insert(it, first, last);
|
||||
return first == last ? it : it + 1;
|
||||
#else
|
||||
return elements_.insert(pos, first, last);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class A=allocator_type, class... Args>
|
||||
typename std::enable_if<extension_traits::is_stateless<A>::value,iterator>::type
|
||||
emplace(const_iterator pos, Args&&... args)
|
||||
{
|
||||
#if defined(JSONCONS_NO_VECTOR_ERASE_TAKES_CONST_ITERATOR)
|
||||
iterator it = elements_.begin() + (pos - elements_.begin());
|
||||
return elements_.emplace(it, std::forward<Args>(args)...);
|
||||
#else
|
||||
return elements_.emplace(pos, std::forward<Args>(args)...);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
Json& emplace_back(Args&&... args)
|
||||
{
|
||||
elements_.emplace_back(std::forward<Args>(args)...);
|
||||
return elements_.back();
|
||||
}
|
||||
|
||||
iterator begin() {return elements_.begin();}
|
||||
|
||||
iterator end() {return elements_.end();}
|
||||
|
||||
const_iterator begin() const {return elements_.begin();}
|
||||
|
||||
const_iterator end() const {return elements_.end();}
|
||||
|
||||
bool operator==(const json_array& rhs) const noexcept
|
||||
{
|
||||
return elements_ == rhs.elements_;
|
||||
}
|
||||
|
||||
bool operator<(const json_array& rhs) const noexcept
|
||||
{
|
||||
return elements_ < rhs.elements_;
|
||||
}
|
||||
private:
|
||||
|
||||
json_array& operator=(const json_array&) = delete;
|
||||
|
||||
void flatten_and_destroy() noexcept
|
||||
{
|
||||
while (!elements_.empty())
|
||||
{
|
||||
value_type current = std::move(elements_.back());
|
||||
elements_.pop_back();
|
||||
switch (current.storage_kind())
|
||||
{
|
||||
case json_storage_kind::array_value:
|
||||
{
|
||||
for (auto&& item : current.array_range())
|
||||
{
|
||||
if (item.size() > 0) // non-empty object or array
|
||||
{
|
||||
elements_.push_back(std::move(item));
|
||||
}
|
||||
}
|
||||
current.clear();
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::object_value:
|
||||
{
|
||||
for (auto&& kv : current.object_range())
|
||||
{
|
||||
if (kv.value().size() > 0) // non-empty object or array
|
||||
{
|
||||
elements_.push_back(std::move(kv.value()));
|
||||
}
|
||||
}
|
||||
current.clear();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_CONTENT_HANDLER_HPP
|
||||
#define JSONCONS_JSON_CONTENT_HANDLER_HPP
|
||||
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
|
||||
#endif
|
||||
461
scripts/exe/jsoncons/include/jsoncons/json_cursor.hpp
Normal file
461
scripts/exe/jsoncons/include/jsoncons/json_cursor.hpp
Normal file
|
|
@ -0,0 +1,461 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_CURSOR_HPP
|
||||
#define JSONCONS_JSON_CURSOR_HPP
|
||||
|
||||
#include <memory> // std::allocator
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <ios>
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/byte_string.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/json_parser.hpp>
|
||||
#include <jsoncons/staj_cursor.hpp>
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons/source_adaptor.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
template<class CharT,class Source=jsoncons::stream_source<CharT>,class Allocator=std::allocator<char>>
|
||||
class basic_json_cursor : public basic_staj_cursor<CharT>, private virtual ser_context
|
||||
{
|
||||
public:
|
||||
using source_type = Source;
|
||||
using char_type = CharT;
|
||||
using allocator_type = Allocator;
|
||||
using string_view_type = jsoncons::basic_string_view<CharT>;
|
||||
private:
|
||||
typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<CharT> char_allocator_type;
|
||||
static constexpr size_t default_max_buffer_size = 16384;
|
||||
|
||||
json_source_adaptor<Source> source_;
|
||||
basic_json_parser<CharT,Allocator> parser_;
|
||||
basic_staj_visitor<CharT> cursor_visitor_;
|
||||
bool done_;
|
||||
|
||||
// Noncopyable and nonmoveable
|
||||
basic_json_cursor(const basic_json_cursor&) = delete;
|
||||
basic_json_cursor& operator=(const basic_json_cursor&) = delete;
|
||||
|
||||
public:
|
||||
|
||||
// Constructors that throw parse exceptions
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_cursor(Sourceable&& source,
|
||||
const basic_json_decode_options<CharT>& options = basic_json_decode_options<CharT>(),
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler = default_json_parsing(),
|
||||
const Allocator& alloc = Allocator(),
|
||||
typename std::enable_if<!std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
parser_(options,err_handler,alloc),
|
||||
cursor_visitor_(accept_all),
|
||||
done_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_cursor(Sourceable&& source,
|
||||
const basic_json_decode_options<CharT>& options = basic_json_decode_options<CharT>(),
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler = default_json_parsing(),
|
||||
const Allocator& alloc = Allocator(),
|
||||
typename std::enable_if<std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(),
|
||||
parser_(options, err_handler, alloc),
|
||||
cursor_visitor_(accept_all),
|
||||
done_(false)
|
||||
{
|
||||
initialize_with_string_view(std::forward<Sourceable>(source));
|
||||
}
|
||||
|
||||
|
||||
// Constructors that set parse error codes
|
||||
template <class Sourceable>
|
||||
basic_json_cursor(Sourceable&& source,
|
||||
std::error_code& ec)
|
||||
: basic_json_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
basic_json_decode_options<CharT>(),
|
||||
default_json_parsing(),
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_cursor(Sourceable&& source,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
std::error_code& ec)
|
||||
: basic_json_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
options,
|
||||
default_json_parsing(),
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_cursor(Sourceable&& source,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
std::error_code& ec)
|
||||
: basic_json_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
options,
|
||||
err_handler,
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_cursor(std::allocator_arg_t, const Allocator& alloc,
|
||||
Sourceable&& source,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
std::error_code& ec,
|
||||
typename std::enable_if<!std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
parser_(options,err_handler,alloc),
|
||||
cursor_visitor_(accept_all),
|
||||
done_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_cursor(std::allocator_arg_t, const Allocator& alloc,
|
||||
Sourceable&& source,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
std::error_code& ec,
|
||||
typename std::enable_if<std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(),
|
||||
parser_(options, err_handler, alloc),
|
||||
cursor_visitor_(accept_all),
|
||||
done_(false)
|
||||
{
|
||||
initialize_with_string_view(std::forward<Sourceable>(source), ec);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
parser_.reset();
|
||||
cursor_visitor_.reset();
|
||||
done_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
typename std::enable_if<!std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type
|
||||
reset(Sourceable&& source)
|
||||
{
|
||||
source_ = std::forward<Sourceable>(source);
|
||||
parser_.reinitialize();
|
||||
cursor_visitor_.reset();
|
||||
done_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
typename std::enable_if<std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type
|
||||
reset(Sourceable&& source)
|
||||
{
|
||||
source_ = {};
|
||||
parser_.reinitialize();
|
||||
cursor_visitor_.reset();
|
||||
done_ = false;
|
||||
initialize_with_string_view(std::forward<Sourceable>(source));
|
||||
}
|
||||
|
||||
void reset(std::error_code& ec)
|
||||
{
|
||||
parser_.reset();
|
||||
cursor_visitor_.reset();
|
||||
done_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
typename std::enable_if<!std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type
|
||||
reset(Sourceable&& source, std::error_code& ec)
|
||||
{
|
||||
source_ = std::forward<Sourceable>(source);
|
||||
parser_.reinitialize();
|
||||
cursor_visitor_.reset();
|
||||
done_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
typename std::enable_if<std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type
|
||||
reset(Sourceable&& source, std::error_code& ec)
|
||||
{
|
||||
source_ = {};
|
||||
parser_.reinitialize();
|
||||
done_ = false;
|
||||
initialize_with_string_view(std::forward<Sourceable>(source), ec);
|
||||
}
|
||||
|
||||
bool done() const override
|
||||
{
|
||||
return parser_.done() || done_;
|
||||
}
|
||||
|
||||
const basic_staj_event<CharT>& current() const override
|
||||
{
|
||||
return cursor_visitor_.event();
|
||||
}
|
||||
|
||||
void read_to(basic_json_visitor<CharT>& visitor) override
|
||||
{
|
||||
std::error_code ec;
|
||||
read_to(visitor, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read_to(basic_json_visitor<CharT>& visitor,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (send_json_event(cursor_visitor_.event(), visitor, *this, ec))
|
||||
{
|
||||
read_next(visitor, ec);
|
||||
}
|
||||
}
|
||||
|
||||
void next() override
|
||||
{
|
||||
std::error_code ec;
|
||||
next(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void next(std::error_code& ec) override
|
||||
{
|
||||
read_next(ec);
|
||||
}
|
||||
|
||||
void check_done()
|
||||
{
|
||||
std::error_code ec;
|
||||
check_done(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
const ser_context& context() const override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
void check_done(std::error_code& ec)
|
||||
{
|
||||
if (source_.is_error())
|
||||
{
|
||||
ec = json_errc::source_error;
|
||||
return;
|
||||
}
|
||||
if (source_.eof())
|
||||
{
|
||||
parser_.check_done(ec);
|
||||
if (ec) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
}
|
||||
}
|
||||
if (!parser_.source_exhausted())
|
||||
{
|
||||
parser_.check_done(ec);
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
while (!eof());
|
||||
}
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return parser_.source_exhausted() && source_.eof();
|
||||
}
|
||||
|
||||
std::size_t line() const override
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const override
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
|
||||
friend
|
||||
basic_staj_filter_view<CharT> operator|(basic_json_cursor& cursor,
|
||||
std::function<bool(const basic_staj_event<CharT>&, const ser_context&)> pred)
|
||||
{
|
||||
return basic_staj_filter_view<CharT>(cursor, pred);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static bool accept_all(const basic_staj_event<CharT>&, const ser_context&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void initialize_with_string_view(string_view_type sv)
|
||||
{
|
||||
auto r = unicode_traits::detect_json_encoding(sv.data(), sv.size());
|
||||
if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected))
|
||||
{
|
||||
JSONCONS_THROW(ser_error(json_errc::illegal_unicode_character,parser_.line(),parser_.column()));
|
||||
}
|
||||
std::size_t offset = (r.ptr - sv.data());
|
||||
parser_.update(sv.data()+offset,sv.size()-offset);
|
||||
|
||||
bool is_done = parser_.done() || done_;
|
||||
if (!is_done)
|
||||
{
|
||||
read_next();
|
||||
}
|
||||
}
|
||||
|
||||
void initialize_with_string_view(string_view_type sv, std::error_code& ec)
|
||||
{
|
||||
auto r = unicode_traits::detect_json_encoding(sv.data(), sv.size());
|
||||
if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected))
|
||||
{
|
||||
ec = json_errc::illegal_unicode_character;
|
||||
return;
|
||||
}
|
||||
std::size_t offset = (r.ptr - sv.data());
|
||||
parser_.update(sv.data()+offset,sv.size()-offset);
|
||||
bool is_done = parser_.done() || done_;
|
||||
if (!is_done)
|
||||
{
|
||||
read_next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
void read_next()
|
||||
{
|
||||
std::error_code ec;
|
||||
read_next(cursor_visitor_, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read_next(std::error_code& ec)
|
||||
{
|
||||
read_next(cursor_visitor_, ec);
|
||||
}
|
||||
|
||||
void read_next(basic_json_visitor<CharT>& visitor, std::error_code& ec)
|
||||
{
|
||||
parser_.restart();
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
bool eof = parser_.source_exhausted() && source_.eof();
|
||||
parser_.parse_some(visitor, ec);
|
||||
if (ec) return;
|
||||
if (eof)
|
||||
{
|
||||
if (parser_.enter())
|
||||
{
|
||||
done_ = true;
|
||||
break;
|
||||
}
|
||||
else if (!parser_.accept())
|
||||
{
|
||||
ec = json_errc::unexpected_eof;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using json_stream_cursor = basic_json_cursor<char,jsoncons::stream_source<char>>;
|
||||
using json_string_cursor = basic_json_cursor<char,jsoncons::string_source<char>>;
|
||||
using wjson_stream_cursor = basic_json_cursor<wchar_t,jsoncons::stream_source<wchar_t>>;
|
||||
using wjson_string_cursor = basic_json_cursor<wchar_t,jsoncons::string_source<wchar_t>>;
|
||||
|
||||
using json_cursor = basic_json_cursor<char>;
|
||||
using wjson_cursor = basic_json_cursor<wchar_t>;
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
template<class CharT,class Source,class Allocator=std::allocator<CharT>>
|
||||
using basic_json_pull_reader = basic_json_cursor<CharT,Source,Allocator>;
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use json_stream_cursor") typedef json_cursor json_pull_reader;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use wjson_stream_cursor") typedef wjson_cursor wjson_pull_reader;
|
||||
|
||||
template<class CharT,class Source,class Allocator=std::allocator<CharT>>
|
||||
using basic_json_stream_reader = basic_json_cursor<CharT,Source,Allocator>;
|
||||
|
||||
template<class CharT,class Source,class Allocator=std::allocator<CharT>>
|
||||
using basic_json_staj_cursor = basic_json_cursor<CharT,Source,Allocator>;
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use json_cursor") typedef json_cursor json_staj_cursor;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use wjson_cursor") typedef wjson_cursor wjson_staj_cursor;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
410
scripts/exe/jsoncons/include/jsoncons/json_decoder.hpp
Normal file
410
scripts/exe/jsoncons/include/jsoncons/json_decoder.hpp
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_DECODER_HPP
|
||||
#define JSONCONS_JSON_DECODER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <type_traits> // std::true_type
|
||||
#include <memory> // std::allocator
|
||||
#include <iterator> // std::make_move_iterator
|
||||
#include <utility> // std::move
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
template <class Json,class TempAllocator=std::allocator<char>>
|
||||
class json_decoder final : public basic_json_visitor<typename Json::char_type>
|
||||
{
|
||||
public:
|
||||
using char_type = typename Json::char_type;
|
||||
using typename basic_json_visitor<char_type>::string_view_type;
|
||||
|
||||
using key_value_type = typename Json::key_value_type;
|
||||
using key_type = typename Json::key_type;
|
||||
using array = typename Json::array;
|
||||
using object = typename Json::object;
|
||||
using result_allocator_type = typename Json::allocator_type;
|
||||
using json_string_allocator = typename key_type::allocator_type;
|
||||
using json_array_allocator = typename array::allocator_type;
|
||||
using json_object_allocator = typename object::allocator_type;
|
||||
typedef typename std::allocator_traits<result_allocator_type>:: template rebind_alloc<uint8_t> json_byte_allocator_type;
|
||||
private:
|
||||
|
||||
enum class structure_type {root_t, array_t, object_t};
|
||||
|
||||
struct structure_info
|
||||
{
|
||||
structure_type type_;
|
||||
std::size_t container_index_;
|
||||
|
||||
structure_info(structure_type type, std::size_t offset) noexcept
|
||||
: type_(type), container_index_(offset)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
using temp_allocator_type = TempAllocator;
|
||||
typedef typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<key_index_value<Json>> stack_item_allocator_type;
|
||||
typedef typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<structure_info> structure_info_allocator_type;
|
||||
|
||||
result_allocator_type result_allocator_;
|
||||
temp_allocator_type temp_allocator_;
|
||||
|
||||
Json result_;
|
||||
|
||||
std::size_t index_;
|
||||
key_type name_;
|
||||
std::vector<key_index_value<Json>,stack_item_allocator_type> item_stack_;
|
||||
std::vector<structure_info,structure_info_allocator_type> structure_stack_;
|
||||
bool is_valid_;
|
||||
|
||||
public:
|
||||
json_decoder(const temp_allocator_type& temp_alloc = temp_allocator_type())
|
||||
: result_allocator_(result_allocator_type()),
|
||||
temp_allocator_(temp_alloc),
|
||||
result_(),
|
||||
index_(0),
|
||||
name_(result_allocator_),
|
||||
item_stack_(temp_allocator_),
|
||||
structure_stack_(temp_allocator_),
|
||||
is_valid_(false)
|
||||
{
|
||||
item_stack_.reserve(1000);
|
||||
structure_stack_.reserve(100);
|
||||
structure_stack_.emplace_back(structure_type::root_t, 0);
|
||||
}
|
||||
|
||||
json_decoder(result_allocator_arg_t,
|
||||
const result_allocator_type& result_alloc)
|
||||
: result_allocator_(result_alloc),
|
||||
temp_allocator_(),
|
||||
result_(),
|
||||
index_(0),
|
||||
name_(result_allocator_),
|
||||
item_stack_(),
|
||||
structure_stack_(),
|
||||
is_valid_(false)
|
||||
{
|
||||
item_stack_.reserve(1000);
|
||||
structure_stack_.reserve(100);
|
||||
structure_stack_.emplace_back(structure_type::root_t, 0);
|
||||
}
|
||||
|
||||
json_decoder(result_allocator_arg_t,
|
||||
const result_allocator_type& result_alloc,
|
||||
const temp_allocator_type& temp_alloc)
|
||||
: result_allocator_(result_alloc),
|
||||
temp_allocator_(temp_alloc),
|
||||
result_(),
|
||||
index_(0),
|
||||
name_(result_allocator_),
|
||||
item_stack_(temp_allocator_),
|
||||
structure_stack_(temp_allocator_),
|
||||
is_valid_(false)
|
||||
{
|
||||
item_stack_.reserve(1000);
|
||||
structure_stack_.reserve(100);
|
||||
structure_stack_.emplace_back(structure_type::root_t, 0);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
is_valid_ = false;
|
||||
index_ = 0;
|
||||
item_stack_.clear();
|
||||
structure_stack_.clear();
|
||||
structure_stack_.emplace_back(structure_type::root_t, 0);
|
||||
}
|
||||
|
||||
bool is_valid() const
|
||||
{
|
||||
return is_valid_;
|
||||
}
|
||||
|
||||
Json get_result()
|
||||
{
|
||||
JSONCONS_ASSERT(is_valid_);
|
||||
is_valid_ = false;
|
||||
return std::move(result_);
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use get_result()")
|
||||
Json& root()
|
||||
{
|
||||
return result_;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
void visit_flush() override
|
||||
{
|
||||
}
|
||||
|
||||
bool visit_begin_object(semantic_tag tag, const ser_context&, std::error_code&) override
|
||||
{
|
||||
if (structure_stack_.back().type_ == structure_type::root_t)
|
||||
{
|
||||
index_ = 0;
|
||||
item_stack_.clear();
|
||||
is_valid_ = false;
|
||||
}
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, json_object_arg, tag, result_allocator_);
|
||||
structure_stack_.emplace_back(structure_type::object_t, item_stack_.size()-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_end_object(const ser_context&, std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(structure_stack_.size() > 0);
|
||||
JSONCONS_ASSERT(structure_stack_.back().type_ == structure_type::object_t);
|
||||
const size_t structure_index = structure_stack_.back().container_index_;
|
||||
JSONCONS_ASSERT(item_stack_.size() > structure_index);
|
||||
const size_t count = item_stack_.size() - (structure_index + 1);
|
||||
auto first = item_stack_.begin() + (structure_index+1);
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
item_stack_[structure_index].value.object_value().init(&item_stack_[structure_index+1], count);
|
||||
}
|
||||
|
||||
item_stack_.erase(first, item_stack_.end());
|
||||
structure_stack_.pop_back();
|
||||
if (structure_stack_.back().type_ == structure_type::root_t)
|
||||
{
|
||||
result_.swap(item_stack_.front().value);
|
||||
item_stack_.pop_back();
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_begin_array(semantic_tag tag, const ser_context&, std::error_code&) override
|
||||
{
|
||||
if (structure_stack_.back().type_ == structure_type::root_t)
|
||||
{
|
||||
index_ = 0;
|
||||
item_stack_.clear();
|
||||
is_valid_ = false;
|
||||
}
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, json_array_arg, tag, result_allocator_);
|
||||
structure_stack_.emplace_back(structure_type::array_t, item_stack_.size()-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_end_array(const ser_context&, std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(structure_stack_.size() > 1);
|
||||
JSONCONS_ASSERT(structure_stack_.back().type_ == structure_type::array_t);
|
||||
const size_t container_index = structure_stack_.back().container_index_;
|
||||
JSONCONS_ASSERT(item_stack_.size() > container_index);
|
||||
|
||||
auto& container = item_stack_[container_index].value;
|
||||
|
||||
const size_t size = item_stack_.size() - (container_index + 1);
|
||||
//std::cout << "size on item stack: " << size << "\n";
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
container.reserve(size);
|
||||
auto first = item_stack_.begin() + (container_index+1);
|
||||
auto last = first + size;
|
||||
for (auto it = first; it != last; ++it)
|
||||
{
|
||||
container.push_back(std::move(it->value));
|
||||
}
|
||||
item_stack_.erase(first, item_stack_.end());
|
||||
}
|
||||
|
||||
structure_stack_.pop_back();
|
||||
if (structure_stack_.back().type_ == structure_type::root_t)
|
||||
{
|
||||
result_.swap(item_stack_.front().value);
|
||||
item_stack_.pop_back();
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_key(const string_view_type& name, const ser_context&, std::error_code&) override
|
||||
{
|
||||
name_ = key_type(name.data(),name.length(),result_allocator_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_string(const string_view_type& sv, semantic_tag tag, const ser_context&, std::error_code&) override
|
||||
{
|
||||
switch (structure_stack_.back().type_)
|
||||
{
|
||||
case structure_type::object_t:
|
||||
case structure_type::array_t:
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, sv, tag, result_allocator_);
|
||||
break;
|
||||
case structure_type::root_t:
|
||||
result_ = Json(sv, tag, result_allocator_);
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_byte_string(const byte_string_view& b,
|
||||
semantic_tag tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
switch (structure_stack_.back().type_)
|
||||
{
|
||||
case structure_type::object_t:
|
||||
case structure_type::array_t:
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, byte_string_arg, b, tag, result_allocator_);
|
||||
break;
|
||||
case structure_type::root_t:
|
||||
result_ = Json(byte_string_arg, b, tag, result_allocator_);
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_byte_string(const byte_string_view& b,
|
||||
uint64_t ext_tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
switch (structure_stack_.back().type_)
|
||||
{
|
||||
case structure_type::object_t:
|
||||
case structure_type::array_t:
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, byte_string_arg, b, ext_tag, result_allocator_);
|
||||
break;
|
||||
case structure_type::root_t:
|
||||
result_ = Json(byte_string_arg, b, ext_tag, result_allocator_);
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_int64(int64_t value,
|
||||
semantic_tag tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
switch (structure_stack_.back().type_)
|
||||
{
|
||||
case structure_type::object_t:
|
||||
case structure_type::array_t:
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, value, tag);
|
||||
break;
|
||||
case structure_type::root_t:
|
||||
result_ = Json(value,tag);
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_uint64(uint64_t value,
|
||||
semantic_tag tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
switch (structure_stack_.back().type_)
|
||||
{
|
||||
case structure_type::object_t:
|
||||
case structure_type::array_t:
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, value, tag);
|
||||
break;
|
||||
case structure_type::root_t:
|
||||
result_ = Json(value,tag);
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_half(uint16_t value,
|
||||
semantic_tag tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
switch (structure_stack_.back().type_)
|
||||
{
|
||||
case structure_type::object_t:
|
||||
case structure_type::array_t:
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, half_arg, value, tag);
|
||||
break;
|
||||
case structure_type::root_t:
|
||||
result_ = Json(half_arg, value, tag);
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_double(double value,
|
||||
semantic_tag tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
switch (structure_stack_.back().type_)
|
||||
{
|
||||
case structure_type::object_t:
|
||||
case structure_type::array_t:
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, value, tag);
|
||||
break;
|
||||
case structure_type::root_t:
|
||||
result_ = Json(value, tag);
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_bool(bool value, semantic_tag tag, const ser_context&, std::error_code&) override
|
||||
{
|
||||
switch (structure_stack_.back().type_)
|
||||
{
|
||||
case structure_type::object_t:
|
||||
case structure_type::array_t:
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, value, tag);
|
||||
break;
|
||||
case structure_type::root_t:
|
||||
result_ = Json(value, tag);
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_null(semantic_tag tag, const ser_context&, std::error_code&) override
|
||||
{
|
||||
switch (structure_stack_.back().type_)
|
||||
{
|
||||
case structure_type::object_t:
|
||||
case structure_type::array_t:
|
||||
item_stack_.emplace_back(std::forward<key_type>(name_), index_++, null_type(), tag);
|
||||
break;
|
||||
case structure_type::root_t:
|
||||
result_ = Json(null_type(), tag);
|
||||
is_valid_ = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
1582
scripts/exe/jsoncons/include/jsoncons/json_encoder.hpp
Normal file
1582
scripts/exe/jsoncons/include/jsoncons/json_encoder.hpp
Normal file
File diff suppressed because it is too large
Load diff
156
scripts/exe/jsoncons/include/jsoncons/json_error.hpp
Normal file
156
scripts/exe/jsoncons/include/jsoncons/json_error.hpp
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_ERROR_HPP
|
||||
#define JSONCONS_JSON_ERROR_HPP
|
||||
|
||||
#include <system_error>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
enum class json_errc
|
||||
{
|
||||
success = 0,
|
||||
unexpected_eof = 1,
|
||||
source_error,
|
||||
syntax_error,
|
||||
extra_character,
|
||||
max_nesting_depth_exceeded,
|
||||
single_quote,
|
||||
illegal_character_in_string,
|
||||
extra_comma,
|
||||
expected_key,
|
||||
expected_value,
|
||||
invalid_value,
|
||||
expected_colon,
|
||||
illegal_control_character,
|
||||
illegal_escaped_character,
|
||||
expected_codepoint_surrogate_pair,
|
||||
invalid_hex_escape_sequence,
|
||||
invalid_unicode_escape_sequence,
|
||||
leading_zero,
|
||||
invalid_number,
|
||||
expected_comma_or_rbrace,
|
||||
expected_comma_or_rbracket,
|
||||
unexpected_rbracket,
|
||||
unexpected_rbrace,
|
||||
illegal_comment,
|
||||
expected_continuation_byte,
|
||||
over_long_utf8_sequence,
|
||||
illegal_codepoint,
|
||||
illegal_surrogate_value,
|
||||
unpaired_high_surrogate,
|
||||
illegal_unicode_character
|
||||
};
|
||||
|
||||
class json_error_category_impl
|
||||
: public std::error_category
|
||||
{
|
||||
public:
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "jsoncons/json";
|
||||
}
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<json_errc>(ev))
|
||||
{
|
||||
case json_errc::unexpected_eof:
|
||||
return "Unexpected end of file";
|
||||
case json_errc::source_error:
|
||||
return "Source error";
|
||||
case json_errc::syntax_error:
|
||||
return "JSON syntax_error";
|
||||
case json_errc::extra_character:
|
||||
return "Unexpected non-whitespace character after JSON text";
|
||||
case json_errc::max_nesting_depth_exceeded:
|
||||
return "Data item nesting exceeds limit in options";
|
||||
case json_errc::single_quote:
|
||||
return "JSON strings cannot be quoted with single quotes";
|
||||
case json_errc::illegal_character_in_string:
|
||||
return "Illegal character in string";
|
||||
case json_errc::extra_comma:
|
||||
return "Extra comma";
|
||||
case json_errc::expected_key:
|
||||
return "Expected object member key";
|
||||
case json_errc::expected_value:
|
||||
return "Expected value";
|
||||
case json_errc::invalid_value:
|
||||
return "Invalid value";
|
||||
case json_errc::expected_colon:
|
||||
return "Expected name separator ':'";
|
||||
case json_errc::illegal_control_character:
|
||||
return "Illegal control character in string";
|
||||
case json_errc::illegal_escaped_character:
|
||||
return "Illegal escaped character in string";
|
||||
case json_errc::expected_codepoint_surrogate_pair:
|
||||
return "Invalid codepoint, expected another \\u token to begin the second half of a codepoint surrogate pair.";
|
||||
case json_errc::invalid_hex_escape_sequence:
|
||||
return "Invalid codepoint, expected hexadecimal digit.";
|
||||
case json_errc::invalid_unicode_escape_sequence:
|
||||
return "Invalid codepoint, expected four hexadecimal digits.";
|
||||
case json_errc::leading_zero:
|
||||
return "A number cannot have a leading zero";
|
||||
case json_errc::invalid_number:
|
||||
return "Invalid number";
|
||||
case json_errc::expected_comma_or_rbrace:
|
||||
return "Expected comma or right brace '}'";
|
||||
case json_errc::expected_comma_or_rbracket:
|
||||
return "Expected comma or right bracket ']'";
|
||||
case json_errc::unexpected_rbrace:
|
||||
return "Unexpected right brace '}'";
|
||||
case json_errc::unexpected_rbracket:
|
||||
return "Unexpected right bracket ']'";
|
||||
case json_errc::illegal_comment:
|
||||
return "Illegal comment";
|
||||
case json_errc::expected_continuation_byte:
|
||||
return "Expected continuation byte";
|
||||
case json_errc::over_long_utf8_sequence:
|
||||
return "Over long UTF-8 sequence";
|
||||
case json_errc::illegal_codepoint:
|
||||
return "Illegal codepoint (>= 0xd800 && <= 0xdfff)";
|
||||
case json_errc::illegal_surrogate_value:
|
||||
return "UTF-16 surrogate values are illegal in UTF-32";
|
||||
case json_errc::unpaired_high_surrogate:
|
||||
return "Expected low surrogate following the high surrogate";
|
||||
case json_errc::illegal_unicode_character:
|
||||
return "Illegal unicode character";
|
||||
default:
|
||||
return "Unknown JSON parser error";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
const std::error_category& json_error_category()
|
||||
{
|
||||
static json_error_category_impl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
inline
|
||||
std::error_code make_error_code(json_errc result)
|
||||
{
|
||||
return std::error_code(static_cast<int>(result),json_error_category());
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use json_errc") typedef json_errc json_parser_errc;
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use json_errc") typedef json_errc json_parse_errc;
|
||||
#endif
|
||||
|
||||
} // jsoncons
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct is_error_code_enum<jsoncons::json_errc> : public true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
241
scripts/exe/jsoncons/include/jsoncons/json_exception.hpp
Normal file
241
scripts/exe/jsoncons/include/jsoncons/json_exception.hpp
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSON_EXCEPTION_HPP
|
||||
#define JSON_EXCEPTION_HPP
|
||||
|
||||
#include <string> // std::string
|
||||
#include <sstream> // std::ostringstream
|
||||
#include <system_error> // std::error_code
|
||||
#include <jsoncons/unicode_traits.hpp> // unicode_traits::convert
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/extension_traits.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// json_exception
|
||||
|
||||
class json_exception
|
||||
{
|
||||
public:
|
||||
virtual ~json_exception() noexcept = default;
|
||||
virtual const char* what() const noexcept = 0;
|
||||
};
|
||||
|
||||
// json_runtime_error
|
||||
|
||||
template <class Base, class Enable = void>
|
||||
class json_runtime_error
|
||||
{
|
||||
};
|
||||
|
||||
template <class Base>
|
||||
class json_runtime_error<Base,
|
||||
typename std::enable_if<std::is_convertible<Base*,std::exception*>::value &&
|
||||
extension_traits::is_constructible_from_string<Base>::value>::type>
|
||||
: public Base, public virtual json_exception
|
||||
{
|
||||
public:
|
||||
json_runtime_error(const std::string& s) noexcept
|
||||
: Base(s)
|
||||
{
|
||||
}
|
||||
~json_runtime_error() noexcept
|
||||
{
|
||||
}
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return Base::what();
|
||||
}
|
||||
};
|
||||
|
||||
class key_not_found : public std::out_of_range, public virtual json_exception
|
||||
{
|
||||
std::string name_;
|
||||
mutable std::string what_;
|
||||
public:
|
||||
template <class CharT>
|
||||
explicit key_not_found(const CharT* key, std::size_t length) noexcept
|
||||
: std::out_of_range("Key not found")
|
||||
{
|
||||
JSONCONS_TRY
|
||||
{
|
||||
unicode_traits::convert(key, length, name_,
|
||||
unicode_traits::conv_flags::strict);
|
||||
}
|
||||
JSONCONS_CATCH(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~key_not_found() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
if (what_.empty())
|
||||
{
|
||||
JSONCONS_TRY
|
||||
{
|
||||
what_.append(std::out_of_range::what());
|
||||
what_.append(": '");
|
||||
what_.append(name_);
|
||||
what_.append("'");
|
||||
return what_.c_str();
|
||||
}
|
||||
JSONCONS_CATCH(...)
|
||||
{
|
||||
return std::out_of_range::what();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return what_.c_str();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class not_an_object : public std::runtime_error, public virtual json_exception
|
||||
{
|
||||
std::string name_;
|
||||
mutable std::string what_;
|
||||
public:
|
||||
template <class CharT>
|
||||
explicit not_an_object(const CharT* key, std::size_t length) noexcept
|
||||
: std::runtime_error("Attempting to access a member of a value that is not an object")
|
||||
{
|
||||
JSONCONS_TRY
|
||||
{
|
||||
unicode_traits::convert(key, length, name_,
|
||||
unicode_traits::conv_flags::strict);
|
||||
}
|
||||
JSONCONS_CATCH(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~not_an_object() noexcept
|
||||
{
|
||||
}
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
if (what_.empty())
|
||||
{
|
||||
JSONCONS_TRY
|
||||
{
|
||||
what_.append(std::runtime_error::what());
|
||||
what_.append(": '");
|
||||
what_.append(name_);
|
||||
what_.append("'");
|
||||
return what_.c_str();
|
||||
}
|
||||
JSONCONS_CATCH(...)
|
||||
{
|
||||
return std::runtime_error::what();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return what_.c_str();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ser_error : public std::system_error, public virtual json_exception
|
||||
{
|
||||
std::size_t line_number_;
|
||||
std::size_t column_number_;
|
||||
mutable std::string what_;
|
||||
public:
|
||||
ser_error(std::error_code ec)
|
||||
: std::system_error(ec), line_number_(0), column_number_(0)
|
||||
{
|
||||
}
|
||||
ser_error(std::error_code ec, const std::string& what_arg)
|
||||
: std::system_error(ec, what_arg), line_number_(0), column_number_(0)
|
||||
{
|
||||
}
|
||||
ser_error(std::error_code ec, std::size_t position)
|
||||
: std::system_error(ec), line_number_(0), column_number_(position)
|
||||
{
|
||||
}
|
||||
ser_error(std::error_code ec, std::size_t line, std::size_t column)
|
||||
: std::system_error(ec), line_number_(line), column_number_(column)
|
||||
{
|
||||
}
|
||||
ser_error(const ser_error& other) = default;
|
||||
|
||||
ser_error(ser_error&& other) = default;
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
if (what_.empty())
|
||||
{
|
||||
JSONCONS_TRY
|
||||
{
|
||||
what_.append(std::system_error::what());
|
||||
if (line_number_ != 0 && column_number_ != 0)
|
||||
{
|
||||
what_.append(" at line ");
|
||||
what_.append(std::to_string(line_number_));
|
||||
what_.append(" and column ");
|
||||
what_.append(std::to_string(column_number_));
|
||||
}
|
||||
else if (column_number_ != 0)
|
||||
{
|
||||
what_.append(" at position ");
|
||||
what_.append(std::to_string(column_number_));
|
||||
}
|
||||
return what_.c_str();
|
||||
}
|
||||
JSONCONS_CATCH(...)
|
||||
{
|
||||
return std::system_error::what();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return what_.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t line() const noexcept
|
||||
{
|
||||
return line_number_;
|
||||
}
|
||||
|
||||
std::size_t column() const noexcept
|
||||
{
|
||||
return column_number_;
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use line()")
|
||||
std::size_t line_number() const noexcept
|
||||
{
|
||||
return line();
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use column()")
|
||||
std::size_t column_number() const noexcept
|
||||
{
|
||||
return column();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_error") typedef ser_error serialization_error;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_error") typedef ser_error json_parse_exception;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_error") typedef ser_error parse_exception;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_error") typedef ser_error parse_error;
|
||||
typedef ser_error codec_error;
|
||||
#endif
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
653
scripts/exe/jsoncons/include/jsoncons/json_filter.hpp
Normal file
653
scripts/exe/jsoncons/include/jsoncons/json_filter.hpp
Normal file
|
|
@ -0,0 +1,653 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_FILTER_HPP
|
||||
#define JSONCONS_JSON_FILTER_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
template <class CharT>
|
||||
class basic_json_filter : public basic_json_visitor<CharT>
|
||||
{
|
||||
public:
|
||||
using typename basic_json_visitor<CharT>::char_type;
|
||||
using typename basic_json_visitor<CharT>::string_view_type;
|
||||
private:
|
||||
basic_json_visitor<char_type>* destination_;
|
||||
|
||||
// noncopyable
|
||||
basic_json_filter(const basic_json_filter&) = delete;
|
||||
basic_json_filter& operator=(const basic_json_filter&) = delete;
|
||||
public:
|
||||
basic_json_filter(basic_json_visitor<char_type>& visitor)
|
||||
: destination_(std::addressof(visitor))
|
||||
{
|
||||
}
|
||||
|
||||
// moveable
|
||||
basic_json_filter(basic_json_filter&&) = default;
|
||||
basic_json_filter& operator=(basic_json_filter&&) = default;
|
||||
|
||||
basic_json_visitor<char_type>& destination()
|
||||
{
|
||||
return *destination_;
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use destination()")
|
||||
basic_json_visitor<char_type>& to_handler()
|
||||
{
|
||||
return destination_;
|
||||
}
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use destination")
|
||||
basic_json_visitor<char_type>& input_handler()
|
||||
{
|
||||
return destination_;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use destination")
|
||||
basic_json_visitor<char_type>& downstream_handler()
|
||||
{
|
||||
return destination_;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use destination")
|
||||
basic_json_visitor<char_type>& destination_handler()
|
||||
{
|
||||
return destination_;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
void visit_flush() override
|
||||
{
|
||||
destination_->flush();
|
||||
}
|
||||
|
||||
bool visit_begin_object(semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->begin_object(tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_begin_object(std::size_t length, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->begin_object(length, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_end_object(const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->end_object(context, ec);
|
||||
}
|
||||
|
||||
bool visit_begin_array(semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->begin_array(tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_begin_array(std::size_t length, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->begin_array(length, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_end_array(const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->end_array(context, ec);
|
||||
}
|
||||
|
||||
bool visit_key(const string_view_type& name,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->key(name, context, ec);
|
||||
}
|
||||
|
||||
bool visit_string(const string_view_type& value,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->string_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_byte_string(const byte_string_view& b,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->byte_string_value(b, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_byte_string(const byte_string_view& b,
|
||||
uint64_t ext_tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->byte_string_value(b, ext_tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_uint64(uint64_t value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->uint64_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_int64(int64_t value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->int64_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_half(uint16_t value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->half_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_double(double value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->double_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_bool(bool value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->bool_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_null(semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->null_value(tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const uint8_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const uint16_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const uint32_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const uint64_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const int8_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const int16_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const int32_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const int64_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(half_arg_t,
|
||||
const jsoncons::span<const uint16_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(half_arg, s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const float>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const double>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_begin_multi_dim(const jsoncons::span<const size_t>& shape,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->begin_multi_dim(shape, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_end_multi_dim(const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->end_multi_dim(context, ec);
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
class basic_rename_object_key_filter : public basic_json_filter<CharT>
|
||||
{
|
||||
public:
|
||||
using typename basic_json_filter<CharT>::string_view_type;
|
||||
|
||||
private:
|
||||
std::basic_string<CharT> name_;
|
||||
std::basic_string<CharT> new_name_;
|
||||
public:
|
||||
basic_rename_object_key_filter(const std::basic_string<CharT>& name,
|
||||
const std::basic_string<CharT>& new_name,
|
||||
basic_json_visitor<CharT>& visitor)
|
||||
: basic_json_filter<CharT>(visitor),
|
||||
name_(name), new_name_(new_name)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
bool visit_key(const string_view_type& name,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (name == name_)
|
||||
{
|
||||
return this->destination().key(new_name_,context, ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->destination().key(name,context,ec);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class From,class To>
|
||||
class json_visitor_adaptor_base : public From
|
||||
{
|
||||
public:
|
||||
using typename From::string_view_type;
|
||||
private:
|
||||
To* destination_;
|
||||
|
||||
// noncopyable
|
||||
json_visitor_adaptor_base(const json_visitor_adaptor_base&) = delete;
|
||||
json_visitor_adaptor_base& operator=(const json_visitor_adaptor_base&) = delete;
|
||||
public:
|
||||
json_visitor_adaptor_base(To& visitor)
|
||||
: destination_(std::addressof(visitor))
|
||||
{
|
||||
}
|
||||
|
||||
// moveable
|
||||
json_visitor_adaptor_base(json_visitor_adaptor_base&&) = default;
|
||||
json_visitor_adaptor_base& operator=(json_visitor_adaptor_base&&) = default;
|
||||
|
||||
To& destination()
|
||||
{
|
||||
return *destination_;
|
||||
}
|
||||
|
||||
private:
|
||||
void visit_flush() override
|
||||
{
|
||||
destination_->flush();
|
||||
}
|
||||
|
||||
bool visit_begin_object(semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->begin_object(tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_begin_object(std::size_t length,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->begin_object(length, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_end_object(const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->end_object(context, ec);
|
||||
}
|
||||
|
||||
bool visit_begin_array(semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->begin_array(tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_begin_array(std::size_t length,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->begin_array(length, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_end_array(const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->end_array(context, ec);
|
||||
}
|
||||
|
||||
bool visit_byte_string(const byte_string_view& b,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->byte_string_value(b, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_byte_string(const byte_string_view& b,
|
||||
uint64_t ext_tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->byte_string_value(b, ext_tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_half(uint16_t value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->half_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_double(double value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->double_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_int64(int64_t value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->int64_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_uint64(uint64_t value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->uint64_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_bool(bool value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->bool_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_null(semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return destination_->null_value(tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const uint8_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const uint16_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const uint32_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const uint64_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const int8_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const int16_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const int32_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const int64_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(half_arg_t,
|
||||
const jsoncons::span<const uint16_t>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(half_arg, s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const float>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_typed_array(const jsoncons::span<const double>& s,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->typed_array(s, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_begin_multi_dim(const jsoncons::span<const size_t>& shape,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->begin_multi_dim(shape, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_end_multi_dim(const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination_->end_multi_dim(context, ec);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <class From,class To,class Enable=void>
|
||||
class json_visitor_adaptor
|
||||
{
|
||||
};
|
||||
|
||||
template <class From,class To>
|
||||
class json_visitor_adaptor<From,To,typename std::enable_if<extension_traits::is_narrow_character<typename From::char_type>::value &&
|
||||
extension_traits::is_narrow_character<typename To::char_type>::value>::type> : public json_visitor_adaptor_base<From,To>
|
||||
{
|
||||
using supertype = json_visitor_adaptor_base<From,To>;
|
||||
using to_char_type = typename To::char_type;
|
||||
using from_char_type = typename From::char_type;
|
||||
public:
|
||||
using typename From::string_view_type;
|
||||
using supertype::destination;
|
||||
private:
|
||||
|
||||
// noncopyable
|
||||
json_visitor_adaptor(const json_visitor_adaptor&) = delete;
|
||||
json_visitor_adaptor& operator=(const json_visitor_adaptor&) = delete;
|
||||
public:
|
||||
json_visitor_adaptor(To& visitor)
|
||||
: supertype(visitor)
|
||||
{
|
||||
}
|
||||
|
||||
// moveable
|
||||
json_visitor_adaptor(json_visitor_adaptor&&) = default;
|
||||
json_visitor_adaptor& operator=(json_visitor_adaptor&&) = default;
|
||||
|
||||
private:
|
||||
|
||||
bool visit_key(const string_view_type& key,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination().key(string_view_type(reinterpret_cast<const to_char_type*>(key.data()),key.size()), context, ec);
|
||||
}
|
||||
|
||||
bool visit_string(const string_view_type& value,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return destination().string_value(string_view_type(reinterpret_cast<const to_char_type*>(value.data()),value.size()), tag, context, ec);
|
||||
}
|
||||
};
|
||||
|
||||
template <class From,class To>
|
||||
class json_visitor_adaptor<From,To,typename std::enable_if<!(extension_traits::is_narrow_character<typename From::char_type>::value &&
|
||||
extension_traits::is_narrow_character<typename To::char_type>::value)>::type> : public json_visitor_adaptor_base<From,To>
|
||||
{
|
||||
using supertype = json_visitor_adaptor_base<From,To>;
|
||||
public:
|
||||
using typename From::string_view_type;
|
||||
using supertype::destination;
|
||||
private:
|
||||
|
||||
// noncopyable
|
||||
json_visitor_adaptor(const json_visitor_adaptor&) = delete;
|
||||
json_visitor_adaptor& operator=(const json_visitor_adaptor&) = delete;
|
||||
public:
|
||||
json_visitor_adaptor(To& visitor)
|
||||
: supertype(visitor)
|
||||
{
|
||||
}
|
||||
|
||||
// moveable
|
||||
json_visitor_adaptor(json_visitor_adaptor&&) = default;
|
||||
json_visitor_adaptor& operator=(json_visitor_adaptor&&) = default;
|
||||
|
||||
private:
|
||||
|
||||
bool visit_key(const string_view_type& name,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
std::basic_string<typename To::char_type> target;
|
||||
auto result = unicode_traits::convert(name.data(), name.size(), target, unicode_traits::conv_flags::strict);
|
||||
if (result.ec != unicode_traits::conv_errc())
|
||||
{
|
||||
ec = result.ec;
|
||||
}
|
||||
return destination().key(target, context, ec);
|
||||
}
|
||||
|
||||
bool visit_string(const string_view_type& value,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
std::basic_string<typename To::char_type> target;
|
||||
auto result = unicode_traits::convert(value.data(), value.size(),
|
||||
target,unicode_traits::conv_flags::strict);
|
||||
if (result.ec != unicode_traits::conv_errc())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(result.ec));
|
||||
}
|
||||
return destination().string_value(target, tag, context, ec);
|
||||
}
|
||||
};
|
||||
|
||||
template <class From,class To>
|
||||
json_visitor_adaptor<From,To> make_json_visitor_adaptor(To& to)
|
||||
{
|
||||
return json_visitor_adaptor<From, To>(to);
|
||||
}
|
||||
|
||||
using json_filter = basic_json_filter<char>;
|
||||
using wjson_filter = basic_json_filter<wchar_t>;
|
||||
using rename_object_key_filter = basic_rename_object_key_filter<char>;
|
||||
using wrename_object_key_filter = basic_rename_object_key_filter<wchar_t>;
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
template <class CharT>
|
||||
using basic_json_content_filter = basic_json_filter<CharT>;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use json_filter") typedef basic_json_filter<char> json_content_filter;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use wjson_filter") typedef basic_json_filter<wchar_t> wjson_content_filter;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use rename_object_key_filter") typedef basic_rename_object_key_filter<char> rename_name_filter;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use wrename_object_key_filter") typedef basic_rename_object_key_filter<wchar_t> wrename_name_filter;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use rename_object_key_filter") typedef basic_rename_object_key_filter<char> rename_object_member_filter;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use wrename_object_key_filter") typedef basic_rename_object_key_filter<wchar_t> wrename_object_member_filter;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
23
scripts/exe/jsoncons/include/jsoncons/json_fwd.hpp
Normal file
23
scripts/exe/jsoncons/include/jsoncons/json_fwd.hpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_FWD_HPP
|
||||
#define JSONCONS_JSON_FWD_HPP
|
||||
|
||||
#include <memory> // std::allocator
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
struct sorted_policy;
|
||||
|
||||
template <class CharT,
|
||||
class ImplementationPolicy = sorted_policy,
|
||||
class Allocator = std::allocator<CharT>>
|
||||
class basic_json;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
1871
scripts/exe/jsoncons/include/jsoncons/json_object.hpp
Normal file
1871
scripts/exe/jsoncons/include/jsoncons/json_object.hpp
Normal file
File diff suppressed because it is too large
Load diff
860
scripts/exe/jsoncons/include/jsoncons/json_options.hpp
Normal file
860
scripts/exe/jsoncons/include/jsoncons/json_options.hpp
Normal file
|
|
@ -0,0 +1,860 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_OPTIONS_HPP
|
||||
#define JSONCONS_JSON_OPTIONS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <cwchar>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/extension_traits.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
enum class float_chars_format : uint8_t {general,fixed,scientific,hex};
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use float_chars_format") typedef float_chars_format chars_format;
|
||||
#endif
|
||||
|
||||
enum class indenting : uint8_t {no_indent = 0, indent = 1};
|
||||
|
||||
enum class line_split_kind : uint8_t {same_line,new_line,multi_line};
|
||||
|
||||
enum class bigint_chars_format : uint8_t {number, base10, base64, base64url
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
,integer = number
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use bigint_chars_format") typedef bigint_chars_format bignum_chars_format;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use bigint_chars_format") typedef bigint_chars_format big_integer_chars_format;
|
||||
#endif
|
||||
|
||||
enum class byte_string_chars_format : uint8_t {none=0,base16,base64,base64url};
|
||||
|
||||
enum class spaces_option : uint8_t {no_spaces=0,space_after,space_before,space_before_and_after};
|
||||
|
||||
template <class CharT>
|
||||
class basic_json_options;
|
||||
|
||||
template <class CharT>
|
||||
class basic_json_options_common
|
||||
{
|
||||
friend class basic_json_options<CharT>;
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using string_type = std::basic_string<CharT>;
|
||||
private:
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
bool can_read_nan_replacement_;
|
||||
bool can_read_pos_inf_replacement_;
|
||||
bool can_read_neg_inf_replacement_;
|
||||
string_type nan_replacement_;
|
||||
string_type pos_inf_replacement_;
|
||||
string_type neg_inf_replacement_;
|
||||
#endif
|
||||
|
||||
bool enable_nan_to_num_:1;
|
||||
bool enable_inf_to_num_:1;
|
||||
bool enable_neginf_to_num_:1;
|
||||
bool enable_nan_to_str_:1;
|
||||
bool enable_inf_to_str_:1;
|
||||
bool enable_neginf_to_str_:1;
|
||||
bool enable_str_to_nan_:1;
|
||||
bool enable_str_to_inf_:1;
|
||||
bool enable_str_to_neginf_:1;
|
||||
|
||||
string_type nan_to_num_;
|
||||
string_type inf_to_num_;
|
||||
string_type neginf_to_num_;
|
||||
string_type nan_to_str_;
|
||||
string_type inf_to_str_;
|
||||
string_type neginf_to_str_;
|
||||
int max_nesting_depth_;
|
||||
|
||||
protected:
|
||||
basic_json_options_common()
|
||||
:
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
can_read_nan_replacement_(false),
|
||||
can_read_pos_inf_replacement_(false),
|
||||
can_read_neg_inf_replacement_(false),
|
||||
#endif
|
||||
enable_nan_to_num_(false),
|
||||
enable_inf_to_num_(false),
|
||||
enable_neginf_to_num_(false),
|
||||
enable_nan_to_str_(false),
|
||||
enable_inf_to_str_(false),
|
||||
enable_neginf_to_str_(false),
|
||||
enable_str_to_nan_(false),
|
||||
enable_str_to_inf_(false),
|
||||
enable_str_to_neginf_(false),
|
||||
max_nesting_depth_(1024)
|
||||
{}
|
||||
|
||||
virtual ~basic_json_options_common() noexcept = default;
|
||||
|
||||
basic_json_options_common(const basic_json_options_common&) = default;
|
||||
basic_json_options_common& operator=(const basic_json_options_common&) = default;
|
||||
basic_json_options_common(basic_json_options_common&&) = default;
|
||||
basic_json_options_common& operator=(basic_json_options_common&&) = default;
|
||||
|
||||
public:
|
||||
|
||||
bool enable_nan_to_num() const
|
||||
{
|
||||
return enable_nan_to_num_;
|
||||
}
|
||||
|
||||
bool enable_inf_to_num() const
|
||||
{
|
||||
return enable_inf_to_num_;
|
||||
}
|
||||
|
||||
bool enable_neginf_to_num() const
|
||||
{
|
||||
return enable_neginf_to_num_ || enable_inf_to_num_;
|
||||
}
|
||||
|
||||
bool enable_nan_to_str() const
|
||||
{
|
||||
return enable_nan_to_str_;
|
||||
}
|
||||
|
||||
bool enable_str_to_nan() const
|
||||
{
|
||||
return enable_str_to_nan_;
|
||||
}
|
||||
|
||||
bool enable_inf_to_str() const
|
||||
{
|
||||
return enable_inf_to_str_;
|
||||
}
|
||||
|
||||
bool enable_str_to_inf() const
|
||||
{
|
||||
return enable_str_to_inf_;
|
||||
}
|
||||
|
||||
bool enable_neginf_to_str() const
|
||||
{
|
||||
return enable_neginf_to_str_ || enable_inf_to_str_;
|
||||
}
|
||||
|
||||
bool enable_str_to_neginf() const
|
||||
{
|
||||
return enable_str_to_neginf_ || enable_str_to_inf_;
|
||||
}
|
||||
|
||||
string_type nan_to_num() const
|
||||
{
|
||||
if (enable_nan_to_num_)
|
||||
{
|
||||
return nan_to_num_;
|
||||
}
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
else if (!can_read_nan_replacement_) // not string
|
||||
{
|
||||
return nan_replacement_;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return nan_to_num_; // empty string
|
||||
}
|
||||
}
|
||||
|
||||
string_type inf_to_num() const
|
||||
{
|
||||
if (enable_inf_to_num_)
|
||||
{
|
||||
return inf_to_num_;
|
||||
}
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
else if (!can_read_pos_inf_replacement_) // not string
|
||||
{
|
||||
return pos_inf_replacement_;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return inf_to_num_; // empty string
|
||||
}
|
||||
}
|
||||
|
||||
string_type neginf_to_num() const
|
||||
{
|
||||
if (enable_neginf_to_num_)
|
||||
{
|
||||
return neginf_to_num_;
|
||||
}
|
||||
else if (enable_inf_to_num_)
|
||||
{
|
||||
string_type s;
|
||||
s.push_back('-');
|
||||
s.append(inf_to_num_);
|
||||
return s;
|
||||
}
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
else if (!can_read_neg_inf_replacement_) // not string
|
||||
{
|
||||
return neg_inf_replacement_;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return neginf_to_num_; // empty string
|
||||
}
|
||||
}
|
||||
|
||||
string_type nan_to_str() const
|
||||
{
|
||||
if (enable_nan_to_str_)
|
||||
{
|
||||
return nan_to_str_;
|
||||
}
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
else if (can_read_nan_replacement_ && nan_replacement_.size() >= 2) // string
|
||||
{
|
||||
return nan_replacement_.substr(1, nan_replacement_.size() - 2); // Remove quotes
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return nan_to_str_; // empty string
|
||||
}
|
||||
}
|
||||
|
||||
string_type inf_to_str() const
|
||||
{
|
||||
if (enable_inf_to_str_)
|
||||
{
|
||||
return inf_to_str_;
|
||||
}
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
else if (can_read_pos_inf_replacement_ && pos_inf_replacement_.size() >= 2) // string
|
||||
{
|
||||
return pos_inf_replacement_.substr(1, pos_inf_replacement_.size() - 2); // Strip quotes
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return inf_to_str_; // empty string
|
||||
}
|
||||
}
|
||||
|
||||
string_type neginf_to_str() const
|
||||
{
|
||||
if (enable_neginf_to_str_)
|
||||
{
|
||||
return neginf_to_str_;
|
||||
}
|
||||
else if (enable_inf_to_str_)
|
||||
{
|
||||
string_type s;
|
||||
s.push_back('-');
|
||||
s.append(inf_to_str_);
|
||||
return s;
|
||||
}
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
else if (can_read_neg_inf_replacement_ && neg_inf_replacement_.size() >= 2) // string
|
||||
{
|
||||
return neg_inf_replacement_.substr(1, neg_inf_replacement_.size() - 2); // Strip quotes
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return neginf_to_str_; // empty string
|
||||
}
|
||||
}
|
||||
|
||||
int max_nesting_depth() const
|
||||
{
|
||||
return max_nesting_depth_;
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use enable_nan_to_num() or enable_nan_to_str()")
|
||||
bool can_read_nan_replacement() const { return can_read_nan_replacement_; }
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use enable_inf_to_num() or enable_inf_to_str()")
|
||||
bool can_read_pos_inf_replacement() const { return can_read_pos_inf_replacement_; }
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use enable_neginf_to_num() or enable_neginf_to_str()")
|
||||
bool can_read_neg_inf_replacement() const { return can_read_neg_inf_replacement_; }
|
||||
|
||||
bool can_write_nan_replacement() const { return !nan_replacement_.empty(); }
|
||||
|
||||
bool can_write_pos_inf_replacement() const { return !pos_inf_replacement_.empty(); }
|
||||
|
||||
bool can_write_neg_inf_replacement() const { return !neg_inf_replacement_.empty(); }
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use nan_to_num() or nan_to_str()")
|
||||
const string_type& nan_replacement() const
|
||||
{
|
||||
return nan_replacement_;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use inf_to_num() or inf_to_str()")
|
||||
const string_type& pos_inf_replacement() const
|
||||
{
|
||||
return pos_inf_replacement_;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use neginf_to_num() or neginf_to_str()")
|
||||
const string_type& neg_inf_replacement() const
|
||||
{
|
||||
return neg_inf_replacement_;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
class basic_json_decode_options : public virtual basic_json_options_common<CharT>
|
||||
{
|
||||
friend class basic_json_options<CharT>;
|
||||
using super_type = basic_json_options_common<CharT>;
|
||||
public:
|
||||
using typename super_type::char_type;
|
||||
using typename super_type::string_type;
|
||||
private:
|
||||
bool lossless_number_:1;
|
||||
public:
|
||||
basic_json_decode_options()
|
||||
: lossless_number_(false)
|
||||
{
|
||||
}
|
||||
|
||||
basic_json_decode_options(const basic_json_decode_options&) = default;
|
||||
|
||||
basic_json_decode_options(basic_json_decode_options&& other)
|
||||
: super_type(std::forward<basic_json_decode_options>(other)),
|
||||
lossless_number_(other.lossless_number_)
|
||||
{
|
||||
}
|
||||
|
||||
basic_json_decode_options& operator=(const basic_json_decode_options&) = default;
|
||||
|
||||
bool lossless_number() const
|
||||
{
|
||||
return lossless_number_;
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use lossless_number()")
|
||||
bool dec_to_str() const
|
||||
{
|
||||
return lossless_number_;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
class basic_json_encode_options : public virtual basic_json_options_common<CharT>
|
||||
{
|
||||
friend class basic_json_options<CharT>;
|
||||
using super_type = basic_json_options_common<CharT>;
|
||||
public:
|
||||
using typename super_type::char_type;
|
||||
using typename super_type::string_type;
|
||||
|
||||
static constexpr uint8_t indent_size_default = 4;
|
||||
static constexpr size_t line_length_limit_default = 120;
|
||||
private:
|
||||
bool escape_all_non_ascii_:1;
|
||||
bool escape_solidus_:1;
|
||||
bool pad_inside_object_braces_:1;
|
||||
bool pad_inside_array_brackets_:1;
|
||||
float_chars_format float_format_;
|
||||
byte_string_chars_format byte_string_format_;
|
||||
bigint_chars_format bigint_format_;
|
||||
line_split_kind object_object_line_splits_;
|
||||
line_split_kind object_array_line_splits_;
|
||||
line_split_kind array_array_line_splits_;
|
||||
line_split_kind array_object_line_splits_;
|
||||
spaces_option spaces_around_colon_;
|
||||
spaces_option spaces_around_comma_;
|
||||
int8_t precision_;
|
||||
uint8_t indent_size_;
|
||||
std::size_t line_length_limit_;
|
||||
string_type new_line_chars_;
|
||||
public:
|
||||
basic_json_encode_options()
|
||||
: escape_all_non_ascii_(false),
|
||||
escape_solidus_(false),
|
||||
pad_inside_object_braces_(false),
|
||||
pad_inside_array_brackets_(false),
|
||||
float_format_(float_chars_format::general),
|
||||
byte_string_format_(byte_string_chars_format::none),
|
||||
bigint_format_(bigint_chars_format::base10),
|
||||
object_object_line_splits_(line_split_kind::multi_line),
|
||||
object_array_line_splits_(line_split_kind::same_line),
|
||||
array_array_line_splits_(line_split_kind::new_line),
|
||||
array_object_line_splits_(line_split_kind::multi_line),
|
||||
spaces_around_colon_(spaces_option::space_after),
|
||||
spaces_around_comma_(spaces_option::space_after),
|
||||
precision_(0),
|
||||
indent_size_(indent_size_default),
|
||||
line_length_limit_(line_length_limit_default)
|
||||
{
|
||||
new_line_chars_.push_back('\n');
|
||||
}
|
||||
|
||||
basic_json_encode_options(const basic_json_encode_options&) = default;
|
||||
|
||||
basic_json_encode_options(basic_json_encode_options&& other)
|
||||
: super_type(std::forward<basic_json_encode_options>(other)),
|
||||
escape_all_non_ascii_(other.escape_all_non_ascii_),
|
||||
escape_solidus_(other.escape_solidus_),
|
||||
pad_inside_object_braces_(other.pad_inside_object_braces_),
|
||||
pad_inside_array_brackets_(other.pad_inside_array_brackets_),
|
||||
float_format_(other.float_format_),
|
||||
byte_string_format_(other.byte_string_format_),
|
||||
bigint_format_(other.bigint_format_),
|
||||
object_object_line_splits_(other.object_object_line_splits_),
|
||||
object_array_line_splits_(other.object_array_line_splits_),
|
||||
array_array_line_splits_(other.array_array_line_splits_),
|
||||
array_object_line_splits_(other.array_object_line_splits_),
|
||||
spaces_around_colon_(other.spaces_around_colon_),
|
||||
spaces_around_comma_(other.spaces_around_comma_),
|
||||
precision_(other.precision_),
|
||||
indent_size_(other.indent_size_),
|
||||
line_length_limit_(other.line_length_limit_),
|
||||
new_line_chars_(std::move(other.new_line_chars_))
|
||||
{
|
||||
}
|
||||
|
||||
basic_json_encode_options& operator=(const basic_json_encode_options&) = default;
|
||||
|
||||
byte_string_chars_format byte_string_format() const {return byte_string_format_;}
|
||||
|
||||
bigint_chars_format bigint_format() const {return bigint_format_;}
|
||||
|
||||
line_split_kind object_object_line_splits() const {return object_object_line_splits_;}
|
||||
|
||||
line_split_kind array_object_line_splits() const {return array_object_line_splits_;}
|
||||
|
||||
line_split_kind object_array_line_splits() const {return object_array_line_splits_;}
|
||||
|
||||
line_split_kind array_array_line_splits() const {return array_array_line_splits_;}
|
||||
|
||||
uint8_t indent_size() const
|
||||
{
|
||||
return indent_size_;
|
||||
}
|
||||
|
||||
spaces_option spaces_around_colon() const
|
||||
{
|
||||
return spaces_around_colon_;
|
||||
}
|
||||
|
||||
spaces_option spaces_around_comma() const
|
||||
{
|
||||
return spaces_around_comma_;
|
||||
}
|
||||
|
||||
bool pad_inside_object_braces() const
|
||||
{
|
||||
return pad_inside_object_braces_;
|
||||
}
|
||||
|
||||
bool pad_inside_array_brackets() const
|
||||
{
|
||||
return pad_inside_array_brackets_;
|
||||
}
|
||||
|
||||
string_type new_line_chars() const
|
||||
{
|
||||
return new_line_chars_;
|
||||
}
|
||||
|
||||
std::size_t line_length_limit() const
|
||||
{
|
||||
return line_length_limit_;
|
||||
}
|
||||
|
||||
float_chars_format float_format() const
|
||||
{
|
||||
return float_format_;
|
||||
}
|
||||
|
||||
int8_t precision() const
|
||||
{
|
||||
return precision_;
|
||||
}
|
||||
|
||||
bool escape_all_non_ascii() const
|
||||
{
|
||||
return escape_all_non_ascii_;
|
||||
}
|
||||
|
||||
bool escape_solidus() const
|
||||
{
|
||||
return escape_solidus_;
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use bigint_format()")
|
||||
bigint_chars_format bignum_format() const {return bigint_format_;}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use indent_size()")
|
||||
uint8_t indent() const
|
||||
{
|
||||
return indent_size();
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use object_object_line_splits()")
|
||||
line_split_kind object_object_split_lines() const {return object_object_line_splits_;}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use array_object_line_splits()")
|
||||
line_split_kind array_object_split_lines() const {return array_object_line_splits_;}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use object_array_line_splits()")
|
||||
line_split_kind object_array_split_lines() const {return object_array_line_splits_;}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use array_array_line_splits()")
|
||||
line_split_kind array_array_split_lines() const {return array_array_line_splits_;}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
class basic_json_options final: public basic_json_decode_options<CharT>,
|
||||
public basic_json_encode_options<CharT>
|
||||
{
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using string_type = std::basic_string<CharT>;
|
||||
|
||||
using basic_json_options_common<CharT>::max_nesting_depth;
|
||||
|
||||
using basic_json_decode_options<CharT>::enable_str_to_nan;
|
||||
using basic_json_decode_options<CharT>::enable_str_to_inf;
|
||||
using basic_json_decode_options<CharT>::enable_str_to_neginf;
|
||||
using basic_json_decode_options<CharT>::nan_to_str;
|
||||
using basic_json_decode_options<CharT>::inf_to_str;
|
||||
using basic_json_decode_options<CharT>::neginf_to_str;
|
||||
using basic_json_decode_options<CharT>::nan_to_num;
|
||||
using basic_json_decode_options<CharT>::inf_to_num;
|
||||
using basic_json_decode_options<CharT>::neginf_to_num;
|
||||
|
||||
using basic_json_decode_options<CharT>::lossless_number;
|
||||
|
||||
using basic_json_encode_options<CharT>::byte_string_format;
|
||||
using basic_json_encode_options<CharT>::bigint_format;
|
||||
using basic_json_encode_options<CharT>::object_object_line_splits;
|
||||
using basic_json_encode_options<CharT>::array_object_line_splits;
|
||||
using basic_json_encode_options<CharT>::object_array_line_splits;
|
||||
using basic_json_encode_options<CharT>::array_array_line_splits;
|
||||
using basic_json_encode_options<CharT>::indent_size;
|
||||
using basic_json_encode_options<CharT>::spaces_around_colon;
|
||||
using basic_json_encode_options<CharT>::spaces_around_comma;
|
||||
using basic_json_encode_options<CharT>::pad_inside_object_braces;
|
||||
using basic_json_encode_options<CharT>::pad_inside_array_brackets;
|
||||
using basic_json_encode_options<CharT>::new_line_chars;
|
||||
using basic_json_encode_options<CharT>::line_length_limit;
|
||||
using basic_json_encode_options<CharT>::float_format;
|
||||
using basic_json_encode_options<CharT>::precision;
|
||||
using basic_json_encode_options<CharT>::escape_all_non_ascii;
|
||||
using basic_json_encode_options<CharT>::escape_solidus;
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
basic_json_options() = default;
|
||||
basic_json_options(const basic_json_options&) = default;
|
||||
basic_json_options(basic_json_options&&) = default;
|
||||
basic_json_options& operator=(const basic_json_options&) = default;
|
||||
basic_json_options& operator=(basic_json_options&&) = default;
|
||||
|
||||
basic_json_options& nan_to_num(const string_type& value)
|
||||
{
|
||||
this->enable_nan_to_num_ = true;
|
||||
this->nan_to_str_.clear();
|
||||
this->nan_to_num_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& inf_to_num(const string_type& value)
|
||||
{
|
||||
this->enable_inf_to_num_ = true;
|
||||
this->inf_to_str_.clear();
|
||||
this->inf_to_num_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& neginf_to_num(const string_type& value)
|
||||
{
|
||||
this->enable_neginf_to_num_ = true;
|
||||
this->neginf_to_str_.clear();
|
||||
this->neginf_to_num_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& nan_to_str(const string_type& value, bool enable_inverse = true)
|
||||
{
|
||||
this->enable_nan_to_str_ = true;
|
||||
this->enable_str_to_nan_ = enable_inverse;
|
||||
this->nan_to_num_.clear();
|
||||
this->nan_to_str_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& inf_to_str(const string_type& value, bool enable_inverse = true)
|
||||
{
|
||||
this->enable_inf_to_str_ = true;
|
||||
this->enable_str_to_inf_ = enable_inverse;
|
||||
this->inf_to_num_.clear();
|
||||
this->inf_to_str_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& neginf_to_str(const string_type& value, bool enable_inverse = true)
|
||||
{
|
||||
this->enable_neginf_to_str_ = true;
|
||||
this->enable_str_to_neginf_ = enable_inverse;
|
||||
this->neginf_to_num_.clear();
|
||||
this->neginf_to_str_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use inf_to_num(const string_type&) or inf_to_str(const string_type&)")
|
||||
basic_json_options& replace_inf(bool replace)
|
||||
{
|
||||
this->can_read_pos_inf_replacement_ = replace;
|
||||
this->can_read_neg_inf_replacement_ = replace;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use inf_to_num(const string_type&) or inf_to_str(const string_type&)")
|
||||
basic_json_options& replace_pos_inf(bool replace)
|
||||
{
|
||||
this->can_read_pos_inf_replacement_ = replace;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use neginf_to_num(const string_type&) or neginf_to_str(const string_type&)")
|
||||
basic_json_options& replace_neg_inf(bool replace)
|
||||
{
|
||||
this->can_read_neg_inf_replacement_ = replace;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use nan_to_num(const string_type&) or nan_to_str(const string_type&)")
|
||||
basic_json_options& nan_replacement(const string_type& value)
|
||||
{
|
||||
this->nan_replacement_ = value;
|
||||
|
||||
this->can_read_nan_replacement_ = is_string(value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use inf_to_num(const string_type&) or inf_to_str(const string_type&)")
|
||||
basic_json_options& pos_inf_replacement(const string_type& value)
|
||||
{
|
||||
this->pos_inf_replacement_ = value;
|
||||
this->can_read_pos_inf_replacement_ = is_string(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use neginf_to_num(const string_type&) or neginf_to_str(const string_type&)")
|
||||
basic_json_options& neg_inf_replacement(const string_type& value)
|
||||
{
|
||||
this->neg_inf_replacement_ = value;
|
||||
this->can_read_neg_inf_replacement_ = is_string(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& byte_string_format(byte_string_chars_format value) {this->byte_string_format_ = value; return *this;}
|
||||
|
||||
basic_json_options& bigint_format(bigint_chars_format value) {this->bigint_format_ = value; return *this;}
|
||||
|
||||
basic_json_options& object_object_line_splits(line_split_kind value) {this->object_object_line_splits_ = value; return *this;}
|
||||
|
||||
basic_json_options& array_object_line_splits(line_split_kind value) {this->array_object_line_splits_ = value; return *this;}
|
||||
|
||||
basic_json_options& object_array_line_splits(line_split_kind value) {this->object_array_line_splits_ = value; return *this;}
|
||||
|
||||
basic_json_options& array_array_line_splits(line_split_kind value) {this->array_array_line_splits_ = value; return *this;}
|
||||
|
||||
basic_json_options& indent_size(uint8_t value)
|
||||
{
|
||||
this->indent_size_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& spaces_around_colon(spaces_option value)
|
||||
{
|
||||
this->spaces_around_colon_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& spaces_around_comma(spaces_option value)
|
||||
{
|
||||
this->spaces_around_comma_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& pad_inside_object_braces(bool value)
|
||||
{
|
||||
this->pad_inside_object_braces_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& pad_inside_array_brackets(bool value)
|
||||
{
|
||||
this->pad_inside_array_brackets_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& new_line_chars(const string_type& value)
|
||||
{
|
||||
this->new_line_chars_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& lossless_number(bool value)
|
||||
{
|
||||
this->lossless_number_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& line_length_limit(std::size_t value)
|
||||
{
|
||||
this->line_length_limit_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& float_format(float_chars_format value)
|
||||
{
|
||||
this->float_format_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& precision(int8_t value)
|
||||
{
|
||||
this->precision_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& escape_all_non_ascii(bool value)
|
||||
{
|
||||
this->escape_all_non_ascii_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& escape_solidus(bool value)
|
||||
{
|
||||
this->escape_solidus_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_json_options& max_nesting_depth(int value)
|
||||
{
|
||||
this->max_nesting_depth_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use bigint_format(bigint_chars_format)")
|
||||
basic_json_options& big_integer_format(bigint_chars_format value) {this->bigint_format_ = value; return *this;}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use bigint_format(bigint_chars_format)")
|
||||
basic_json_options& bignum_format(bigint_chars_format value) {this->bigint_format_ = value; return *this;}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use float_format(float_chars_format)")
|
||||
basic_json_options& floating_point_format(float_chars_format value)
|
||||
{
|
||||
this->float_format_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use lossless_number(bool)")
|
||||
basic_json_options& dec_to_str(bool value)
|
||||
{
|
||||
this->lossless_number_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use indent_size(uint8_t_t)")
|
||||
basic_json_options& indent(uint8_t value)
|
||||
{
|
||||
return indent_size(value);
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use object_object_line_splits(line_split_kind)")
|
||||
basic_json_options& object_object_split_lines(line_split_kind value) {this->object_object_line_splits_ = value; return *this;}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use array_object_line_splits(line_split_kind)")
|
||||
basic_json_options& array_object_split_lines(line_split_kind value) {this->array_object_line_splits_ = value; return *this;}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use object_array_line_splits(line_split_kind)")
|
||||
basic_json_options& object_array_split_lines(line_split_kind value) {this->object_array_line_splits_ = value; return *this;}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use array_array_line_splits(line_split_kind)")
|
||||
basic_json_options& array_array_split_lines(line_split_kind value) {this->array_array_line_splits_ = value; return *this;}
|
||||
#endif
|
||||
private:
|
||||
enum class input_state {initial,begin_quote,character,end_quote,escape,error};
|
||||
bool is_string(const string_type& s) const
|
||||
{
|
||||
input_state state = input_state::initial;
|
||||
for (char_type c : s)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\t': case ' ': case '\n': case'\r':
|
||||
break;
|
||||
case '\\':
|
||||
state = input_state::escape;
|
||||
break;
|
||||
case '\"':
|
||||
switch (state)
|
||||
{
|
||||
case input_state::initial:
|
||||
state = input_state::begin_quote;
|
||||
break;
|
||||
case input_state::begin_quote:
|
||||
case input_state::character:
|
||||
state = input_state::end_quote;
|
||||
break;
|
||||
case input_state::end_quote:
|
||||
state = input_state::error;
|
||||
break;
|
||||
case input_state::escape:
|
||||
state = input_state::character;
|
||||
break;
|
||||
default:
|
||||
state = input_state::character;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return state == input_state::end_quote;
|
||||
}
|
||||
};
|
||||
|
||||
using json_options = basic_json_options<char>;
|
||||
using wjson_options = basic_json_options<wchar_t>;
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("json_options") typedef json_options output_format;
|
||||
JSONCONS_DEPRECATED_MSG("wjson_options") typedef wjson_options woutput_format;
|
||||
JSONCONS_DEPRECATED_MSG("json_options") typedef json_options serialization_options;
|
||||
JSONCONS_DEPRECATED_MSG("wjson_options") typedef wjson_options wserialization_options;
|
||||
JSONCONS_DEPRECATED_MSG("json_options") typedef json_options json_serializing_options;
|
||||
JSONCONS_DEPRECATED_MSG("wjson_options") typedef wjson_options wjson_serializing_options;
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
2887
scripts/exe/jsoncons/include/jsoncons/json_parser.hpp
Normal file
2887
scripts/exe/jsoncons/include/jsoncons/json_parser.hpp
Normal file
File diff suppressed because it is too large
Load diff
731
scripts/exe/jsoncons/include/jsoncons/json_reader.hpp
Normal file
731
scripts/exe/jsoncons/include/jsoncons/json_reader.hpp
Normal file
|
|
@ -0,0 +1,731 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_READER_HPP
|
||||
#define JSONCONS_JSON_READER_HPP
|
||||
|
||||
#include <memory> // std::allocator
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <ios>
|
||||
#include <utility> // std::move
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/json_parser.hpp>
|
||||
#include <jsoncons/source_adaptor.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// utf8_other_json_input_adapter
|
||||
|
||||
template <class CharT>
|
||||
class json_utf8_to_other_visitor_adaptor : public json_visitor
|
||||
{
|
||||
public:
|
||||
using json_visitor::string_view_type;
|
||||
private:
|
||||
basic_default_json_visitor<CharT> default_visitor_;
|
||||
basic_json_visitor<CharT>& other_visitor_;
|
||||
//std::function<bool(json_errc,const ser_context&)> err_handler_;
|
||||
|
||||
// noncopyable and nonmoveable
|
||||
json_utf8_to_other_visitor_adaptor(const json_utf8_to_other_visitor_adaptor<CharT>&) = delete;
|
||||
json_utf8_to_other_visitor_adaptor<CharT>& operator=(const json_utf8_to_other_visitor_adaptor<CharT>&) = delete;
|
||||
|
||||
public:
|
||||
json_utf8_to_other_visitor_adaptor()
|
||||
: other_visitor_(default_visitor_)
|
||||
{
|
||||
}
|
||||
|
||||
json_utf8_to_other_visitor_adaptor(basic_json_visitor<CharT>& other_visitor/*,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler*/)
|
||||
: other_visitor_(other_visitor)/*,
|
||||
err_handler_(err_handler)*/
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void visit_flush() override
|
||||
{
|
||||
other_visitor_.flush();
|
||||
}
|
||||
|
||||
bool visit_begin_object(semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return other_visitor_.begin_object(tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_end_object(const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return other_visitor_.end_object(context, ec);
|
||||
}
|
||||
|
||||
bool visit_begin_array(semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return other_visitor_.begin_array(tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_end_array(const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return other_visitor_.end_array(context, ec);
|
||||
}
|
||||
|
||||
bool visit_key(const string_view_type& name, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
std::basic_string<CharT> target;
|
||||
auto result = unicode_traits::convert(
|
||||
name.data(), name.size(), target,
|
||||
unicode_traits::conv_flags::strict);
|
||||
if (result.ec != unicode_traits::conv_errc())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(result.ec,context.line(),context.column()));
|
||||
}
|
||||
return other_visitor_.key(target, context, ec);
|
||||
}
|
||||
|
||||
bool visit_string(const string_view_type& value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
std::basic_string<CharT> target;
|
||||
auto result = unicode_traits::convert(
|
||||
value.data(), value.size(), target,
|
||||
unicode_traits::conv_flags::strict);
|
||||
if (result.ec != unicode_traits::conv_errc())
|
||||
{
|
||||
ec = result.ec;
|
||||
return false;
|
||||
}
|
||||
return other_visitor_.string_value(target, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_int64(int64_t value,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return other_visitor_.int64_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_uint64(uint64_t value,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return other_visitor_.uint64_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_half(uint16_t value,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return other_visitor_.half_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_double(double value,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
return other_visitor_.double_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_bool(bool value, semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return other_visitor_.bool_value(value, tag, context, ec);
|
||||
}
|
||||
|
||||
bool visit_null(semantic_tag tag, const ser_context& context, std::error_code& ec) override
|
||||
{
|
||||
return other_visitor_.null_value(tag, context, ec);
|
||||
}
|
||||
};
|
||||
|
||||
template<class CharT,class Source=jsoncons::stream_source<CharT>,class Allocator=std::allocator<char>>
|
||||
class basic_json_reader
|
||||
{
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using source_type = Source;
|
||||
using string_view_type = jsoncons::basic_string_view<CharT>;
|
||||
private:
|
||||
typedef typename std::allocator_traits<Allocator>:: template rebind_alloc<CharT> char_allocator_type;
|
||||
|
||||
static constexpr size_t default_max_buffer_size = 16384;
|
||||
|
||||
json_source_adaptor<Source> source_;
|
||||
basic_default_json_visitor<CharT> default_visitor_;
|
||||
basic_json_visitor<CharT>& visitor_;
|
||||
basic_json_parser<CharT,Allocator> parser_;
|
||||
|
||||
// Noncopyable and nonmoveable
|
||||
basic_json_reader(const basic_json_reader&) = delete;
|
||||
basic_json_reader& operator=(const basic_json_reader&) = delete;
|
||||
|
||||
public:
|
||||
template <class Sourceable>
|
||||
explicit basic_json_reader(Sourceable&& source, const Allocator& alloc = Allocator())
|
||||
: basic_json_reader(std::forward<Sourceable>(source),
|
||||
default_visitor_,
|
||||
basic_json_decode_options<CharT>(),
|
||||
default_json_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_reader(Sourceable&& source,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
const Allocator& alloc = Allocator())
|
||||
: basic_json_reader(std::forward<Sourceable>(source),
|
||||
default_visitor_,
|
||||
options,
|
||||
default_json_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_reader(Sourceable&& source,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator())
|
||||
: basic_json_reader(std::forward<Sourceable>(source),
|
||||
default_visitor_,
|
||||
basic_json_decode_options<CharT>(),
|
||||
err_handler,
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_reader(Sourceable&& source,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator())
|
||||
: basic_json_reader(std::forward<Sourceable>(source),
|
||||
default_visitor_,
|
||||
options,
|
||||
err_handler,
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const Allocator& alloc = Allocator())
|
||||
: basic_json_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
basic_json_decode_options<CharT>(),
|
||||
default_json_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
const Allocator& alloc = Allocator())
|
||||
: basic_json_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
options,
|
||||
default_json_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator())
|
||||
: basic_json_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
basic_json_decode_options<CharT>(),
|
||||
err_handler,
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_json_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator())
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
visitor_(visitor),
|
||||
parser_(options,err_handler,alloc)
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use max_nesting_depth() on options")
|
||||
int max_nesting_depth() const
|
||||
{
|
||||
return parser_.max_nesting_depth();
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use max_nesting_depth(int) on options")
|
||||
void max_nesting_depth(int depth)
|
||||
{
|
||||
parser_.max_nesting_depth(depth);
|
||||
}
|
||||
#endif
|
||||
void read_next()
|
||||
{
|
||||
std::error_code ec;
|
||||
read_next(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read_next(std::error_code& ec)
|
||||
{
|
||||
if (source_.is_error())
|
||||
{
|
||||
ec = json_errc::source_error;
|
||||
return;
|
||||
}
|
||||
parser_.reset();
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
}
|
||||
}
|
||||
bool eof = parser_.source_exhausted();
|
||||
parser_.parse_some(visitor_, ec);
|
||||
if (ec) return;
|
||||
if (eof)
|
||||
{
|
||||
if (parser_.enter())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (!parser_.accept())
|
||||
{
|
||||
ec = json_errc::unexpected_eof;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!source_.eof())
|
||||
{
|
||||
parser_.skip_whitespace();
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void check_done()
|
||||
{
|
||||
std::error_code ec;
|
||||
check_done(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t line() const
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
|
||||
void check_done(std::error_code& ec)
|
||||
{
|
||||
if (source_.is_error())
|
||||
{
|
||||
ec = json_errc::source_error;
|
||||
return;
|
||||
}
|
||||
if (source_.eof())
|
||||
{
|
||||
parser_.check_done(ec);
|
||||
if (ec) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
}
|
||||
}
|
||||
if (!parser_.source_exhausted())
|
||||
{
|
||||
parser_.check_done(ec);
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
while (!eof());
|
||||
}
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return parser_.source_exhausted() && source_.eof();
|
||||
}
|
||||
|
||||
void read()
|
||||
{
|
||||
read_next();
|
||||
check_done();
|
||||
}
|
||||
|
||||
void read(std::error_code& ec)
|
||||
{
|
||||
read_next(ec);
|
||||
if (!ec)
|
||||
{
|
||||
check_done(ec);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class CharT,class Source=jsoncons::stream_source<CharT>,class Allocator=std::allocator<char>>
|
||||
class legacy_basic_json_reader
|
||||
{
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using source_type = Source;
|
||||
using string_view_type = jsoncons::basic_string_view<CharT>;
|
||||
private:
|
||||
typedef typename std::allocator_traits<Allocator>:: template rebind_alloc<CharT> char_allocator_type;
|
||||
|
||||
static constexpr size_t default_max_buffer_size = 16384;
|
||||
|
||||
json_source_adaptor<Source> source_;
|
||||
basic_default_json_visitor<CharT> default_visitor_;
|
||||
basic_json_visitor<CharT>& visitor_;
|
||||
basic_json_parser<CharT,Allocator> parser_;
|
||||
|
||||
// Noncopyable and nonmoveable
|
||||
legacy_basic_json_reader(const legacy_basic_json_reader&) = delete;
|
||||
legacy_basic_json_reader& operator=(const legacy_basic_json_reader&) = delete;
|
||||
|
||||
public:
|
||||
template <class Sourceable>
|
||||
explicit legacy_basic_json_reader(Sourceable&& source, const Allocator& alloc = Allocator())
|
||||
: legacy_basic_json_reader(std::forward<Sourceable>(source),
|
||||
default_visitor_,
|
||||
basic_json_decode_options<CharT>(),
|
||||
default_json_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_json_reader(Sourceable&& source,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
const Allocator& alloc = Allocator())
|
||||
: legacy_basic_json_reader(std::forward<Sourceable>(source),
|
||||
default_visitor_,
|
||||
options,
|
||||
default_json_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_json_reader(Sourceable&& source,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator())
|
||||
: legacy_basic_json_reader(std::forward<Sourceable>(source),
|
||||
default_visitor_,
|
||||
basic_json_decode_options<CharT>(),
|
||||
err_handler,
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_json_reader(Sourceable&& source,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator())
|
||||
: legacy_basic_json_reader(std::forward<Sourceable>(source),
|
||||
default_visitor_,
|
||||
options,
|
||||
err_handler,
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_json_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const Allocator& alloc = Allocator())
|
||||
: legacy_basic_json_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
basic_json_decode_options<CharT>(),
|
||||
default_json_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_json_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
const Allocator& alloc = Allocator())
|
||||
: legacy_basic_json_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
options,
|
||||
default_json_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_json_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator())
|
||||
: legacy_basic_json_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
basic_json_decode_options<CharT>(),
|
||||
err_handler,
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_json_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator(),
|
||||
typename std::enable_if<!std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
visitor_(visitor),
|
||||
parser_(options,err_handler,alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_json_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const basic_json_decode_options<CharT>& options,
|
||||
std::function<bool(json_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator(),
|
||||
typename std::enable_if<std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(),
|
||||
visitor_(visitor),
|
||||
parser_(options,err_handler,alloc)
|
||||
{
|
||||
jsoncons::basic_string_view<CharT> sv(std::forward<Sourceable>(source));
|
||||
|
||||
auto r = unicode_traits::detect_json_encoding(sv.data(), sv.size());
|
||||
if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected))
|
||||
{
|
||||
JSONCONS_THROW(ser_error(json_errc::illegal_unicode_character,parser_.line(),parser_.column()));
|
||||
}
|
||||
std::size_t offset = (r.ptr - sv.data());
|
||||
parser_.update(sv.data()+offset,sv.size()-offset);
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use max_nesting_depth() on options")
|
||||
int max_nesting_depth() const
|
||||
{
|
||||
return parser_.max_nesting_depth();
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use max_nesting_depth(int) on options")
|
||||
void max_nesting_depth(int depth)
|
||||
{
|
||||
parser_.max_nesting_depth(depth);
|
||||
}
|
||||
#endif
|
||||
void read_next()
|
||||
{
|
||||
std::error_code ec;
|
||||
read_next(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read_next(std::error_code& ec)
|
||||
{
|
||||
if (source_.is_error())
|
||||
{
|
||||
ec = json_errc::source_error;
|
||||
return;
|
||||
}
|
||||
parser_.reset();
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
}
|
||||
}
|
||||
bool eof = parser_.source_exhausted();
|
||||
parser_.parse_some(visitor_, ec);
|
||||
if (ec) return;
|
||||
if (eof)
|
||||
{
|
||||
if (parser_.enter())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (!parser_.accept())
|
||||
{
|
||||
ec = json_errc::unexpected_eof;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!source_.eof())
|
||||
{
|
||||
parser_.skip_whitespace();
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void check_done()
|
||||
{
|
||||
std::error_code ec;
|
||||
check_done(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t line() const
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
|
||||
void check_done(std::error_code& ec)
|
||||
{
|
||||
if (source_.is_error())
|
||||
{
|
||||
ec = json_errc::source_error;
|
||||
return;
|
||||
}
|
||||
if (source_.eof())
|
||||
{
|
||||
parser_.check_done(ec);
|
||||
if (ec) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
}
|
||||
}
|
||||
if (!parser_.source_exhausted())
|
||||
{
|
||||
parser_.check_done(ec);
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
while (!eof());
|
||||
}
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return parser_.source_exhausted() && source_.eof();
|
||||
}
|
||||
|
||||
void read()
|
||||
{
|
||||
read_next();
|
||||
check_done();
|
||||
}
|
||||
|
||||
void read(std::error_code& ec)
|
||||
{
|
||||
read_next(ec);
|
||||
if (!ec)
|
||||
{
|
||||
check_done(ec);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
using json_reader = legacy_basic_json_reader<char>;
|
||||
using wjson_reader = legacy_basic_json_reader<wchar_t>;
|
||||
#endif
|
||||
using json_string_reader = basic_json_reader<char,string_source<char>>;
|
||||
using wjson_string_reader = basic_json_reader<wchar_t,string_source<wchar_t>>;
|
||||
using json_stream_reader = basic_json_reader<char,stream_source<char>>;
|
||||
using wjson_stream_reader = basic_json_reader<wchar_t,stream_source<wchar_t>>;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
1072
scripts/exe/jsoncons/include/jsoncons/json_traits_macros.hpp
Normal file
1072
scripts/exe/jsoncons/include/jsoncons/json_traits_macros.hpp
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,144 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_TRAITS_MACROS_DEPRECATED_HPP
|
||||
#define JSONCONS_JSON_TRAITS_MACROS_DEPRECATED_HPP
|
||||
|
||||
#include <jsoncons/json_traits_macros.hpp>
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
|
||||
#define JSONCONS_MEMBER_TRAITS_DECL(ValueType, ...) \
|
||||
JSONCONS_MEMBER_TRAITS_BASE(JSONCONS_AS,JSONCONS_TO_JSON,0, ValueType, JSONCONS_NARGS(__VA_ARGS__), 0, __VA_ARGS__) \
|
||||
/**/
|
||||
|
||||
#define JSONCONS_TPL_MEMBER_TRAITS_DECL(NumTemplateParams, ValueType, ...) \
|
||||
JSONCONS_MEMBER_TRAITS_BASE(JSONCONS_AS,JSONCONS_TO_JSON,NumTemplateParams, ValueType, JSONCONS_NARGS(__VA_ARGS__), 0, __VA_ARGS__) \
|
||||
/**/
|
||||
|
||||
#define JSONCONS_MEMBER_NAMED_TRAITS_DECL(ValueType, ...) \
|
||||
JSONCONS_MEMBER_NAME_TRAITS_BASE(JSONCONS_NAME_AS, JSONCONS_NAME_TO_JSON, 0, ValueType, JSONCONS_NARGS(__VA_ARGS__), 0, __VA_ARGS__) \
|
||||
/**/
|
||||
|
||||
#define JSONCONS_TPL_MEMBER_NAMED_TRAITS_DECL(NumTemplateParams, ValueType, ...) \
|
||||
JSONCONS_MEMBER_NAME_TRAITS_BASE(JSONCONS_NAME_AS, JSONCONS_NAME_TO_JSON, NumTemplateParams, ValueType, JSONCONS_NARGS(__VA_ARGS__), 0, __VA_ARGS__) \
|
||||
/**/
|
||||
|
||||
#define JSONCONS_GETTER_SETTER_TRAITS_DECL(ValueType,GetPrefix,SetPrefix, ...) \
|
||||
JSONCONS_GETTER_SETTER_TRAITS_BASE(JSONCONS_GETTER_SETTER_AS, JSONCONS_GETTER_SETTER_TO_JSON,0, ValueType,GetPrefix,SetPrefix, JSONCONS_NARGS(__VA_ARGS__), 0, __VA_ARGS__) \
|
||||
/**/
|
||||
|
||||
#define JSONCONS_TPL_GETTER_SETTER_TRAITS_DECL(NumTemplateParams, ValueType,GetPrefix,SetPrefix, ...) \
|
||||
JSONCONS_GETTER_SETTER_TRAITS_BASE(JSONCONS_GETTER_SETTER_AS, JSONCONS_GETTER_SETTER_TO_JSON,NumTemplateParams, ValueType,GetPrefix,SetPrefix, JSONCONS_NARGS(__VA_ARGS__), 0, __VA_ARGS__) \
|
||||
/**/
|
||||
|
||||
#define JSONCONS_GETTER_SETTER_NAMED_TRAITS_DECL(ValueType, ...) \
|
||||
JSONCONS_GETTER_SETTER_NAME_TRAITS_BASE(JSONCONS_GETTER_SETTER_NAME_AS,JSONCONS_GETTER_SETTER_NAME_TO_JSON, 0, ValueType, JSONCONS_NARGS(__VA_ARGS__), 0, __VA_ARGS__) \
|
||||
/**/
|
||||
|
||||
#define JSONCONS_TPL_GETTER_SETTER_NAMED_TRAITS_DECL(NumTemplateParams, ValueType, ...) \
|
||||
JSONCONS_GETTER_SETTER_NAME_TRAITS_BASE(JSONCONS_GETTER_SETTER_NAME_AS,JSONCONS_GETTER_SETTER_NAME_TO_JSON, NumTemplateParams, ValueType, JSONCONS_NARGS(__VA_ARGS__), 0, __VA_ARGS__) \
|
||||
/**/
|
||||
|
||||
#define JSONCONS_ALL_GETTER_CTOR_TRAITS JSONCONS_ALL_CTOR_GETTER_TRAITS
|
||||
#define JSONCONS_N_GETTER_CTOR_TRAITS JSONCONS_N_CTOR_GETTER_TRAITS
|
||||
#define JSONCONS_TPL_ALL_GETTER_CTOR_TRAITS JSONCONS_TPL_ALL_CTOR_GETTER_TRAITS
|
||||
#define JSONCONS_TPL_N_GETTER_CTOR_TRAITS JSONCONS_TPL_N_CTOR_GETTER_TRAITS
|
||||
|
||||
#define JSONCONS_ALL_GETTER_CTOR_NAME_TRAITS JSONCONS_ALL_CTOR_GETTER_NAME_TRAITS
|
||||
#define JSONCONS_N_GETTER_CTOR_NAME_TRAITS JSONCONS_N_CTOR_GETTER_NAME_TRAITS
|
||||
#define JSONCONS_TPL_ALL_GETTER_CTOR_NAME_TRAITS JSONCONS_TPL_ALL_CTOR_GETTER_NAME_TRAITS
|
||||
#define JSONCONS_TPL_N_GETTER_CTOR_NAME_TRAITS JSONCONS_TPL_N_CTOR_GETTER_NAME_TRAITS
|
||||
|
||||
#define JSONCONS_PROPERTY_TRAITS_DECL JSONCONS_GETTER_SETTER_TRAITS_DECL
|
||||
#define JSONCONS_TPL_PROPERTY_TRAITS_DECL JSONCONS_TPL_GETTER_SETTER_TRAITS_DECL
|
||||
#define JSONCONS_TYPE_TRAITS_DECL JSONCONS_MEMBER_TRAITS_DECL
|
||||
#define JSONCONS_MEMBER_TRAITS_NAMED_DECL JSONCONS_MEMBER_NAMED_TRAITS_DECL
|
||||
#define JSONCONS_TEMPLATE_MEMBER_TRAITS_NAMED_DECL JSONCONS_TPL_MEMBER_NAMED_TRAITS_DECL
|
||||
#define JSONCONS_TEMPLATE_GETTER_SETTER_TRAITS_NAMED_DECL JSONCONS_TPL_GETTER_SETTER_NAMED_TRAITS_DECL
|
||||
#define JSONCONS_TEMPLATE_MEMBER_TRAITS_DECL JSONCONS_TPL_MEMBER_TRAITS_DECL
|
||||
|
||||
#define JSONCONS_N_MEMBER_NAMED_TRAITS JSONCONS_N_MEMBER_NAME_TRAITS
|
||||
#define JSONCONS_TPL_N_MEMBER_NAMED_TRAITS JSONCONS_TPL_N_MEMBER_NAME_TRAITS
|
||||
#define JSONCONS_ALL_MEMBER_NAMED_TRAITS JSONCONS_ALL_MEMBER_NAME_TRAITS
|
||||
#define JSONCONS_TPL_ALL_MEMBER_NAMED_TRAITS JSONCONS_TPL_ALL_MEMBER_NAME_TRAITS
|
||||
|
||||
#define JSONCONS_ALL_GETTER_CTOR_NAMED_TRAITS JSONCONS_ALL_GETTER_CTOR_NAME_TRAITS
|
||||
#define JSONCONS_TPL_ALL_GETTER_CTOR_NAMED_TRAITS JSONCONS_TPL_ALL_GETTER_CTOR_NAME_TRAITS
|
||||
#define JSONCONS_N_GETTER_CTOR_NAMED_TRAITS JSONCONS_N_GETTER_CTOR_NAME_TRAITS
|
||||
#define JSONCONS_TPL_N_GETTER_CTOR_NAMED_TRAITS JSONCONS_TPL_N_GETTER_CTOR_NAME_TRAITS
|
||||
|
||||
#define JSONCONS_ENUM_NAMED_TRAITS JSONCONS_ENUM_NAME_TRAITS
|
||||
|
||||
#define JSONCONS_N_GETTER_SETTER_NAMED_TRAITS JSONCONS_N_GETTER_SETTER_NAME_TRAITS
|
||||
#define JSONCONS_TPL_N_GETTER_SETTER_NAMED_TRAITS JSONCONS_TPL_N_GETTER_SETTER_NAME_TRAITS
|
||||
#define JSONCONS_ALL_GETTER_SETTER_NAMED_TRAITS JSONCONS_ALL_GETTER_SETTER_NAME_TRAITS
|
||||
#define JSONCONS_TPL_ALL_GETTER_SETTER_NAMED_TRAITS JSONCONS_TPL_ALL_GETTER_SETTER_NAME_TRAITS
|
||||
|
||||
#define JSONCONS_N_MEMBER_TRAITS_DECL JSONCONS_N_MEMBER_TRAITS
|
||||
#define JSONCONS_TPL_N_MEMBER_TRAITS_DECL JSONCONS_TPL_N_MEMBER_TRAITS
|
||||
#define JSONCONS_ALL_MEMBER_TRAITS_DECL JSONCONS_ALL_MEMBER_TRAITS
|
||||
#define JSONCONS_TPL_ALL_MEMBER_TRAITS_DECL JSONCONS_TPL_ALL_MEMBER_TRAITS
|
||||
#define JSONCONS_N_MEMBER_NAMED_TRAITS_DECL JSONCONS_N_MEMBER_NAMED_TRAITS
|
||||
#define JSONCONS_TPL_N_MEMBER_NAMED_TRAITS_DECL JSONCONS_TPL_N_MEMBER_NAMED_TRAITS
|
||||
#define JSONCONS_ALL_MEMBER_NAMED_TRAITS_DECL JSONCONS_ALL_MEMBER_NAMED_TRAITS
|
||||
#define JSONCONS_TPL_ALL_MEMBER_NAMED_TRAITS_DECL JSONCONS_TPL_ALL_MEMBER_NAMED_TRAITS
|
||||
#define JSONCONS_ALL_GETTER_CTOR_TRAITS_DECL JSONCONS_ALL_GETTER_CTOR_TRAITS
|
||||
#define JSONCONS_TPL_ALL_GETTER_CTOR_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_CTOR_TRAITS
|
||||
#define JSONCONS_N_GETTER_CTOR_TRAITS_DECL JSONCONS_N_GETTER_CTOR_TRAITS
|
||||
#define JSONCONS_N_ALL_GETTER_CTOR_TRAITS_DECL JSONCONS_N_ALL_GETTER_CTOR_TRAITS
|
||||
#define JSONCONS_ALL_GETTER_CTOR_NAMED_TRAITS_DECL JSONCONS_ALL_GETTER_CTOR_NAMED_TRAITS
|
||||
#define JSONCONS_TPL_ALL_GETTER_CTOR_NAMED_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_CTOR_NAMED_TRAITS
|
||||
#define JSONCONS_N_GETTER_CTOR_NAMED_TRAITS_DECL JSONCONS_N_GETTER_CTOR_NAMED_TRAITS
|
||||
#define JSONCONS_TPL_N_GETTER_CTOR_NAMED_TRAITS_DECL JSONCONS_TPL_N_GETTER_CTOR_NAMED_TRAITS
|
||||
#define JSONCONS_ENUM_TRAITS_DECL JSONCONS_ENUM_TRAITS
|
||||
#define JSONCONS_ENUM_NAMED_TRAITS_DECL JSONCONS_ENUM_NAMED_TRAITS
|
||||
#define JSONCONS_N_GETTER_SETTER_TRAITS_DECL JSONCONS_N_GETTER_SETTER_TRAITS
|
||||
#define JSONCONS_TPL_N_GETTER_SETTER_TRAITS_DECL JSONCONS_TPL_N_GETTER_SETTER_TRAITS
|
||||
#define JSONCONS_ALL_GETTER_SETTER_TRAITS_DECL JSONCONS_ALL_GETTER_SETTER_TRAITS
|
||||
#define JSONCONS_TPL_ALL_GETTER_SETTER_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_SETTER_TRAITS
|
||||
#define JSONCONS_N_GETTER_SETTER_NAMED_TRAITS_DECL JSONCONS_N_GETTER_SETTER_NAMED_TRAITS
|
||||
#define JSONCONS_TPL_N_GETTER_SETTER_NAMED_TRAITS_DECL JSONCONS_TPL_N_GETTER_SETTER_NAMED_TRAITS
|
||||
#define JSONCONS_ALL_GETTER_SETTER_NAMED_TRAITS_DECL JSONCONS_ALL_GETTER_SETTER_NAMED_TRAITS
|
||||
#define JSONCONS_TPL_ALL_GETTER_SETTER_NAMED_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_SETTER_NAMED_TRAITS
|
||||
#define JSONCONS_POLYMORPHIC_TRAITS_DECL JSONCONS_POLYMORPHIC_TRAITS
|
||||
#define JSONCONS_NONDEFAULT_MEMBER_TRAITS_DECL JSONCONS_ALL_MEMBER_TRAITS
|
||||
#define JSONCONS_TEMPLATE_STRICT_MEMBER_TRAITS_DECL JSONCONS_TPL_ALL_MEMBER_TRAITS
|
||||
|
||||
#define JSONCONS_STRICT_MEMBER_TRAITS_NAMED_DECL JSONCONS_ALL_MEMBER_NAME_TRAITS
|
||||
#define JSONCONS_STRICT_TEMPLATE_MEMBER_TRAITS_DECL JSONCONS_TPL_ALL_MEMBER_TRAITS
|
||||
#define JSONCONS_STRICT_TEMPLATE_MEMBER_TRAITS_NAMED_DECL JSONCONS_TPL_ALL_MEMBER_NAME_TRAITS
|
||||
#define JSONCONS_ENUM_TRAITS_NAMED_DECL JSONCONS_ENUM_NAME_TRAITS
|
||||
#define JSONCONS_GETTER_CTOR_TRAITS_NAMED_DECL JSONCONS_ALL_GETTER_CTOR_NAME_TRAITS
|
||||
#define JSONCONS_TEMPLATE_GETTER_CTOR_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_CTOR_TRAITS
|
||||
#define JSONCONS_TEMPLATE_GETTER_CTOR_TRAITS_NAMED_DECL JSONCONS_TPL_ALL_GETTER_CTOR_NAME_TRAITS
|
||||
#define JSONCONS_GETTER_SETTER_TRAITS_NAMED_DECL JSONCONS_ALL_GETTER_SETTER_NAME_TRAITS
|
||||
#define JSONCONS_STRICT_GETTER_SETTER_TRAITS_NAMED_DECL JSONCONS_ALL_GETTER_SETTER_NAME_TRAITS
|
||||
#define JSONCONS_STRICT_TEMPLATE_GETTER_SETTER_TRAITS_NAMED_DECL JSONCONS_TPL_ALL_GETTER_SETTER_NAME_TRAITS
|
||||
#define JSONCONS_STRICT_TPL_MEMBER_TRAITS_DECL JSONCONS_TPL_ALL_MEMBER_TRAITS
|
||||
#define JSONCONS_STRICT_TPL_MEMBER_NAMED_TRAITS_DECL JSONCONS_TPL_ALL_MEMBER_NAME_TRAITS
|
||||
#define JSONCONS_STRICT_TPL_GETTER_SETTER_NAMED_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_SETTER_NAME_TRAITS
|
||||
|
||||
#define JSONCONS_STRICT_MEMBER_TRAITS_DECL JSONCONS_ALL_MEMBER_TRAITS
|
||||
#define JSONCONS_TPL_STRICT_MEMBER_TRAITS_DECL JSONCONS_TPL_ALL_MEMBER_TRAITS
|
||||
#define JSONCONS_STRICT_MEMBER_NAMED_TRAITS_DECL JSONCONS_ALL_MEMBER_NAME_TRAITS
|
||||
#define JSONCONS_TPL_STRICT_MEMBER_NAMED_TRAITS_DECL JSONCONS_ALL_STRICT_MEMBER_NAME_TRAITS
|
||||
#define JSONCONS_STRICT_PROPERTY_TRAITS_DECL JSONCONS_ALL_GETTER_SETTER_TRAITS
|
||||
#define JSONCONS_TPL_STRICT_PROPERTY_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_SETTER_TRAITS
|
||||
#define JSONCONS_STRICT_GETTER_SETTER_NAMED_TRAITS_DECL JSONCONS_ALL_GETTER_SETTER_NAME_TRAITS
|
||||
#define JSONCONS_TPL_STRICT_GETTER_SETTER_NAMED_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_SETTER_NAME_TRAITS
|
||||
#define JSONCONS_GETTER_CTOR_TRAITS_DECL JSONCONS_ALL_GETTER_CTOR_TRAITS
|
||||
#define JSONCONS_TPL_GETTER_CTOR_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_CTOR_TRAITS
|
||||
#define JSONCONS_GETTER_CTOR_NAMED_TRAITS_DECL JSONCONS_ALL_GETTER_CTOR_NAME_TRAITS
|
||||
#define JSONCONS_TPL_GETTER_CTOR_NAMED_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_CTOR_NAME_TRAITS
|
||||
#define JSONCONS_N_PROPERTY_TRAITS_DECL JSONCONS_N_GETTER_SETTER_TRAITS
|
||||
#define JSONCONS_ALL_PROPERTY_TRAITS_DECL JSONCONS_ALL_GETTER_SETTER_TRAITS
|
||||
#define JSONCONS_TPL_N_PROPERTY_TRAITS_DECL JSONCONS_TPL_N_GETTER_SETTER_TRAITS
|
||||
#define JSONCONS_TPL_ALL_PROPERTY_TRAITS_DECL JSONCONS_TPL_ALL_GETTER_SETTER_TRAITS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
206
scripts/exe/jsoncons/include/jsoncons/json_type.hpp
Normal file
206
scripts/exe/jsoncons/include/jsoncons/json_type.hpp
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_JSON_TYPE_HPP
|
||||
#define JSONCONS_JSON_TYPE_HPP
|
||||
|
||||
#include <ostream>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
enum class json_type : uint8_t
|
||||
{
|
||||
null_value,
|
||||
bool_value,
|
||||
int64_value,
|
||||
uint64_value,
|
||||
half_value,
|
||||
double_value,
|
||||
string_value,
|
||||
byte_string_value,
|
||||
array_value,
|
||||
object_value
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, json_type type)
|
||||
{
|
||||
static constexpr const CharT* null_value = JSONCONS_CSTRING_CONSTANT(CharT, "null");
|
||||
static constexpr const CharT* bool_value = JSONCONS_CSTRING_CONSTANT(CharT, "bool");
|
||||
static constexpr const CharT* int64_value = JSONCONS_CSTRING_CONSTANT(CharT, "int64");
|
||||
static constexpr const CharT* uint64_value = JSONCONS_CSTRING_CONSTANT(CharT, "uint64");
|
||||
static constexpr const CharT* half_value = JSONCONS_CSTRING_CONSTANT(CharT, "half");
|
||||
static constexpr const CharT* double_value = JSONCONS_CSTRING_CONSTANT(CharT, "double");
|
||||
static constexpr const CharT* string_value = JSONCONS_CSTRING_CONSTANT(CharT, "string");
|
||||
static constexpr const CharT* byte_string_value = JSONCONS_CSTRING_CONSTANT(CharT, "byte_string");
|
||||
static constexpr const CharT* array_value = JSONCONS_CSTRING_CONSTANT(CharT, "array");
|
||||
static constexpr const CharT* object_value = JSONCONS_CSTRING_CONSTANT(CharT, "object");
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case json_type::null_value:
|
||||
{
|
||||
os << null_value;
|
||||
break;
|
||||
}
|
||||
case json_type::bool_value:
|
||||
{
|
||||
os << bool_value;
|
||||
break;
|
||||
}
|
||||
case json_type::int64_value:
|
||||
{
|
||||
os << int64_value;
|
||||
break;
|
||||
}
|
||||
case json_type::uint64_value:
|
||||
{
|
||||
os << uint64_value;
|
||||
break;
|
||||
}
|
||||
case json_type::half_value:
|
||||
{
|
||||
os << half_value;
|
||||
break;
|
||||
}
|
||||
case json_type::double_value:
|
||||
{
|
||||
os << double_value;
|
||||
break;
|
||||
}
|
||||
case json_type::string_value:
|
||||
{
|
||||
os << string_value;
|
||||
break;
|
||||
}
|
||||
case json_type::byte_string_value:
|
||||
{
|
||||
os << byte_string_value;
|
||||
break;
|
||||
}
|
||||
case json_type::array_value:
|
||||
{
|
||||
os << array_value;
|
||||
break;
|
||||
}
|
||||
case json_type::object_value:
|
||||
{
|
||||
os << object_value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
enum class json_storage_kind : uint8_t
|
||||
{
|
||||
null_value = 0x00,
|
||||
bool_value = 0x01,
|
||||
int64_value = 0x02,
|
||||
uint64_value = 0x03,
|
||||
half_value = 0x04,
|
||||
double_value = 0x05,
|
||||
short_string_value = 0x06,
|
||||
long_string_value = 0x07,
|
||||
byte_string_value = 0x08,
|
||||
array_value = 0x09,
|
||||
empty_object_value = 0x0a,
|
||||
object_value = 0x0b,
|
||||
json_const_pointer = 0x0c
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, json_storage_kind storage)
|
||||
{
|
||||
static constexpr const CharT* null_value = JSONCONS_CSTRING_CONSTANT(CharT, "null");
|
||||
static constexpr const CharT* bool_value = JSONCONS_CSTRING_CONSTANT(CharT, "bool");
|
||||
static constexpr const CharT* int64_value = JSONCONS_CSTRING_CONSTANT(CharT, "int64");
|
||||
static constexpr const CharT* uint64_value = JSONCONS_CSTRING_CONSTANT(CharT, "uint64");
|
||||
static constexpr const CharT* half_value = JSONCONS_CSTRING_CONSTANT(CharT, "half");
|
||||
static constexpr const CharT* double_value = JSONCONS_CSTRING_CONSTANT(CharT, "double");
|
||||
static constexpr const CharT* short_string_value = JSONCONS_CSTRING_CONSTANT(CharT, "short_string");
|
||||
static constexpr const CharT* long_string_value = JSONCONS_CSTRING_CONSTANT(CharT, "string");
|
||||
static constexpr const CharT* byte_string_value = JSONCONS_CSTRING_CONSTANT(CharT, "byte_string");
|
||||
static constexpr const CharT* array_value = JSONCONS_CSTRING_CONSTANT(CharT, "array");
|
||||
static constexpr const CharT* empty_object_value = JSONCONS_CSTRING_CONSTANT(CharT, "empty_object");
|
||||
static constexpr const CharT* object_value = JSONCONS_CSTRING_CONSTANT(CharT, "object");
|
||||
static constexpr const CharT* json_const_pointer = JSONCONS_CSTRING_CONSTANT(CharT, "json_const_pointer");
|
||||
|
||||
switch (storage)
|
||||
{
|
||||
case json_storage_kind::null_value:
|
||||
{
|
||||
os << null_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::bool_value:
|
||||
{
|
||||
os << bool_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::int64_value:
|
||||
{
|
||||
os << int64_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::uint64_value:
|
||||
{
|
||||
os << uint64_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::half_value:
|
||||
{
|
||||
os << half_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::double_value:
|
||||
{
|
||||
os << double_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::short_string_value:
|
||||
{
|
||||
os << short_string_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::long_string_value:
|
||||
{
|
||||
os << long_string_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::byte_string_value:
|
||||
{
|
||||
os << byte_string_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::array_value:
|
||||
{
|
||||
os << array_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::empty_object_value:
|
||||
{
|
||||
os << empty_object_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::object_value:
|
||||
{
|
||||
os << object_value;
|
||||
break;
|
||||
}
|
||||
case json_storage_kind::json_const_pointer:
|
||||
{
|
||||
os << json_const_pointer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
} // jsoncons
|
||||
|
||||
#endif
|
||||
1908
scripts/exe/jsoncons/include/jsoncons/json_type_traits.hpp
Normal file
1908
scripts/exe/jsoncons/include/jsoncons/json_type_traits.hpp
Normal file
File diff suppressed because it is too large
Load diff
1560
scripts/exe/jsoncons/include/jsoncons/json_visitor.hpp
Normal file
1560
scripts/exe/jsoncons/include/jsoncons/json_visitor.hpp
Normal file
File diff suppressed because it is too large
Load diff
89
scripts/exe/jsoncons/include/jsoncons/pretty_print.hpp
Normal file
89
scripts/exe/jsoncons/include/jsoncons/pretty_print.hpp
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_PRETTY_PRINT_HPP
|
||||
#define JSONCONS_PRETTY_PRINT_HPP
|
||||
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <cstring>
|
||||
#include <ostream>
|
||||
#include <memory>
|
||||
#include <typeinfo>
|
||||
#include <cstring>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/json_options.hpp>
|
||||
#include <jsoncons/json_encoder.hpp>
|
||||
#include <jsoncons/json_type_traits.hpp>
|
||||
#include <jsoncons/json_error.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
template<class Json>
|
||||
class json_printable
|
||||
{
|
||||
public:
|
||||
using char_type = typename Json::char_type;
|
||||
|
||||
json_printable(const Json& j, indenting line_indent)
|
||||
: j_(&j), indenting_(line_indent)
|
||||
{
|
||||
}
|
||||
|
||||
json_printable(const Json& j,
|
||||
const basic_json_encode_options<char_type>& options,
|
||||
indenting line_indent)
|
||||
: j_(&j), options_(options), indenting_(line_indent)
|
||||
{
|
||||
}
|
||||
|
||||
void dump(std::basic_ostream<char_type>& os) const
|
||||
{
|
||||
j_->dump(os, options_, indenting_);
|
||||
}
|
||||
|
||||
friend std::basic_ostream<char_type>& operator<<(std::basic_ostream<char_type>& os, const json_printable<Json>& pr)
|
||||
{
|
||||
pr.dump(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
const Json *j_;
|
||||
basic_json_encode_options<char_type> options_;
|
||||
indenting indenting_;
|
||||
private:
|
||||
json_printable();
|
||||
};
|
||||
|
||||
template<class Json>
|
||||
json_printable<Json> print(const Json& j)
|
||||
{
|
||||
return json_printable<Json>(j, indenting::no_indent);
|
||||
}
|
||||
|
||||
template<class Json>
|
||||
json_printable<Json> print(const Json& j,
|
||||
const basic_json_encode_options<typename Json::char_type>& options)
|
||||
{
|
||||
return json_printable<Json>(j, options, indenting::no_indent);
|
||||
}
|
||||
|
||||
template<class Json>
|
||||
json_printable<Json> pretty_print(const Json& j)
|
||||
{
|
||||
return json_printable<Json>(j, indenting::indent);
|
||||
}
|
||||
|
||||
template<class Json>
|
||||
json_printable<Json> pretty_print(const Json& j,
|
||||
const basic_json_encode_options<typename Json::char_type>& options)
|
||||
{
|
||||
return json_printable<Json>(j, options, indenting::indent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
62
scripts/exe/jsoncons/include/jsoncons/ser_context.hpp
Normal file
62
scripts/exe/jsoncons/include/jsoncons/ser_context.hpp
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_SER_CONTEXT_HPP
|
||||
#define JSONCONS_SER_CONTEXT_HPP
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
class ser_context
|
||||
{
|
||||
public:
|
||||
virtual ~ser_context() noexcept = default;
|
||||
|
||||
virtual size_t line() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t column() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t position() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual size_t end_position() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use line()")
|
||||
std::size_t line_number() const
|
||||
{
|
||||
return line();
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use column()")
|
||||
std::size_t column_number() const
|
||||
{
|
||||
return column();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_context") typedef ser_context null_ser_context;
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_context") typedef ser_context parsing_context;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_context") typedef ser_context serializing_context;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_context") typedef ser_context null_parsing_context;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_context") typedef ser_context null_serializing_context;
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
289
scripts/exe/jsoncons/include/jsoncons/sink.hpp
Normal file
289
scripts/exe/jsoncons/include/jsoncons/sink.hpp
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_SINK_HPP
|
||||
#define JSONCONS_SINK_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <cmath>
|
||||
#include <exception>
|
||||
#include <memory> // std::addressof
|
||||
#include <cstring> // std::memcpy
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/extension_traits.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// stream_sink
|
||||
|
||||
template <class CharT>
|
||||
class stream_sink
|
||||
{
|
||||
public:
|
||||
using value_type = CharT;
|
||||
using container_type = std::basic_ostream<CharT>;
|
||||
|
||||
private:
|
||||
static constexpr size_t default_buffer_length = 16384;
|
||||
|
||||
std::basic_ostream<CharT>* stream_ptr_;
|
||||
std::vector<CharT> buffer_;
|
||||
CharT * begin_buffer_;
|
||||
const CharT* end_buffer_;
|
||||
CharT* p_;
|
||||
|
||||
// Noncopyable
|
||||
stream_sink(const stream_sink&) = delete;
|
||||
stream_sink& operator=(const stream_sink&) = delete;
|
||||
|
||||
public:
|
||||
stream_sink(stream_sink&&) = default;
|
||||
|
||||
stream_sink(std::basic_ostream<CharT>& os)
|
||||
: stream_ptr_(std::addressof(os)), buffer_(default_buffer_length), begin_buffer_(buffer_.data()), end_buffer_(begin_buffer_+buffer_.size()), p_(begin_buffer_)
|
||||
{
|
||||
}
|
||||
stream_sink(std::basic_ostream<CharT>& os, std::size_t buflen)
|
||||
: stream_ptr_(std::addressof(os)), buffer_(buflen), begin_buffer_(buffer_.data()), end_buffer_(begin_buffer_+buffer_.size()), p_(begin_buffer_)
|
||||
{
|
||||
}
|
||||
~stream_sink() noexcept
|
||||
{
|
||||
stream_ptr_->write(begin_buffer_, buffer_length());
|
||||
stream_ptr_->flush();
|
||||
}
|
||||
|
||||
// Movable
|
||||
stream_sink& operator=(stream_sink&&) = default;
|
||||
|
||||
void flush()
|
||||
{
|
||||
stream_ptr_->write(begin_buffer_, buffer_length());
|
||||
stream_ptr_->flush();
|
||||
p_ = buffer_.data();
|
||||
}
|
||||
|
||||
void append(const CharT* s, std::size_t length)
|
||||
{
|
||||
std::size_t diff = end_buffer_ - p_;
|
||||
if (diff >= length)
|
||||
{
|
||||
std::memcpy(p_, s, length*sizeof(CharT));
|
||||
p_ += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_ptr_->write(begin_buffer_, buffer_length());
|
||||
stream_ptr_->write(s,length);
|
||||
p_ = begin_buffer_;
|
||||
}
|
||||
}
|
||||
|
||||
void push_back(CharT ch)
|
||||
{
|
||||
if (p_ < end_buffer_)
|
||||
{
|
||||
*p_++ = ch;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_ptr_->write(begin_buffer_, buffer_length());
|
||||
p_ = begin_buffer_;
|
||||
push_back(ch);
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
std::size_t buffer_length() const
|
||||
{
|
||||
return p_ - begin_buffer_;
|
||||
}
|
||||
};
|
||||
|
||||
// binary_stream_sink
|
||||
|
||||
class binary_stream_sink
|
||||
{
|
||||
public:
|
||||
typedef uint8_t value_type;
|
||||
using container_type = std::basic_ostream<char>;
|
||||
private:
|
||||
static constexpr size_t default_buffer_length = 16384;
|
||||
|
||||
std::basic_ostream<char>* stream_ptr_;
|
||||
std::vector<uint8_t> buffer_;
|
||||
uint8_t * begin_buffer_;
|
||||
const uint8_t* end_buffer_;
|
||||
uint8_t* p_;
|
||||
|
||||
// Noncopyable
|
||||
binary_stream_sink(const binary_stream_sink&) = delete;
|
||||
binary_stream_sink& operator=(const binary_stream_sink&) = delete;
|
||||
|
||||
public:
|
||||
binary_stream_sink(binary_stream_sink&&) = default;
|
||||
|
||||
binary_stream_sink(std::basic_ostream<char>& os)
|
||||
: stream_ptr_(std::addressof(os)),
|
||||
buffer_(default_buffer_length),
|
||||
begin_buffer_(buffer_.data()),
|
||||
end_buffer_(begin_buffer_+buffer_.size()),
|
||||
p_(begin_buffer_)
|
||||
{
|
||||
}
|
||||
binary_stream_sink(std::basic_ostream<char>& os, std::size_t buflen)
|
||||
: stream_ptr_(std::addressof(os)),
|
||||
buffer_(buflen),
|
||||
begin_buffer_(buffer_.data()),
|
||||
end_buffer_(begin_buffer_+buffer_.size()),
|
||||
p_(begin_buffer_)
|
||||
{
|
||||
}
|
||||
~binary_stream_sink() noexcept
|
||||
{
|
||||
stream_ptr_->write((char*)begin_buffer_, buffer_length());
|
||||
stream_ptr_->flush();
|
||||
}
|
||||
|
||||
binary_stream_sink& operator=(binary_stream_sink&&) = default;
|
||||
|
||||
void flush()
|
||||
{
|
||||
stream_ptr_->write((char*)begin_buffer_, buffer_length());
|
||||
p_ = buffer_.data();
|
||||
}
|
||||
|
||||
void append(const uint8_t* s, std::size_t length)
|
||||
{
|
||||
std::size_t diff = end_buffer_ - p_;
|
||||
if (diff >= length)
|
||||
{
|
||||
std::memcpy(p_, s, length*sizeof(uint8_t));
|
||||
p_ += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_ptr_->write((char*)begin_buffer_, buffer_length());
|
||||
stream_ptr_->write((const char*)s,length);
|
||||
p_ = begin_buffer_;
|
||||
}
|
||||
}
|
||||
|
||||
void push_back(uint8_t ch)
|
||||
{
|
||||
if (p_ < end_buffer_)
|
||||
{
|
||||
*p_++ = ch;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_ptr_->write((char*)begin_buffer_, buffer_length());
|
||||
p_ = begin_buffer_;
|
||||
push_back(ch);
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
std::size_t buffer_length() const
|
||||
{
|
||||
return p_ - begin_buffer_;
|
||||
}
|
||||
};
|
||||
|
||||
// string_sink
|
||||
|
||||
template <class StringT>
|
||||
class string_sink
|
||||
{
|
||||
public:
|
||||
using value_type = typename StringT::value_type;
|
||||
using container_type = StringT;
|
||||
private:
|
||||
container_type* buf_ptr;
|
||||
|
||||
// Noncopyable
|
||||
string_sink(const string_sink&) = delete;
|
||||
string_sink& operator=(const string_sink&) = delete;
|
||||
public:
|
||||
string_sink(string_sink&& val) noexcept
|
||||
: buf_ptr(nullptr)
|
||||
{
|
||||
std::swap(buf_ptr,val.buf_ptr);
|
||||
}
|
||||
|
||||
string_sink(container_type& buf)
|
||||
: buf_ptr(std::addressof(buf))
|
||||
{
|
||||
}
|
||||
|
||||
string_sink& operator=(string_sink&& val) noexcept
|
||||
{
|
||||
// TODO: Shouldn't val.buf_ptr be nullified?
|
||||
// Also see move constructor above.
|
||||
std::swap(buf_ptr,val.buf_ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
}
|
||||
|
||||
void append(const value_type* s, std::size_t length)
|
||||
{
|
||||
buf_ptr->insert(buf_ptr->end(), s, s+length);
|
||||
}
|
||||
|
||||
void push_back(value_type ch)
|
||||
{
|
||||
buf_ptr->push_back(ch);
|
||||
}
|
||||
};
|
||||
|
||||
// bytes_sink
|
||||
|
||||
template <class Container, class = void>
|
||||
class bytes_sink
|
||||
{
|
||||
};
|
||||
|
||||
template <class Container>
|
||||
class bytes_sink<Container,typename std::enable_if<extension_traits::is_back_insertable_byte_container<Container>::value>::type>
|
||||
{
|
||||
public:
|
||||
using container_type = Container;
|
||||
using value_type = typename Container::value_type;
|
||||
private:
|
||||
container_type* buf_ptr;
|
||||
|
||||
// Noncopyable
|
||||
bytes_sink(const bytes_sink&) = delete;
|
||||
bytes_sink& operator=(const bytes_sink&) = delete;
|
||||
public:
|
||||
bytes_sink(bytes_sink&&) = default;
|
||||
|
||||
bytes_sink(container_type& buf)
|
||||
: buf_ptr(std::addressof(buf))
|
||||
{
|
||||
}
|
||||
|
||||
bytes_sink& operator=(bytes_sink&&) = default;
|
||||
|
||||
void flush()
|
||||
{
|
||||
}
|
||||
|
||||
void push_back(uint8_t ch)
|
||||
{
|
||||
buf_ptr->push_back(static_cast<value_type>(ch));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
793
scripts/exe/jsoncons/include/jsoncons/source.hpp
Normal file
793
scripts/exe/jsoncons/include/jsoncons/source.hpp
Normal file
|
|
@ -0,0 +1,793 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_SOURCE_HPP
|
||||
#define JSONCONS_SOURCE_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <istream>
|
||||
#include <memory> // std::addressof
|
||||
#include <cstring> // std::memcpy
|
||||
#include <exception>
|
||||
#include <iterator>
|
||||
#include <type_traits> // std::enable_if
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/byte_string.hpp> // jsoncons::byte_traits
|
||||
#include <jsoncons/extension_traits.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
template <class CharT>
|
||||
class basic_null_istream : public std::basic_istream<CharT>
|
||||
{
|
||||
class null_buffer : public std::basic_streambuf<CharT>
|
||||
{
|
||||
null_buffer(const null_buffer&) = delete;
|
||||
null_buffer& operator=(const null_buffer&) = delete;
|
||||
public:
|
||||
using typename std::basic_streambuf<CharT>::int_type;
|
||||
using typename std::basic_streambuf<CharT>::traits_type;
|
||||
|
||||
null_buffer() = default;
|
||||
null_buffer(null_buffer&&) = default;
|
||||
null_buffer& operator=(null_buffer&&) = default;
|
||||
|
||||
int_type overflow( int_type ch = typename std::basic_streambuf<CharT>::traits_type::eof() ) override
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
} nb_;
|
||||
public:
|
||||
basic_null_istream()
|
||||
: std::basic_istream<CharT>(&nb_)
|
||||
{
|
||||
}
|
||||
|
||||
basic_null_istream(const null_buffer&) = delete;
|
||||
basic_null_istream& operator=(const null_buffer&) = delete;
|
||||
basic_null_istream(basic_null_istream&&) noexcept
|
||||
: std::basic_istream<CharT>(&nb_)
|
||||
{
|
||||
}
|
||||
basic_null_istream& operator=(basic_null_istream&&) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
struct char_result
|
||||
{
|
||||
CharT value;
|
||||
bool eof;
|
||||
};
|
||||
|
||||
// text sources
|
||||
|
||||
template <class CharT>
|
||||
class stream_source
|
||||
{
|
||||
static constexpr std::size_t default_max_buffer_size = 16384;
|
||||
public:
|
||||
using value_type = CharT;
|
||||
private:
|
||||
using char_type = typename std::conditional<sizeof(CharT) == sizeof(char),char,CharT>::type;
|
||||
basic_null_istream<char_type> null_is_;
|
||||
std::basic_istream<char_type>* stream_ptr_;
|
||||
std::basic_streambuf<char_type>* sbuf_;
|
||||
std::size_t position_;
|
||||
std::vector<value_type> buffer_;
|
||||
const value_type* buffer_data_;
|
||||
std::size_t buffer_length_;
|
||||
|
||||
// Noncopyable
|
||||
stream_source(const stream_source&) = delete;
|
||||
stream_source& operator=(const stream_source&) = delete;
|
||||
public:
|
||||
stream_source()
|
||||
: stream_ptr_(&null_is_), sbuf_(null_is_.rdbuf()), position_(0),
|
||||
buffer_(1), buffer_data_(buffer_.data()), buffer_length_(0)
|
||||
{
|
||||
}
|
||||
|
||||
stream_source(std::basic_istream<char_type>& is, std::size_t buf_size = default_max_buffer_size)
|
||||
: stream_ptr_(std::addressof(is)), sbuf_(is.rdbuf()), position_(0),
|
||||
buffer_(buf_size), buffer_data_(buffer_.data()), buffer_length_(0)
|
||||
{
|
||||
}
|
||||
|
||||
stream_source(stream_source&& other) noexcept
|
||||
: stream_ptr_(&null_is_), sbuf_(null_is_.rdbuf()), position_(0),
|
||||
buffer_(), buffer_data_(buffer_.data()), buffer_length_(0)
|
||||
{
|
||||
if (other.stream_ptr_ != &other.null_is_)
|
||||
{
|
||||
stream_ptr_ = other.stream_ptr_;
|
||||
sbuf_ = other.sbuf_;
|
||||
position_ = other.position_;
|
||||
buffer_ = std::move(other.buffer_);
|
||||
buffer_data_ = buffer_.data() + (other.buffer_data_ - other.buffer_.data());
|
||||
buffer_length_ = other.buffer_length_;
|
||||
other = stream_source();
|
||||
}
|
||||
}
|
||||
|
||||
~stream_source()
|
||||
{
|
||||
}
|
||||
|
||||
stream_source& operator=(stream_source&& other) noexcept
|
||||
{
|
||||
if (other.stream_ptr_ != &other.null_is_)
|
||||
{
|
||||
stream_ptr_ = other.stream_ptr_;
|
||||
sbuf_ = other.sbuf_;
|
||||
position_ = other.position_;
|
||||
buffer_ = std::move(other.buffer_);
|
||||
buffer_data_ = buffer_.data() + (other.buffer_data_ - other.buffer_.data());
|
||||
buffer_length_ = other.buffer_length_;
|
||||
other = stream_source();
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_ptr_ = &null_is_;
|
||||
sbuf_ = null_is_.rdbuf();
|
||||
position_ = 0;
|
||||
buffer_data_ = buffer_.data();
|
||||
buffer_length_ = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return buffer_length_ == 0 && stream_ptr_->eof();
|
||||
}
|
||||
|
||||
bool is_error() const
|
||||
{
|
||||
return stream_ptr_->bad();
|
||||
}
|
||||
|
||||
std::size_t position() const
|
||||
{
|
||||
return position_;
|
||||
}
|
||||
|
||||
void ignore(std::size_t length)
|
||||
{
|
||||
std::size_t len = 0;
|
||||
if (buffer_length_ > 0)
|
||||
{
|
||||
len = (std::min)(buffer_length_, length);
|
||||
position_ += len;
|
||||
buffer_data_ += len;
|
||||
buffer_length_ -= len;
|
||||
}
|
||||
while (len < length)
|
||||
{
|
||||
fill_buffer();
|
||||
if (buffer_length_ == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
std::size_t len2 = (std::min)(buffer_length_, length-len);
|
||||
position_ += len2;
|
||||
buffer_data_ += len2;
|
||||
buffer_length_ -= len2;
|
||||
len += len2;
|
||||
}
|
||||
}
|
||||
|
||||
char_result<value_type> peek()
|
||||
{
|
||||
if (buffer_length_ == 0)
|
||||
{
|
||||
fill_buffer();
|
||||
}
|
||||
if (buffer_length_ > 0)
|
||||
{
|
||||
value_type c = *buffer_data_;
|
||||
return char_result<value_type>{c, false};
|
||||
}
|
||||
else
|
||||
{
|
||||
return char_result<value_type>{0, true};
|
||||
}
|
||||
}
|
||||
|
||||
span<const value_type> read_buffer()
|
||||
{
|
||||
if (buffer_length_ == 0)
|
||||
{
|
||||
fill_buffer();
|
||||
}
|
||||
const value_type* data = buffer_data_;
|
||||
std::size_t length = buffer_length_;
|
||||
buffer_data_ += buffer_length_;
|
||||
position_ += buffer_length_;
|
||||
buffer_length_ = 0;
|
||||
|
||||
return span<const value_type>(data, length);
|
||||
}
|
||||
|
||||
std::size_t read(value_type* p, std::size_t length)
|
||||
{
|
||||
std::size_t len = 0;
|
||||
if (buffer_length_ > 0)
|
||||
{
|
||||
len = (std::min)(buffer_length_, length);
|
||||
std::memcpy(p, buffer_data_, len*sizeof(value_type));
|
||||
buffer_data_ += len;
|
||||
buffer_length_ -= len;
|
||||
position_ += len;
|
||||
}
|
||||
if (length - len == 0)
|
||||
{
|
||||
return len;
|
||||
}
|
||||
else if (length - len < buffer_.size())
|
||||
{
|
||||
fill_buffer();
|
||||
if (buffer_length_ > 0)
|
||||
{
|
||||
std::size_t len2 = (std::min)(buffer_length_, length-len);
|
||||
std::memcpy(p+len, buffer_data_, len2*sizeof(value_type));
|
||||
buffer_data_ += len2;
|
||||
buffer_length_ -= len2;
|
||||
position_ += len2;
|
||||
len += len2;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stream_ptr_->eof())
|
||||
{
|
||||
buffer_length_ = 0;
|
||||
return 0;
|
||||
}
|
||||
JSONCONS_TRY
|
||||
{
|
||||
std::streamsize count = sbuf_->sgetn(reinterpret_cast<char_type*>(p+len), length-len);
|
||||
std::size_t len2 = static_cast<std::size_t>(count);
|
||||
if (len2 < length-len)
|
||||
{
|
||||
stream_ptr_->clear(stream_ptr_->rdstate() | std::ios::eofbit);
|
||||
}
|
||||
len += len2;
|
||||
position_ += len2;
|
||||
return len;
|
||||
}
|
||||
JSONCONS_CATCH(const std::exception&)
|
||||
{
|
||||
stream_ptr_->clear(stream_ptr_->rdstate() | std::ios::badbit | std::ios::eofbit);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
void fill_buffer()
|
||||
{
|
||||
if (stream_ptr_->eof())
|
||||
{
|
||||
buffer_length_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_data_ = buffer_.data();
|
||||
JSONCONS_TRY
|
||||
{
|
||||
std::streamsize count = sbuf_->sgetn(reinterpret_cast<char_type*>(buffer_.data()), buffer_.size());
|
||||
buffer_length_ = static_cast<std::size_t>(count);
|
||||
|
||||
if (buffer_length_ < buffer_.size())
|
||||
{
|
||||
stream_ptr_->clear(stream_ptr_->rdstate() | std::ios::eofbit);
|
||||
}
|
||||
}
|
||||
JSONCONS_CATCH(const std::exception&)
|
||||
{
|
||||
stream_ptr_->clear(stream_ptr_->rdstate() | std::ios::badbit | std::ios::eofbit);
|
||||
buffer_length_ = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// string_source
|
||||
|
||||
template <class CharT>
|
||||
class string_source
|
||||
{
|
||||
public:
|
||||
using value_type = CharT;
|
||||
using string_view_type = jsoncons::basic_string_view<value_type>;
|
||||
private:
|
||||
const value_type* data_;
|
||||
const value_type* current_;
|
||||
const value_type* end_;
|
||||
|
||||
// Noncopyable
|
||||
string_source(const string_source&) = delete;
|
||||
string_source& operator=(const string_source&) = delete;
|
||||
public:
|
||||
string_source()
|
||||
: data_(nullptr), current_(nullptr), end_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
string_source(const Sourceable& s,
|
||||
typename std::enable_if<extension_traits::is_sequence_of<Sourceable,value_type>::value>::type* = 0)
|
||||
: data_(s.data()), current_(s.data()), end_(s.data()+s.size())
|
||||
{
|
||||
}
|
||||
|
||||
string_source(const value_type* data)
|
||||
: data_(data), current_(data), end_(data+std::char_traits<value_type>::length(data))
|
||||
{
|
||||
}
|
||||
|
||||
string_source(string_source&& val) = default;
|
||||
|
||||
string_source& operator=(string_source&& val) = default;
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return current_ == end_;
|
||||
}
|
||||
|
||||
bool is_error() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t position() const
|
||||
{
|
||||
return (current_ - data_)/sizeof(value_type);
|
||||
}
|
||||
|
||||
void ignore(std::size_t count)
|
||||
{
|
||||
std::size_t len;
|
||||
if ((std::size_t)(end_ - current_) < count)
|
||||
{
|
||||
len = end_ - current_;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = count;
|
||||
}
|
||||
current_ += len;
|
||||
}
|
||||
|
||||
char_result<value_type> peek()
|
||||
{
|
||||
return current_ < end_ ? char_result<value_type>{*current_, false} : char_result<value_type>{0, true};
|
||||
}
|
||||
|
||||
span<const value_type> read_buffer()
|
||||
{
|
||||
const value_type* data = current_;
|
||||
std::size_t length = end_ - current_;
|
||||
current_ = end_;
|
||||
|
||||
return span<const value_type>(data, length);
|
||||
}
|
||||
|
||||
std::size_t read(value_type* p, std::size_t length)
|
||||
{
|
||||
std::size_t len;
|
||||
if ((std::size_t)(end_ - current_) < length)
|
||||
{
|
||||
len = end_ - current_;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = length;
|
||||
}
|
||||
std::memcpy(p, current_, len*sizeof(value_type));
|
||||
current_ += len;
|
||||
return len;
|
||||
}
|
||||
};
|
||||
|
||||
// iterator source
|
||||
|
||||
template <class IteratorT>
|
||||
class iterator_source
|
||||
{
|
||||
public:
|
||||
using value_type = typename std::iterator_traits<IteratorT>::value_type;
|
||||
private:
|
||||
static constexpr std::size_t default_max_buffer_size = 16384;
|
||||
|
||||
IteratorT current_;
|
||||
IteratorT end_;
|
||||
std::size_t position_;
|
||||
std::vector<value_type> buffer_;
|
||||
std::size_t buffer_length_;
|
||||
|
||||
using difference_type = typename std::iterator_traits<IteratorT>::difference_type;
|
||||
using iterator_category = typename std::iterator_traits<IteratorT>::iterator_category;
|
||||
|
||||
// Noncopyable
|
||||
iterator_source(const iterator_source&) = delete;
|
||||
iterator_source& operator=(const iterator_source&) = delete;
|
||||
public:
|
||||
|
||||
iterator_source(const IteratorT& first, const IteratorT& last, std::size_t buf_size = default_max_buffer_size)
|
||||
: current_(first), end_(last), position_(0), buffer_(buf_size), buffer_length_(0)
|
||||
{
|
||||
}
|
||||
|
||||
iterator_source(iterator_source&& other) = default;
|
||||
|
||||
iterator_source& operator=(iterator_source&& other) = default;
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return !(current_ != end_);
|
||||
}
|
||||
|
||||
bool is_error() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t position() const
|
||||
{
|
||||
return position_;
|
||||
}
|
||||
|
||||
void ignore(std::size_t count)
|
||||
{
|
||||
while (count-- > 0 && current_ != end_)
|
||||
{
|
||||
++position_;
|
||||
++current_;
|
||||
}
|
||||
}
|
||||
|
||||
char_result<value_type> peek()
|
||||
{
|
||||
return current_ != end_ ? char_result<value_type>{*current_, false} : char_result<value_type>{0, true};
|
||||
}
|
||||
|
||||
span<const value_type> read_buffer()
|
||||
{
|
||||
if (buffer_length_ == 0)
|
||||
{
|
||||
buffer_length_ = read(buffer_.data(), buffer_.size());
|
||||
}
|
||||
std::size_t length = buffer_length_;
|
||||
buffer_length_ = 0;
|
||||
|
||||
return span<const value_type>(buffer_.data(), length);
|
||||
}
|
||||
|
||||
template <class Category = iterator_category>
|
||||
typename std::enable_if<std::is_same<Category,std::random_access_iterator_tag>::value, std::size_t>::type
|
||||
read(value_type* data, std::size_t length)
|
||||
{
|
||||
std::size_t count = (std::min)(length, static_cast<std::size_t>(std::distance(current_, end_)));
|
||||
|
||||
//JSONCONS_COPY(current_, current_ + count, data);
|
||||
|
||||
auto end = current_ + count;
|
||||
value_type* p = data;
|
||||
while (current_ != end)
|
||||
{
|
||||
*p++ = *current_++;
|
||||
}
|
||||
|
||||
//current_ += count;
|
||||
position_ += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template <class Category = iterator_category>
|
||||
typename std::enable_if<!std::is_same<Category,std::random_access_iterator_tag>::value, std::size_t>::type
|
||||
read(value_type* data, std::size_t length)
|
||||
{
|
||||
value_type* p = data;
|
||||
value_type* pend = data + length;
|
||||
|
||||
while (p < pend && current_ != end_)
|
||||
{
|
||||
*p = static_cast<value_type>(*current_);
|
||||
++p;
|
||||
++current_;
|
||||
}
|
||||
|
||||
position_ += (p - data);
|
||||
|
||||
return p - data;
|
||||
}
|
||||
};
|
||||
|
||||
// binary sources
|
||||
|
||||
using binary_stream_source = stream_source<uint8_t>;
|
||||
|
||||
class bytes_source
|
||||
{
|
||||
public:
|
||||
typedef uint8_t value_type;
|
||||
private:
|
||||
const value_type* data_;
|
||||
const value_type* current_;
|
||||
const value_type* end_;
|
||||
|
||||
// Noncopyable
|
||||
bytes_source(const bytes_source&) = delete;
|
||||
bytes_source& operator=(const bytes_source&) = delete;
|
||||
public:
|
||||
bytes_source()
|
||||
: data_(nullptr), current_(nullptr), end_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
bytes_source(const Sourceable& source,
|
||||
typename std::enable_if<extension_traits::is_byte_sequence<Sourceable>::value,int>::type = 0)
|
||||
: data_(reinterpret_cast<const value_type*>(source.data())),
|
||||
current_(data_),
|
||||
end_(data_+source.size())
|
||||
{
|
||||
}
|
||||
|
||||
bytes_source(bytes_source&&) = default;
|
||||
|
||||
bytes_source& operator=(bytes_source&&) = default;
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return current_ == end_;
|
||||
}
|
||||
|
||||
bool is_error() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t position() const
|
||||
{
|
||||
return current_ - data_;
|
||||
}
|
||||
|
||||
void ignore(std::size_t count)
|
||||
{
|
||||
std::size_t len;
|
||||
if ((std::size_t)(end_ - current_) < count)
|
||||
{
|
||||
len = end_ - current_;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = count;
|
||||
}
|
||||
current_ += len;
|
||||
}
|
||||
|
||||
char_result<value_type> peek()
|
||||
{
|
||||
return current_ < end_ ? char_result<value_type>{*current_, false} : char_result<value_type>{0, true};
|
||||
}
|
||||
|
||||
span<const value_type> read_buffer()
|
||||
{
|
||||
const value_type* data = current_;
|
||||
std::size_t length = end_ - current_;
|
||||
current_ = end_;
|
||||
|
||||
return span<const value_type>(data, length);
|
||||
}
|
||||
|
||||
std::size_t read(value_type* p, std::size_t length)
|
||||
{
|
||||
std::size_t len;
|
||||
if ((std::size_t)(end_ - current_) < length)
|
||||
{
|
||||
len = end_ - current_;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = length;
|
||||
}
|
||||
std::memcpy(p, current_, len*sizeof(value_type));
|
||||
current_ += len;
|
||||
return len;
|
||||
}
|
||||
};
|
||||
|
||||
// binary_iterator source
|
||||
|
||||
template <class IteratorT>
|
||||
class binary_iterator_source
|
||||
{
|
||||
public:
|
||||
using value_type = uint8_t;
|
||||
private:
|
||||
static constexpr std::size_t default_max_buffer_size = 16384;
|
||||
|
||||
IteratorT current_;
|
||||
IteratorT end_;
|
||||
std::size_t position_;
|
||||
std::vector<value_type> buffer_;
|
||||
std::size_t buffer_length_;
|
||||
|
||||
using difference_type = typename std::iterator_traits<IteratorT>::difference_type;
|
||||
using iterator_category = typename std::iterator_traits<IteratorT>::iterator_category;
|
||||
|
||||
// Noncopyable
|
||||
binary_iterator_source(const binary_iterator_source&) = delete;
|
||||
binary_iterator_source& operator=(const binary_iterator_source&) = delete;
|
||||
public:
|
||||
binary_iterator_source(const IteratorT& first, const IteratorT& last, std::size_t buf_size = default_max_buffer_size)
|
||||
: current_(first), end_(last), position_(0), buffer_(buf_size), buffer_length_(0)
|
||||
{
|
||||
}
|
||||
|
||||
binary_iterator_source(binary_iterator_source&& other) = default;
|
||||
|
||||
binary_iterator_source& operator=(binary_iterator_source&& other) = default;
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return !(current_ != end_);
|
||||
}
|
||||
|
||||
bool is_error() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t position() const
|
||||
{
|
||||
return position_;
|
||||
}
|
||||
|
||||
void ignore(std::size_t count)
|
||||
{
|
||||
while (count-- > 0 && current_ != end_)
|
||||
{
|
||||
++position_;
|
||||
++current_;
|
||||
}
|
||||
}
|
||||
|
||||
char_result<value_type> peek()
|
||||
{
|
||||
return current_ != end_ ? char_result<value_type>{static_cast<value_type>(*current_), false} : char_result<value_type>{0, true};
|
||||
}
|
||||
|
||||
span<const value_type> read_buffer()
|
||||
{
|
||||
if (buffer_length_ == 0)
|
||||
{
|
||||
buffer_length_ = read(buffer_.data(), buffer_.size());
|
||||
}
|
||||
std::size_t length = buffer_length_;
|
||||
buffer_length_ = 0;
|
||||
|
||||
return span<const value_type>(buffer_.data(), length);
|
||||
}
|
||||
|
||||
template <class Category = iterator_category>
|
||||
typename std::enable_if<std::is_same<Category,std::random_access_iterator_tag>::value, std::size_t>::type
|
||||
read(value_type* data, std::size_t length)
|
||||
{
|
||||
std::size_t count = (std::min)(length, static_cast<std::size_t>(std::distance(current_, end_)));
|
||||
//JSONCONS_COPY(current_, current_ + count, data);
|
||||
|
||||
auto end = current_ + count;
|
||||
value_type* p = data;
|
||||
while (current_ != end)
|
||||
{
|
||||
*p++ = *current_++;
|
||||
}
|
||||
|
||||
//current_ += count;
|
||||
position_ += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template <class Category = iterator_category>
|
||||
typename std::enable_if<!std::is_same<Category,std::random_access_iterator_tag>::value, std::size_t>::type
|
||||
read(value_type* data, std::size_t length)
|
||||
{
|
||||
value_type* p = data;
|
||||
value_type* pend = data + length;
|
||||
|
||||
while (p < pend && current_ != end_)
|
||||
{
|
||||
*p = static_cast<value_type>(*current_);
|
||||
++p;
|
||||
++current_;
|
||||
}
|
||||
|
||||
position_ += (p - data);
|
||||
|
||||
return p - data;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Source>
|
||||
struct source_reader
|
||||
{
|
||||
using value_type = typename Source::value_type;
|
||||
static constexpr std::size_t max_buffer_length = 16384;
|
||||
|
||||
template <class Container>
|
||||
static
|
||||
typename std::enable_if<std::is_convertible<value_type,typename Container::value_type>::value &&
|
||||
extension_traits::has_reserve<Container>::value &&
|
||||
extension_traits::has_data_exact<value_type*,Container>::value
|
||||
, std::size_t>::type
|
||||
read(Source& source, Container& v, std::size_t length)
|
||||
{
|
||||
std::size_t unread = length;
|
||||
|
||||
std::size_t n = (std::min)(max_buffer_length, unread);
|
||||
while (n > 0 && !source.eof())
|
||||
{
|
||||
std::size_t offset = v.size();
|
||||
v.resize(v.size()+n);
|
||||
std::size_t actual = source.read(v.data()+offset, n);
|
||||
unread -= actual;
|
||||
n = (std::min)(max_buffer_length, unread);
|
||||
}
|
||||
|
||||
return length - unread;
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
static
|
||||
typename std::enable_if<std::is_convertible<value_type,typename Container::value_type>::value &&
|
||||
extension_traits::has_reserve<Container>::value &&
|
||||
!extension_traits::has_data_exact<value_type*, Container>::value
|
||||
, std::size_t>::type
|
||||
read(Source& source, Container& v, std::size_t length)
|
||||
{
|
||||
std::size_t unread = length;
|
||||
|
||||
std::size_t n = (std::min)(max_buffer_length, unread);
|
||||
while (n > 0 && !source.eof())
|
||||
{
|
||||
v.reserve(v.size()+n);
|
||||
std::size_t actual = 0;
|
||||
while (actual < n)
|
||||
{
|
||||
typename Source::value_type c;
|
||||
if (source.read(&c,1) != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
v.push_back(c);
|
||||
++actual;
|
||||
}
|
||||
unread -= actual;
|
||||
n = (std::min)(max_buffer_length, unread);
|
||||
}
|
||||
|
||||
return length - unread;
|
||||
}
|
||||
};
|
||||
template <class Source>
|
||||
constexpr std::size_t source_reader<Source>::max_buffer_length;
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
using bin_stream_source = binary_stream_source;
|
||||
#endif
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
148
scripts/exe/jsoncons/include/jsoncons/source_adaptor.hpp
Normal file
148
scripts/exe/jsoncons/include/jsoncons/source_adaptor.hpp
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BUFFER_READER_HPP
|
||||
#define JSONCONS_BUFFER_READER_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <memory> // std::allocator_traits
|
||||
#include <vector> // std::vector
|
||||
#include <jsoncons/unicode_traits.hpp>
|
||||
#include <jsoncons/json_error.hpp> // json_errc
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// text_source_adaptor
|
||||
|
||||
template<class Source>
|
||||
class text_source_adaptor
|
||||
{
|
||||
public:
|
||||
using value_type = typename Source::value_type;
|
||||
private:
|
||||
Source source_;
|
||||
bool bof_;
|
||||
|
||||
public:
|
||||
text_source_adaptor()
|
||||
: bof_(true)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
text_source_adaptor(Sourceable&& source)
|
||||
: source_(std::forward<Sourceable>(source)), bof_(true)
|
||||
{
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return source_.eof();
|
||||
}
|
||||
|
||||
bool is_error() const
|
||||
{
|
||||
return source_.is_error();
|
||||
}
|
||||
|
||||
span<const value_type> read_buffer(std::error_code& ec)
|
||||
{
|
||||
if (source_.eof())
|
||||
{
|
||||
return span<const value_type>();
|
||||
}
|
||||
|
||||
auto s = source_.read_buffer();
|
||||
const value_type* data = s.data();
|
||||
std::size_t length = s.size();
|
||||
|
||||
if (bof_ && length > 0)
|
||||
{
|
||||
auto r = unicode_traits::detect_encoding_from_bom(data, length);
|
||||
if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected))
|
||||
{
|
||||
ec = json_errc::illegal_unicode_character;
|
||||
return span<const value_type>();
|
||||
}
|
||||
length -= (r.ptr - data);
|
||||
data = r.ptr;
|
||||
bof_ = false;
|
||||
}
|
||||
return span<const value_type>(data, length);
|
||||
}
|
||||
};
|
||||
|
||||
// json_source_adaptor
|
||||
|
||||
template<class Source>
|
||||
class json_source_adaptor
|
||||
{
|
||||
public:
|
||||
using value_type = typename Source::value_type;
|
||||
private:
|
||||
Source source_;
|
||||
bool bof_;
|
||||
|
||||
public:
|
||||
json_source_adaptor()
|
||||
: bof_(true)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
json_source_adaptor(Sourceable&& source)
|
||||
: source_(std::forward<Sourceable>(source)), bof_(true)
|
||||
{
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return source_.eof();
|
||||
}
|
||||
|
||||
bool is_error() const
|
||||
{
|
||||
return source_.is_error();
|
||||
}
|
||||
|
||||
span<const value_type> read_buffer(std::error_code& ec)
|
||||
{
|
||||
if (source_.eof())
|
||||
{
|
||||
return span<const value_type>();
|
||||
}
|
||||
|
||||
auto s = source_.read_buffer();
|
||||
const value_type* data = s.data();
|
||||
std::size_t length = s.size();
|
||||
|
||||
if (bof_ && length > 0)
|
||||
{
|
||||
auto r = unicode_traits::detect_json_encoding(data, length);
|
||||
if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected))
|
||||
{
|
||||
ec = json_errc::illegal_unicode_character;
|
||||
return span<const value_type>();
|
||||
}
|
||||
length -= (r.ptr - data);
|
||||
data = r.ptr;
|
||||
bof_ = false;
|
||||
}
|
||||
|
||||
return span<const value_type>(data, length);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
1254
scripts/exe/jsoncons/include/jsoncons/staj_cursor.hpp
Normal file
1254
scripts/exe/jsoncons/include/jsoncons/staj_cursor.hpp
Normal file
File diff suppressed because it is too large
Load diff
449
scripts/exe/jsoncons/include/jsoncons/staj_iterator.hpp
Normal file
449
scripts/exe/jsoncons/include/jsoncons/staj_iterator.hpp
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_STAJ_ITERATOR_HPP
|
||||
#define JSONCONS_STAJ_ITERATOR_HPP
|
||||
|
||||
#include <new> // placement new
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <ios>
|
||||
#include <iterator> // std::input_iterator_tag
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/staj_cursor.hpp>
|
||||
#include <jsoncons/basic_json.hpp>
|
||||
#include <jsoncons/decode_traits.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
template <class T, class Json>
|
||||
class staj_array_view;
|
||||
|
||||
template<class T, class Json>
|
||||
class staj_array_iterator
|
||||
{
|
||||
using char_type = typename Json::char_type;
|
||||
|
||||
staj_array_view<T, Json>* view_;
|
||||
std::exception_ptr eptr_;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
|
||||
staj_array_iterator() noexcept
|
||||
: view_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
staj_array_iterator(staj_array_view<T, Json>& view)
|
||||
: view_(std::addressof(view))
|
||||
{
|
||||
if (view_->cursor_->current().event_type() == staj_event_type::begin_array)
|
||||
{
|
||||
next();
|
||||
}
|
||||
else
|
||||
{
|
||||
view_->cursor_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
staj_array_iterator(staj_array_view<T, Json>& view,
|
||||
std::error_code& ec)
|
||||
: view_(std::addressof(view))
|
||||
{
|
||||
if (view_->cursor_->current().event_type() == staj_event_type::begin_array)
|
||||
{
|
||||
next(ec);
|
||||
if (ec) {view_ = nullptr;}
|
||||
}
|
||||
else
|
||||
{
|
||||
view_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~staj_array_iterator() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
bool has_value() const
|
||||
{
|
||||
return !eptr_;
|
||||
}
|
||||
|
||||
const T& operator*() const
|
||||
{
|
||||
if (eptr_)
|
||||
{
|
||||
std::rethrow_exception(eptr_);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *view_->value_;
|
||||
}
|
||||
}
|
||||
|
||||
const T* operator->() const
|
||||
{
|
||||
if (eptr_)
|
||||
{
|
||||
std::rethrow_exception(eptr_);
|
||||
}
|
||||
else
|
||||
{
|
||||
return view_->value_.operator->();
|
||||
}
|
||||
}
|
||||
|
||||
staj_array_iterator& operator++()
|
||||
{
|
||||
next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
staj_array_iterator& increment(std::error_code& ec)
|
||||
{
|
||||
next(ec);
|
||||
if (ec) {view_ = nullptr;}
|
||||
return *this;
|
||||
}
|
||||
|
||||
staj_array_iterator operator++(int) // postfix increment
|
||||
{
|
||||
staj_array_iterator temp(*this);
|
||||
next();
|
||||
return temp;
|
||||
}
|
||||
|
||||
friend bool operator==(const staj_array_iterator& a, const staj_array_iterator& b)
|
||||
{
|
||||
return (!a.view_ && !b.view_)
|
||||
|| (!a.view_ && b.done())
|
||||
|| (!b.view_ && a.done());
|
||||
}
|
||||
|
||||
friend bool operator!=(const staj_array_iterator& a, const staj_array_iterator& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool done() const
|
||||
{
|
||||
return view_->cursor_->done() || view_->cursor_->current().event_type() == staj_event_type::end_array;
|
||||
}
|
||||
|
||||
void next()
|
||||
{
|
||||
std::error_code ec;
|
||||
next(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, view_->cursor_->context().line(), view_->cursor_->context().column()));
|
||||
}
|
||||
}
|
||||
|
||||
void next(std::error_code& ec)
|
||||
{
|
||||
using char_type = typename Json::char_type;
|
||||
|
||||
if (!done())
|
||||
{
|
||||
view_->cursor_->next(ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!done())
|
||||
{
|
||||
eptr_ = std::exception_ptr();
|
||||
JSONCONS_TRY
|
||||
{
|
||||
view_->value_ = decode_traits<T,char_type>::decode(*view_->cursor_, view_->decoder_, ec);
|
||||
}
|
||||
JSONCONS_CATCH(const conv_error&)
|
||||
{
|
||||
eptr_ = std::current_exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class Key,class Json,class T=Json>
|
||||
class staj_object_view;
|
||||
|
||||
template <class Key, class T, class Json>
|
||||
class staj_object_iterator
|
||||
{
|
||||
using char_type = typename Json::char_type;
|
||||
|
||||
staj_object_view<Key, T, Json>* view_;
|
||||
std::exception_ptr eptr_;
|
||||
public:
|
||||
using key_type = std::basic_string<char_type>;
|
||||
using value_type = std::pair<key_type,T>;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
|
||||
public:
|
||||
|
||||
staj_object_iterator() noexcept
|
||||
: view_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
staj_object_iterator(staj_object_view<Key, T, Json>& view)
|
||||
: view_(std::addressof(view))
|
||||
{
|
||||
if (view_->cursor_->current().event_type() == staj_event_type::begin_object)
|
||||
{
|
||||
next();
|
||||
}
|
||||
else
|
||||
{
|
||||
view_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
staj_object_iterator(staj_object_view<Key, T, Json>& view,
|
||||
std::error_code& ec)
|
||||
: view_(std::addressof(view))
|
||||
{
|
||||
if (view_->cursor_->current().event_type() == staj_event_type::begin_object)
|
||||
{
|
||||
next(ec);
|
||||
if (ec) {view_ = nullptr;}
|
||||
}
|
||||
else
|
||||
{
|
||||
view_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~staj_object_iterator() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
bool has_value() const
|
||||
{
|
||||
return !eptr_;
|
||||
}
|
||||
|
||||
const value_type& operator*() const
|
||||
{
|
||||
if (eptr_)
|
||||
{
|
||||
std::rethrow_exception(eptr_);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *view_->key_value_;
|
||||
}
|
||||
}
|
||||
|
||||
const value_type* operator->() const
|
||||
{
|
||||
if (eptr_)
|
||||
{
|
||||
std::rethrow_exception(eptr_);
|
||||
}
|
||||
else
|
||||
{
|
||||
return view_->key_value_.operator->();
|
||||
}
|
||||
}
|
||||
|
||||
staj_object_iterator& operator++()
|
||||
{
|
||||
next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
staj_object_iterator& increment(std::error_code& ec)
|
||||
{
|
||||
next(ec);
|
||||
if (ec)
|
||||
{
|
||||
view_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
staj_object_iterator operator++(int) // postfix increment
|
||||
{
|
||||
staj_object_iterator temp(*this);
|
||||
next();
|
||||
return temp;
|
||||
}
|
||||
|
||||
friend bool operator==(const staj_object_iterator& a, const staj_object_iterator& b)
|
||||
{
|
||||
return (!a.view_ && !b.view_)
|
||||
|| (!a.view_ && b.done())
|
||||
|| (!b.view_ && a.done());
|
||||
}
|
||||
|
||||
friend bool operator!=(const staj_object_iterator& a, const staj_object_iterator& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool done() const
|
||||
{
|
||||
return view_->cursor_->done() || view_->cursor_->current().event_type() == staj_event_type::end_object;
|
||||
}
|
||||
|
||||
void next()
|
||||
{
|
||||
std::error_code ec;
|
||||
next(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, view_->cursor_->context().line(), view_->cursor_->context().column()));
|
||||
}
|
||||
}
|
||||
|
||||
void next(std::error_code& ec)
|
||||
{
|
||||
using char_type = typename Json::char_type;
|
||||
|
||||
view_->cursor_->next(ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!done())
|
||||
{
|
||||
JSONCONS_ASSERT(view_->cursor_->current().event_type() == staj_event_type::key);
|
||||
auto key = view_->cursor_->current(). template get<key_type>();
|
||||
view_->cursor_->next(ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!done())
|
||||
{
|
||||
eptr_ = std::exception_ptr();
|
||||
JSONCONS_TRY
|
||||
{
|
||||
view_->key_value_ = value_type(std::move(key),decode_traits<T,char_type>::decode(*view_->cursor_, view_->decoder_, ec));
|
||||
}
|
||||
JSONCONS_CATCH(const conv_error&)
|
||||
{
|
||||
eptr_ = std::current_exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// staj_array_view
|
||||
|
||||
template <class T, class Json>
|
||||
class staj_array_view
|
||||
{
|
||||
friend class staj_array_iterator<T, Json>;
|
||||
public:
|
||||
using char_type = typename Json::char_type;
|
||||
using iterator = staj_array_iterator<T, Json>;
|
||||
private:
|
||||
basic_staj_cursor<char_type>* cursor_;
|
||||
json_decoder<Json> decoder_;
|
||||
jsoncons::optional<T> value_;
|
||||
public:
|
||||
staj_array_view(basic_staj_cursor<char_type>& cursor)
|
||||
: cursor_(std::addressof(cursor))
|
||||
{
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return staj_array_iterator<T, Json>(*this);
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return staj_array_iterator<T, Json>();
|
||||
}
|
||||
};
|
||||
|
||||
// staj_object_view
|
||||
|
||||
template <class Key, class T, class Json>
|
||||
class staj_object_view
|
||||
{
|
||||
friend class staj_object_iterator<Key,T,Json>;
|
||||
public:
|
||||
using char_type = typename Json::char_type;
|
||||
using iterator = staj_object_iterator<Key,T,Json>;
|
||||
using key_type = std::basic_string<char_type>;
|
||||
using value_type = std::pair<key_type,T>;
|
||||
private:
|
||||
basic_staj_cursor<char_type>* cursor_;
|
||||
json_decoder<Json> decoder_;
|
||||
jsoncons::optional<value_type> key_value_;
|
||||
public:
|
||||
staj_object_view(basic_staj_cursor<char_type>& cursor)
|
||||
: cursor_(std::addressof(cursor))
|
||||
{
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return staj_object_iterator<Key,T,Json>(*this);
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return staj_object_iterator<Key,T,Json>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class CharT, class Json=typename std::conditional<extension_traits::is_basic_json<T>::value,T,basic_json<CharT>>::type>
|
||||
staj_array_view<T, Json> staj_array(basic_staj_cursor<CharT>& cursor)
|
||||
{
|
||||
return staj_array_view<T, Json>(cursor);
|
||||
}
|
||||
|
||||
template <class Key, class T, class CharT, class Json=typename std::conditional<extension_traits::is_basic_json<T>::value,T,basic_json<CharT>>::type>
|
||||
staj_object_view<Key, T, Json> staj_object(basic_staj_cursor<CharT>& cursor)
|
||||
{
|
||||
return staj_object_view<Key, T, Json>(cursor);
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
template <class T, class CharT, class Json=typename std::conditional<extension_traits::is_basic_json<T>::value,T,basic_json<CharT>>::type>
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use staj_array()")
|
||||
staj_array_view<T, Json> make_array_iterator(basic_staj_cursor<CharT>& cursor)
|
||||
{
|
||||
return staj_array_view<T, Json>(cursor);
|
||||
}
|
||||
|
||||
template <class T, class CharT, class Json=typename std::conditional<extension_traits::is_basic_json<T>::value,T,basic_json<CharT>>::type>
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use staj_object()")
|
||||
staj_object_view<std::basic_string<CharT>, T, Json> make_object_iterator(basic_staj_cursor<CharT>& cursor)
|
||||
{
|
||||
return staj_object_view<std::basic_string<CharT>, T, Json>(cursor);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
245
scripts/exe/jsoncons/include/jsoncons/tag_type.hpp
Normal file
245
scripts/exe/jsoncons/include/jsoncons/tag_type.hpp
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_TAG_TYPE_HPP
|
||||
#define JSONCONS_TAG_TYPE_HPP
|
||||
|
||||
#include <ostream>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
struct null_type
|
||||
{
|
||||
explicit null_type() = default;
|
||||
};
|
||||
|
||||
struct temp_allocator_arg_t
|
||||
{
|
||||
explicit temp_allocator_arg_t() = default;
|
||||
};
|
||||
|
||||
constexpr temp_allocator_arg_t temp_allocator_arg{};
|
||||
|
||||
struct result_allocator_arg_t
|
||||
{
|
||||
explicit result_allocator_arg_t() = default;
|
||||
};
|
||||
|
||||
constexpr result_allocator_arg_t result_allocator_arg{};
|
||||
|
||||
struct half_arg_t
|
||||
{
|
||||
explicit half_arg_t() = default;
|
||||
};
|
||||
|
||||
constexpr half_arg_t half_arg{};
|
||||
|
||||
struct json_array_arg_t
|
||||
{
|
||||
explicit json_array_arg_t() = default;
|
||||
};
|
||||
|
||||
constexpr json_array_arg_t json_array_arg{};
|
||||
|
||||
struct json_object_arg_t
|
||||
{
|
||||
explicit json_object_arg_t() = default;
|
||||
};
|
||||
|
||||
constexpr json_object_arg_t json_object_arg{};
|
||||
|
||||
struct byte_string_arg_t
|
||||
{
|
||||
explicit byte_string_arg_t() = default;
|
||||
};
|
||||
|
||||
constexpr byte_string_arg_t byte_string_arg{};
|
||||
|
||||
struct json_const_pointer_arg_t
|
||||
{
|
||||
explicit json_const_pointer_arg_t() = default;
|
||||
};
|
||||
|
||||
constexpr json_const_pointer_arg_t json_const_pointer_arg{};
|
||||
|
||||
enum class semantic_tag : uint8_t
|
||||
{
|
||||
none = 0,
|
||||
undefined = 0x01,
|
||||
datetime = 0x02,
|
||||
epoch_second = 0x03,
|
||||
epoch_milli = 0x04,
|
||||
epoch_nano = 0x05,
|
||||
bigint = 0x06,
|
||||
bigdec = 0x07,
|
||||
bigfloat = 0x08,
|
||||
float128 = 0x09,
|
||||
base16 = 0x1a,
|
||||
base64 = 0x1b,
|
||||
base64url = 0x1c,
|
||||
uri = 0x0d,
|
||||
clamped = 0x0e,
|
||||
multi_dim_row_major = 0x0f,
|
||||
multi_dim_column_major = 0x10,
|
||||
ext = 0x11,
|
||||
id = 0x12,
|
||||
regex = 0x13,
|
||||
code = 0x14
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
, big_integer = bigint
|
||||
, big_decimal = bigdec
|
||||
, big_float = bigfloat
|
||||
, date_time = datetime
|
||||
, timestamp = epoch_second
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os, semantic_tag tag)
|
||||
{
|
||||
static constexpr const CharT* na_name = JSONCONS_CSTRING_CONSTANT(CharT, "n/a");
|
||||
static constexpr const CharT* undefined_name = JSONCONS_CSTRING_CONSTANT(CharT, "undefined");
|
||||
static constexpr const CharT* datetime_name = JSONCONS_CSTRING_CONSTANT(CharT, "datetime");
|
||||
static constexpr const CharT* epoch_second_name = JSONCONS_CSTRING_CONSTANT(CharT, "epoch-second");
|
||||
static constexpr const CharT* epoch_milli_name = JSONCONS_CSTRING_CONSTANT(CharT, "epoch-milli");
|
||||
static constexpr const CharT* epoch_nano_name = JSONCONS_CSTRING_CONSTANT(CharT, "epoch-nano");
|
||||
static constexpr const CharT* bigint_name = JSONCONS_CSTRING_CONSTANT(CharT, "bigint");
|
||||
static constexpr const CharT* bigdec_name = JSONCONS_CSTRING_CONSTANT(CharT, "bigdec");
|
||||
static constexpr const CharT* bigfloat_name = JSONCONS_CSTRING_CONSTANT(CharT, "bigfloat");
|
||||
static constexpr const CharT* base16_name = JSONCONS_CSTRING_CONSTANT(CharT, "base16");
|
||||
static constexpr const CharT* base64_name = JSONCONS_CSTRING_CONSTANT(CharT, "base64");
|
||||
static constexpr const CharT* base64url_name = JSONCONS_CSTRING_CONSTANT(CharT, "base64url");
|
||||
static constexpr const CharT* uri_name = JSONCONS_CSTRING_CONSTANT(CharT, "uri");
|
||||
static constexpr const CharT* clamped_name = JSONCONS_CSTRING_CONSTANT(CharT, "clamped");
|
||||
static constexpr const CharT* multi_dim_row_major_name = JSONCONS_CSTRING_CONSTANT(CharT, "multi-dim-row-major");
|
||||
static constexpr const CharT* multi_dim_column_major_name = JSONCONS_CSTRING_CONSTANT(CharT, "multi-dim-column-major");
|
||||
static constexpr const CharT* ext_name = JSONCONS_CSTRING_CONSTANT(CharT, "ext");
|
||||
static constexpr const CharT* id_name = JSONCONS_CSTRING_CONSTANT(CharT, "id");
|
||||
static constexpr const CharT* float128_name = JSONCONS_CSTRING_CONSTANT(CharT, "float128");
|
||||
static constexpr const CharT* regex_name = JSONCONS_CSTRING_CONSTANT(CharT, "regex");
|
||||
static constexpr const CharT* code_name = JSONCONS_CSTRING_CONSTANT(CharT, "code");
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::none:
|
||||
{
|
||||
os << na_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::undefined:
|
||||
{
|
||||
os << undefined_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::datetime:
|
||||
{
|
||||
os << datetime_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::epoch_second:
|
||||
{
|
||||
os << epoch_second_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::epoch_milli:
|
||||
{
|
||||
os << epoch_milli_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::epoch_nano:
|
||||
{
|
||||
os << epoch_nano_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::bigint:
|
||||
{
|
||||
os << bigint_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::bigdec:
|
||||
{
|
||||
os << bigdec_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::bigfloat:
|
||||
{
|
||||
os << bigfloat_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::float128:
|
||||
{
|
||||
os << float128_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::base16:
|
||||
{
|
||||
os << base16_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::base64:
|
||||
{
|
||||
os << base64_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::base64url:
|
||||
{
|
||||
os << base64url_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::uri:
|
||||
{
|
||||
os << uri_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::clamped:
|
||||
{
|
||||
os << clamped_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::multi_dim_row_major:
|
||||
{
|
||||
os << multi_dim_row_major_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::multi_dim_column_major:
|
||||
{
|
||||
os << multi_dim_column_major_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::ext:
|
||||
{
|
||||
os << ext_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::id:
|
||||
{
|
||||
os << id_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::regex:
|
||||
{
|
||||
os << regex_name;
|
||||
break;
|
||||
}
|
||||
case semantic_tag::code:
|
||||
{
|
||||
os << code_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use semantic_tag") typedef semantic_tag semantic_tag_type;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use byte_string_arg_t") typedef byte_string_arg_t bstr_arg_t;
|
||||
constexpr byte_string_arg_t bstr_arg{};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
144
scripts/exe/jsoncons/include/jsoncons/text_source_adaptor.hpp
Normal file
144
scripts/exe/jsoncons/include/jsoncons/text_source_adaptor.hpp
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_TEXT_SOURCE_ADAPTOR_HPP
|
||||
#define JSONCONS_TEXT_SOURCE_ADAPTOR_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <memory> // std::allocator_traits
|
||||
#include <vector> // std::vector
|
||||
#include <jsoncons/unicode_traits.hpp>
|
||||
#include <jsoncons/json_error.hpp> // json_errc
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
// unicode_source_adaptor
|
||||
|
||||
template<class Source,class Allocator>
|
||||
class unicode_source_adaptor
|
||||
{
|
||||
public:
|
||||
using value_type = typename Source::value_type;
|
||||
using source_type = Source;
|
||||
private:
|
||||
source_type source_;
|
||||
bool bof_;
|
||||
|
||||
|
||||
public:
|
||||
template <class Sourceable>
|
||||
unicode_source_adaptor(Sourceable&& source)
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
bof_(true)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_error() const
|
||||
{
|
||||
return source_.is_error();
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return source_.eof();
|
||||
}
|
||||
|
||||
span<const value_type> read_buffer(std::error_code& ec)
|
||||
{
|
||||
if (source_.eof())
|
||||
{
|
||||
return span<const value_type>();
|
||||
}
|
||||
|
||||
auto s = source_.read_buffer();
|
||||
const value_type* data = s.data();
|
||||
std::size_t length = s.size();
|
||||
|
||||
if (bof_ && length > 0)
|
||||
{
|
||||
auto r = unicode_traits::detect_encoding_from_bom(data, length);
|
||||
if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected))
|
||||
{
|
||||
ec = json_errc::illegal_unicode_character;
|
||||
return;
|
||||
}
|
||||
length -= (r.ptr - data);
|
||||
data = r.ptr;
|
||||
bof_ = false;
|
||||
}
|
||||
return span<const value_type>(data, length);
|
||||
}
|
||||
};
|
||||
|
||||
// json_source_adaptor
|
||||
|
||||
template<class Source,class Allocator>
|
||||
class json_source_adaptor
|
||||
{
|
||||
public:
|
||||
using value_type = typename Source::value_type;
|
||||
using value_type = typename Source::value_type;
|
||||
using source_type = Source;
|
||||
private:
|
||||
source_type source_;
|
||||
bool bof_;
|
||||
|
||||
public:
|
||||
|
||||
template <class Sourceable>
|
||||
json_source_adaptor(Sourceable&& source)
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
bof_(true)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_error() const
|
||||
{
|
||||
return source_.is_error();
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return source_.eof();
|
||||
}
|
||||
|
||||
span<const value_type> read_buffer(std::error_code& ec)
|
||||
{
|
||||
if (source_.eof())
|
||||
{
|
||||
return span<const value_type>();
|
||||
}
|
||||
|
||||
auto s = source_.read_buffer();
|
||||
const value_type* data = s.data();
|
||||
std::size_t length = s.size();
|
||||
|
||||
if (bof_ && length > 0)
|
||||
{
|
||||
auto r = unicode_traits::detect_json_encoding(data, length);
|
||||
if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected))
|
||||
{
|
||||
ec = json_errc::illegal_unicode_character;
|
||||
return span<const value_type>();
|
||||
}
|
||||
length -= (r.ptr - data);
|
||||
data = r.ptr;
|
||||
bof_ = false;
|
||||
}
|
||||
return span<const value_type>(data, length);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
250
scripts/exe/jsoncons/include/jsoncons/typed_array_view.hpp
Normal file
250
scripts/exe/jsoncons/include/jsoncons/typed_array_view.hpp
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_TYPED_ARRAY_VIEW_HPP
|
||||
#define JSONCONS_TYPED_ARRAY_VIEW_HPP
|
||||
|
||||
#include <memory> // std::allocator
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <ios>
|
||||
#include <type_traits> // std::enable_if
|
||||
#include <array> // std::array
|
||||
#include <functional> // std::function
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/bigint.hpp>
|
||||
#include <jsoncons/json_parser.hpp>
|
||||
#include <jsoncons/ser_context.hpp>
|
||||
#include <jsoncons/sink.hpp>
|
||||
#include <jsoncons/detail/write_number.hpp>
|
||||
#include <jsoncons/json_type_traits.hpp>
|
||||
#include <jsoncons/value_converter.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
struct uint8_array_arg_t {explicit uint8_array_arg_t() = default; };
|
||||
constexpr uint8_array_arg_t uint8_array_arg = uint8_array_arg_t();
|
||||
struct uint16_array_arg_t {explicit uint16_array_arg_t() = default; };
|
||||
struct uint32_array_arg_t {explicit uint32_array_arg_t() = default; };
|
||||
constexpr uint32_array_arg_t uint32_array_arg = uint32_array_arg_t();
|
||||
struct uint64_array_arg_t {explicit uint64_array_arg_t() = default; };
|
||||
constexpr uint64_array_arg_t uint64_array_arg = uint64_array_arg_t();
|
||||
struct int8_array_arg_t {explicit int8_array_arg_t() = default; };
|
||||
constexpr int8_array_arg_t int8_array_arg = int8_array_arg_t();
|
||||
struct int16_array_arg_t {explicit int16_array_arg_t() = default; };
|
||||
constexpr int16_array_arg_t int16_array_arg = int16_array_arg_t();
|
||||
struct int32_array_arg_t {explicit int32_array_arg_t() = default; };
|
||||
constexpr int32_array_arg_t int32_array_arg = int32_array_arg_t();
|
||||
struct int64_array_arg_t {explicit int64_array_arg_t() = default; };
|
||||
constexpr int64_array_arg_t int64_array_arg = int64_array_arg_t();
|
||||
constexpr uint16_array_arg_t uint16_array_arg = uint16_array_arg_t();
|
||||
struct half_array_arg_t {explicit half_array_arg_t() = default; };
|
||||
constexpr half_array_arg_t half_array_arg = half_array_arg_t();
|
||||
struct float_array_arg_t {explicit float_array_arg_t() = default; };
|
||||
constexpr float_array_arg_t float_array_arg = float_array_arg_t();
|
||||
struct double_array_arg_t {explicit double_array_arg_t() = default; };
|
||||
constexpr double_array_arg_t double_array_arg = double_array_arg_t();
|
||||
struct float128_array_arg_t {explicit float128_array_arg_t() = default; };
|
||||
constexpr float128_array_arg_t float128_array_arg = float128_array_arg_t();
|
||||
|
||||
enum class typed_array_type{uint8_value=1,uint16_value,uint32_value,uint64_value,
|
||||
int8_value,int16_value,int32_value,int64_value,
|
||||
half_value, float_value,double_value};
|
||||
|
||||
class typed_array_view
|
||||
{
|
||||
typed_array_type type_;
|
||||
union
|
||||
{
|
||||
const uint8_t* uint8_data_;
|
||||
const uint16_t* uint16_data_;
|
||||
const uint32_t* uint32_data_;
|
||||
const uint64_t* uint64_data_;
|
||||
const int8_t* int8_data_;
|
||||
const int16_t* int16_data_;
|
||||
const int32_t* int32_data_;
|
||||
const int64_t* int64_data_;
|
||||
const float* float_data_;
|
||||
const double* double_data_;
|
||||
} data_;
|
||||
std::size_t size_;
|
||||
public:
|
||||
|
||||
typed_array_view()
|
||||
: type_(), data_(), size_(0)
|
||||
{
|
||||
}
|
||||
|
||||
typed_array_view(const typed_array_view& other)
|
||||
: type_(other.type_), data_(other.data_), size_(other.size())
|
||||
{
|
||||
}
|
||||
|
||||
typed_array_view(typed_array_view&& other) noexcept
|
||||
{
|
||||
swap(*this,other);
|
||||
}
|
||||
|
||||
typed_array_view(const uint8_t* data, std::size_t size)
|
||||
: type_(typed_array_type::uint8_value), size_(size)
|
||||
{
|
||||
data_.uint8_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view(const uint16_t* data, std::size_t size)
|
||||
: type_(typed_array_type::uint16_value), size_(size)
|
||||
{
|
||||
data_.uint16_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view(const uint32_t* data, std::size_t size)
|
||||
: type_(typed_array_type::uint32_value), size_(size)
|
||||
{
|
||||
data_.uint32_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view(const uint64_t* data, std::size_t size)
|
||||
: type_(typed_array_type::uint64_value), size_(size)
|
||||
{
|
||||
data_.uint64_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view(const int8_t* data, std::size_t size)
|
||||
: type_(typed_array_type::int8_value), size_(size)
|
||||
{
|
||||
data_.int8_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view(const int16_t* data, std::size_t size)
|
||||
: type_(typed_array_type::int16_value), size_(size)
|
||||
{
|
||||
data_.int16_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view(const int32_t* data, std::size_t size)
|
||||
: type_(typed_array_type::int32_value), size_(size)
|
||||
{
|
||||
data_.int32_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view(const int64_t* data, std::size_t size)
|
||||
: type_(typed_array_type::int64_value), size_(size)
|
||||
{
|
||||
data_.int64_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view(half_array_arg_t, const uint16_t* data, std::size_t size)
|
||||
: type_(typed_array_type::half_value), size_(size)
|
||||
{
|
||||
data_.uint16_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view(const float* data, std::size_t size)
|
||||
: type_(typed_array_type::float_value), size_(size)
|
||||
{
|
||||
data_.float_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view(const double* data, std::size_t size)
|
||||
: type_(typed_array_type::double_value), size_(size)
|
||||
{
|
||||
data_.double_data_ = data;
|
||||
}
|
||||
|
||||
typed_array_view& operator=(const typed_array_view& other)
|
||||
{
|
||||
typed_array_view temp(other);
|
||||
swap(*this,temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
typed_array_type type() const {return type_;}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
jsoncons::span<const uint8_t> data(uint8_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::uint8_value);
|
||||
return jsoncons::span<const uint8_t>(data_.uint8_data_, size_);
|
||||
}
|
||||
|
||||
jsoncons::span<const uint16_t> data(uint16_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::uint16_value);
|
||||
return jsoncons::span<const uint16_t>(data_.uint16_data_, size_);
|
||||
}
|
||||
|
||||
jsoncons::span<const uint32_t> data(uint32_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::uint32_value);
|
||||
return jsoncons::span<const uint32_t>(data_.uint32_data_, size_);
|
||||
}
|
||||
|
||||
jsoncons::span<const uint64_t> data(uint64_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::uint64_value);
|
||||
return jsoncons::span<const uint64_t>(data_.uint64_data_, size_);
|
||||
}
|
||||
|
||||
jsoncons::span<const int8_t> data(int8_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::int8_value);
|
||||
return jsoncons::span<const int8_t>(data_.int8_data_, size_);
|
||||
}
|
||||
|
||||
jsoncons::span<const int16_t> data(int16_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::int16_value);
|
||||
return jsoncons::span<const int16_t>(data_.int16_data_, size_);
|
||||
}
|
||||
|
||||
jsoncons::span<const int32_t> data(int32_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::int32_value);
|
||||
return jsoncons::span<const int32_t>(data_.int32_data_, size_);
|
||||
}
|
||||
|
||||
jsoncons::span<const int64_t> data(int64_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::int64_value);
|
||||
return jsoncons::span<const int64_t>(data_.int64_data_, size_);
|
||||
}
|
||||
|
||||
jsoncons::span<const uint16_t> data(half_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::half_value);
|
||||
return jsoncons::span<const uint16_t>(data_.uint16_data_, size_);
|
||||
}
|
||||
|
||||
jsoncons::span<const float> data(float_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::float_value);
|
||||
return jsoncons::span<const float>(data_.float_data_, size_);
|
||||
}
|
||||
|
||||
jsoncons::span<const double> data(double_array_arg_t) const
|
||||
{
|
||||
JSONCONS_ASSERT(type_ == typed_array_type::double_value);
|
||||
return jsoncons::span<const double>(data_.double_data_, size_);
|
||||
}
|
||||
|
||||
friend void swap(typed_array_view& a, typed_array_view& b) noexcept
|
||||
{
|
||||
std::swap(a.data_,b.data_);
|
||||
std::swap(a.type_,b.type_);
|
||||
std::swap(a.size_,b.size_);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
1330
scripts/exe/jsoncons/include/jsoncons/unicode_traits.hpp
Normal file
1330
scripts/exe/jsoncons/include/jsoncons/unicode_traits.hpp
Normal file
File diff suppressed because it is too large
Load diff
635
scripts/exe/jsoncons/include/jsoncons/uri.hpp
Normal file
635
scripts/exe/jsoncons/include/jsoncons/uri.hpp
Normal file
|
|
@ -0,0 +1,635 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_URI_HPP
|
||||
#define JSONCONS_URI_HPP
|
||||
|
||||
#include <string> // std::string
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
class uri
|
||||
{
|
||||
using part_type = std::pair<std::size_t,std::size_t>;
|
||||
|
||||
std::string uri_;
|
||||
part_type scheme_;
|
||||
part_type userinfo_;
|
||||
part_type host_;
|
||||
part_type port_;
|
||||
part_type path_;
|
||||
part_type query_;
|
||||
part_type fragment_;
|
||||
public:
|
||||
|
||||
uri() = default;
|
||||
|
||||
uri(const std::string& uri)
|
||||
{
|
||||
*this = parse(uri);
|
||||
}
|
||||
|
||||
uri(jsoncons::string_view scheme,
|
||||
jsoncons::string_view userinfo,
|
||||
jsoncons::string_view host,
|
||||
jsoncons::string_view port,
|
||||
jsoncons::string_view path,
|
||||
jsoncons::string_view query,
|
||||
jsoncons::string_view fragment)
|
||||
{
|
||||
if (!scheme.empty())
|
||||
{
|
||||
uri_.append(std::string(scheme));
|
||||
scheme_.second = uri_.length();
|
||||
}
|
||||
if (!userinfo.empty() || !host.empty() || !port.empty())
|
||||
{
|
||||
if (!scheme.empty())
|
||||
{
|
||||
uri_.append("://");
|
||||
}
|
||||
|
||||
if (!userinfo.empty())
|
||||
{
|
||||
userinfo_.first = uri_.length();
|
||||
uri_.append(std::string(userinfo));
|
||||
userinfo_.second = uri_.length();
|
||||
uri_.append("@");
|
||||
}
|
||||
else
|
||||
{
|
||||
userinfo_.first = userinfo_.second = uri_.length();
|
||||
}
|
||||
|
||||
if (!host.empty())
|
||||
{
|
||||
host_.first = uri_.length();
|
||||
uri_.append(std::string(host));
|
||||
host_.second = uri_.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("uri error."));
|
||||
}
|
||||
|
||||
if (!port.empty())
|
||||
{
|
||||
uri_.append(":");
|
||||
port_.first = uri_.length();
|
||||
uri_.append(std::string(port));
|
||||
port_.second = uri_.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
port_.first = port_.second = uri_.length();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
userinfo_.first = userinfo_.second = uri_.length();
|
||||
host_.first = host_.second = uri_.length();
|
||||
port_.first = port_.second = uri_.length();
|
||||
if (!scheme.empty())
|
||||
{
|
||||
if (!path.empty() || !query.empty() || !fragment.empty())
|
||||
{
|
||||
uri_.append(":");
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("uri error."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!path.empty())
|
||||
{
|
||||
// if the URI is not opaque and the path is not already prefixed
|
||||
// with a '/', add one.
|
||||
path_.first = uri_.length();
|
||||
if (!host.empty() && (path.front() != '/'))
|
||||
{
|
||||
uri_.push_back('/');
|
||||
}
|
||||
uri_.append(std::string(path));
|
||||
path_.second = uri_.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
path_.first = path_.second = uri_.length();
|
||||
}
|
||||
|
||||
if (!query.empty())
|
||||
{
|
||||
uri_.append("?");
|
||||
query_.first = uri_.length();
|
||||
uri_.append(std::string(query));
|
||||
query_.second = uri_.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
query_.first = query_.second = uri_.length();
|
||||
}
|
||||
|
||||
if (!fragment.empty())
|
||||
{
|
||||
uri_.append("#");
|
||||
fragment_.first = uri_.length();
|
||||
uri_.append(std::string(fragment));
|
||||
fragment_.second = uri_.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
fragment_.first = fragment_.second = uri_.length();
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& string() const
|
||||
{
|
||||
return uri_;
|
||||
}
|
||||
|
||||
bool is_absolute() const noexcept
|
||||
{
|
||||
return scheme_.first != scheme_.second;
|
||||
}
|
||||
|
||||
bool is_opaque() const noexcept
|
||||
{
|
||||
return is_absolute() && !authority().empty();
|
||||
}
|
||||
|
||||
string_view base() const noexcept { return string_view(uri_.data()+scheme_.first,(path_.second-scheme_.first)); }
|
||||
|
||||
string_view scheme() const noexcept { return string_view(uri_.data()+scheme_.first,(scheme_.second-scheme_.first)); }
|
||||
|
||||
string_view userinfo() const noexcept { return string_view(uri_.data()+userinfo_.first,(userinfo_.second-userinfo_.first)); }
|
||||
|
||||
string_view host() const noexcept { return string_view(uri_.data()+host_.first,(host_.second-host_.first)); }
|
||||
|
||||
string_view port() const noexcept { return string_view(uri_.data()+port_.first,(port_.second-port_.first)); }
|
||||
|
||||
string_view path() const noexcept { return string_view(uri_.data()+path_.first,(path_.second-path_.first)); }
|
||||
|
||||
string_view query() const noexcept { return string_view(uri_.data()+query_.first,(query_.second-query_.first)); }
|
||||
|
||||
string_view fragment() const noexcept { return string_view(uri_.data()+fragment_.first,(fragment_.second-fragment_.first)); }
|
||||
|
||||
string_view authority() const noexcept { return string_view(uri_.data()+userinfo_.first,(port_.second-userinfo_.first)); }
|
||||
|
||||
uri resolve(const uri& base) const
|
||||
{
|
||||
// This implementation uses the psuedo-code given in
|
||||
// http://tools.ietf.org/html/rfc3986#section-5.2.2
|
||||
|
||||
if (is_absolute() && !is_opaque())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (is_opaque())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string userinfo, host, port, path, query, fragment;
|
||||
|
||||
if (!authority().empty())
|
||||
{
|
||||
// g -> http://g
|
||||
if (!this->userinfo().empty())
|
||||
{
|
||||
userinfo = std::string(this->userinfo());
|
||||
}
|
||||
|
||||
if (!this->host().empty())
|
||||
{
|
||||
host = std::string(this->host());
|
||||
}
|
||||
|
||||
if (!this->port().empty())
|
||||
{
|
||||
port = std::string(this->port());
|
||||
}
|
||||
|
||||
if (!this->path().empty())
|
||||
{
|
||||
path = remove_dot_segments(this->path());
|
||||
}
|
||||
|
||||
if (!this->query().empty())
|
||||
{
|
||||
query = std::string(this->query());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->path().empty())
|
||||
{
|
||||
if (!base.path().empty())
|
||||
{
|
||||
path = std::string(base.path());
|
||||
}
|
||||
|
||||
if (!this->query().empty())
|
||||
{
|
||||
query = std::string(this->query());
|
||||
}
|
||||
else if (!base.query().empty())
|
||||
{
|
||||
query = std::string(base.query());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->path().front() == '/')
|
||||
{
|
||||
path = remove_dot_segments(this->path());
|
||||
}
|
||||
else
|
||||
{
|
||||
path = merge_paths(base, *this);
|
||||
}
|
||||
|
||||
if (!this->query().empty())
|
||||
{
|
||||
query = std::string(this->query());
|
||||
}
|
||||
}
|
||||
|
||||
if (!base.userinfo().empty())
|
||||
{
|
||||
userinfo = std::string(base.userinfo());
|
||||
}
|
||||
|
||||
if (!base.host().empty())
|
||||
{
|
||||
host = std::string(base.host());
|
||||
}
|
||||
|
||||
if (!base.port().empty())
|
||||
{
|
||||
port = std::string(base.port());
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->fragment().empty())
|
||||
{
|
||||
fragment = std::string(this->fragment());
|
||||
}
|
||||
|
||||
return uri(std::string(base.scheme()), userinfo, host, port, path, query, fragment);
|
||||
}
|
||||
|
||||
int compare(const uri& other) const
|
||||
{
|
||||
int result = scheme().compare(other.scheme());
|
||||
if (result != 0) return result;
|
||||
result = userinfo().compare(other.userinfo());
|
||||
if (result != 0) return result;
|
||||
result = host().compare(other.host());
|
||||
if (result != 0) return result;
|
||||
result = port().compare(other.port());
|
||||
if (result != 0) return result;
|
||||
result = path().compare(other.path());
|
||||
if (result != 0) return result;
|
||||
result = query().compare(other.query());
|
||||
if (result != 0) return result;
|
||||
result = fragment().compare(other.fragment());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator==(const uri& lhs, const uri& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) == 0;
|
||||
}
|
||||
|
||||
friend bool operator!=(const uri& lhs, const uri& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) != 0;
|
||||
}
|
||||
|
||||
friend bool operator<(const uri& lhs, const uri& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) < 0;
|
||||
}
|
||||
|
||||
friend bool operator<=(const uri& lhs, const uri& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) <= 0;
|
||||
}
|
||||
|
||||
friend bool operator>(const uri& lhs, const uri& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) > 0;
|
||||
}
|
||||
|
||||
friend bool operator>=(const uri& lhs, const uri& rhs)
|
||||
{
|
||||
return lhs.compare(rhs) >= 0;
|
||||
}
|
||||
|
||||
private:
|
||||
enum class parse_state {expect_scheme,
|
||||
expect_first_slash,
|
||||
expect_second_slash,
|
||||
expect_authority,
|
||||
expect_host_ipv6,
|
||||
expect_userinfo,
|
||||
expect_host,
|
||||
expect_port,
|
||||
expect_path,
|
||||
expect_query,
|
||||
expect_fragment};
|
||||
|
||||
uri(const std::string& uri, part_type scheme, part_type userinfo,
|
||||
part_type host, part_type port, part_type path,
|
||||
part_type query, part_type fragment)
|
||||
: uri_(uri), scheme_(scheme), userinfo_(userinfo),
|
||||
host_(host), port_(port), path_(path),
|
||||
query_(query), fragment_(fragment)
|
||||
{
|
||||
}
|
||||
|
||||
static uri parse(const std::string& s)
|
||||
{
|
||||
part_type scheme;
|
||||
part_type userinfo;
|
||||
part_type host;
|
||||
part_type port;
|
||||
part_type path;
|
||||
part_type query;
|
||||
part_type fragment;
|
||||
|
||||
std::size_t start = 0;
|
||||
|
||||
parse_state state = parse_state::expect_scheme;
|
||||
for (std::size_t i = 0; i < s.size(); ++i)
|
||||
{
|
||||
char c = s[i];
|
||||
switch (state)
|
||||
{
|
||||
case parse_state::expect_scheme:
|
||||
switch (c)
|
||||
{
|
||||
case ':':
|
||||
scheme = std::make_pair(start,i);
|
||||
state = parse_state::expect_first_slash;
|
||||
start = i;
|
||||
break;
|
||||
case '#':
|
||||
userinfo = std::make_pair(start,start);
|
||||
host = std::make_pair(start,start);
|
||||
port = std::make_pair(start,start);
|
||||
path = std::make_pair(start,i);
|
||||
query = std::make_pair(i,i);
|
||||
state = parse_state::expect_fragment;
|
||||
start = i+1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case parse_state::expect_first_slash:
|
||||
switch (c)
|
||||
{
|
||||
case '/':
|
||||
state = parse_state::expect_second_slash;
|
||||
break;
|
||||
default:
|
||||
start = i;
|
||||
state = parse_state::expect_path;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case parse_state::expect_second_slash:
|
||||
switch (c)
|
||||
{
|
||||
case '/':
|
||||
state = parse_state::expect_authority;
|
||||
start = i+1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case parse_state::expect_authority:
|
||||
switch (c)
|
||||
{
|
||||
case '[':
|
||||
state = parse_state::expect_host_ipv6;
|
||||
start = i+1;
|
||||
break;
|
||||
default:
|
||||
state = parse_state::expect_userinfo;
|
||||
start = i;
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case parse_state::expect_host_ipv6:
|
||||
switch (c)
|
||||
{
|
||||
case ']':
|
||||
userinfo = std::make_pair(start,start);
|
||||
host = std::make_pair(start,i);
|
||||
port = std::make_pair(i,i);
|
||||
state = parse_state::expect_path;
|
||||
start = i+1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case parse_state::expect_userinfo:
|
||||
switch (c)
|
||||
{
|
||||
case '@':
|
||||
userinfo = std::make_pair(start,i);
|
||||
state = parse_state::expect_host;
|
||||
start = i+1;
|
||||
break;
|
||||
case ':':
|
||||
userinfo = std::make_pair(start,start);
|
||||
host = std::make_pair(start,i);
|
||||
state = parse_state::expect_port;
|
||||
start = i+1;
|
||||
break;
|
||||
case '/':
|
||||
userinfo = std::make_pair(start,start);
|
||||
host = std::make_pair(start,i);
|
||||
port = std::make_pair(i,i);
|
||||
state = parse_state::expect_path;
|
||||
start = i;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case parse_state::expect_host:
|
||||
switch (c)
|
||||
{
|
||||
case ':':
|
||||
host = std::make_pair(start,i);
|
||||
state = parse_state::expect_port;
|
||||
start = i+1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case parse_state::expect_port:
|
||||
switch (c)
|
||||
{
|
||||
case '/':
|
||||
port = std::make_pair(start,i);
|
||||
state = parse_state::expect_path;
|
||||
start = i;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case parse_state::expect_path:
|
||||
switch (c)
|
||||
{
|
||||
case '?':
|
||||
path = std::make_pair(start,i);
|
||||
state = parse_state::expect_query;
|
||||
start = i+1;
|
||||
break;
|
||||
case '#':
|
||||
path = std::make_pair(start,i);
|
||||
query = std::make_pair(start,start);
|
||||
state = parse_state::expect_fragment;
|
||||
start = i+1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case parse_state::expect_query:
|
||||
switch (c)
|
||||
{
|
||||
case '#':
|
||||
query = std::make_pair(start,i);
|
||||
state = parse_state::expect_fragment;
|
||||
start = i+1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case parse_state::expect_fragment:
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (state)
|
||||
{
|
||||
case parse_state::expect_scheme:
|
||||
userinfo = std::make_pair(start,start);
|
||||
host = std::make_pair(start,start);
|
||||
port = std::make_pair(start,start);
|
||||
path = std::make_pair(start,s.size());
|
||||
break;
|
||||
case parse_state::expect_userinfo:
|
||||
userinfo = std::make_pair(start,start);
|
||||
host = std::make_pair(start,start);
|
||||
port = std::make_pair(start,start);
|
||||
path = std::make_pair(start,s.size());
|
||||
break;
|
||||
case parse_state::expect_path:
|
||||
path = std::make_pair(start,s.size());
|
||||
break;
|
||||
case parse_state::expect_query:
|
||||
query = std::make_pair(start,s.size());
|
||||
break;
|
||||
case parse_state::expect_fragment:
|
||||
fragment = std::make_pair(start,s.size());
|
||||
break;
|
||||
default:
|
||||
JSONCONS_THROW(std::invalid_argument("Invalid uri"));
|
||||
break;
|
||||
}
|
||||
|
||||
return uri(s, scheme, userinfo, host, port, path, query, fragment);
|
||||
}
|
||||
|
||||
static std::string remove_dot_segments(const jsoncons::string_view& input)
|
||||
{
|
||||
std::string result = std::string(input);
|
||||
/*
|
||||
std::size_t pos = 0;
|
||||
while (pos < input.size())
|
||||
{
|
||||
if (input.compare(0, 3, "../"))
|
||||
{
|
||||
network_boost::erase_head(input, 3);
|
||||
} else if (network_boost::starts_with(input, "./")) {
|
||||
network_boost::erase_head(input, 2);
|
||||
} else if (network_boost::starts_with(input, "/./")) {
|
||||
network_boost::replace_head(input, 3, "/");
|
||||
} else if (input == "/.") {
|
||||
network_boost::replace_head(input, 2, "/");
|
||||
} else if (network_boost::starts_with(input, "/../")) {
|
||||
network_boost::erase_head(input, 3);
|
||||
remove_last_segment(result);
|
||||
} else if (network_boost::starts_with(input, "/..")) {
|
||||
network_boost::replace_head(input, 3, "/");
|
||||
remove_last_segment(result);
|
||||
} else if (network_boost::algorithm::all(input, [](char ch) { return ch == '.'; })) {
|
||||
input.clear();
|
||||
}
|
||||
else {
|
||||
int n = (input.front() == '/')? 1 : 0;
|
||||
auto slash = network_boost::find_nth(input, "/", n);
|
||||
result.append(std::begin(input), std::begin(slash));
|
||||
input.erase(std::begin(input), std::begin(slash));
|
||||
}
|
||||
}
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string merge_paths(const uri& base, const uri& relative)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
if (base.path().empty())
|
||||
{
|
||||
result = "/";
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& base_path = base.path();
|
||||
auto last_slash = base_path.rfind('/');
|
||||
result.append(std::string(base_path.substr(0,last_slash+1)));
|
||||
}
|
||||
if (!relative.path().empty())
|
||||
{
|
||||
result.append(relative.path().begin(), relative.path().end());
|
||||
}
|
||||
return remove_dot_segments(jsoncons::string_view(result));
|
||||
}
|
||||
|
||||
static void remove_last_segment(std::string& path)
|
||||
{
|
||||
auto last_slash = path.rfind('/');
|
||||
if (last_slash != std::string::npos)
|
||||
{
|
||||
path.erase(last_slash);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
340
scripts/exe/jsoncons/include/jsoncons/value_converter.hpp
Normal file
340
scripts/exe/jsoncons/include/jsoncons/value_converter.hpp
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CONVERTER_HPP
|
||||
#define JSONCONS_CONVERTER_HPP
|
||||
|
||||
#include <system_error> // std::error_code
|
||||
#include <jsoncons/extension_traits.hpp>
|
||||
#include <jsoncons/byte_string.hpp>
|
||||
#include <jsoncons/json_type.hpp>
|
||||
#include <jsoncons/conv_error.hpp>
|
||||
#include <jsoncons/detail/write_number.hpp> // from_integer
|
||||
#include <jsoncons/tag_type.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
|
||||
template <class From, class Into, class Enable = void>
|
||||
class value_converter
|
||||
{
|
||||
};
|
||||
|
||||
template <class Into>
|
||||
class value_converter_base
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename std::conditional<extension_traits::has_allocator_type<Into>::value, typename Into::allocator_type, std::allocator<char>>::type;
|
||||
private:
|
||||
allocator_type alloc_;
|
||||
|
||||
public:
|
||||
value_converter_base(const allocator_type& alloc = allocator_type())
|
||||
: alloc_(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const noexcept
|
||||
{
|
||||
return alloc_;
|
||||
}
|
||||
};
|
||||
|
||||
// From any byte sequence, Into string
|
||||
template <class From, class Into>
|
||||
class value_converter<From, Into,
|
||||
typename std::enable_if<extension_traits::is_byte_sequence<From>::value && !extension_traits::is_string_or_string_view<From>::value &&
|
||||
extension_traits::is_string<Into>::value>::type> : value_converter_base<Into>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename value_converter_base<Into>::allocator_type;
|
||||
|
||||
template <class CharT = typename Into::value_type>
|
||||
typename std::enable_if<extension_traits::is_narrow_character<CharT>::value,Into>::type
|
||||
convert(const From& value, semantic_tag tag, std::error_code&)
|
||||
{
|
||||
Into s(this->get_allocator());
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::base64:
|
||||
encode_base64(value.begin(), value.end(), s);
|
||||
break;
|
||||
case semantic_tag::base16:
|
||||
encode_base16(value.begin(), value.end(), s);
|
||||
break;
|
||||
default:
|
||||
encode_base64url(value.begin(), value.end(), s);
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
template <class CharT = typename Into::value_type>
|
||||
typename std::enable_if<extension_traits::is_wide_character<CharT>::value,Into>::type
|
||||
convert(const From& value, semantic_tag tag, std::error_code& ec)
|
||||
{
|
||||
std::string s;
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::base64:
|
||||
encode_base64(value.begin(), value.end(), s);
|
||||
break;
|
||||
case semantic_tag::base16:
|
||||
encode_base16(value.begin(), value.end(), s);
|
||||
break;
|
||||
default:
|
||||
encode_base64url(value.begin(), value.end(), s);
|
||||
break;
|
||||
}
|
||||
|
||||
Into ws(this->get_allocator());
|
||||
auto retval = unicode_traits::convert(s.data(), s.size(), ws);
|
||||
if (retval.ec != unicode_traits::conv_errc())
|
||||
{
|
||||
ec = conv_errc::not_wide_char;
|
||||
}
|
||||
|
||||
return ws;
|
||||
}
|
||||
};
|
||||
|
||||
// From byte string, Into byte string
|
||||
template <class From, class Into>
|
||||
class value_converter<From, Into,
|
||||
typename std::enable_if<extension_traits::is_byte_sequence<From>::value &&
|
||||
!extension_traits::is_string_or_string_view<From>::value &&
|
||||
!extension_traits::is_string_or_string_view<Into>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<Into>::value>::type> : value_converter_base<Into>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename value_converter_base<Into>::allocator_type;
|
||||
|
||||
Into convert(const From& value, semantic_tag, std::error_code&)
|
||||
{
|
||||
Into s(value.begin(),value.end(),this->get_allocator());
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
// From string or string_view, Into string, same character type
|
||||
template <class From, class Into>
|
||||
class value_converter<From, Into,
|
||||
typename std::enable_if<extension_traits::is_string_or_string_view<From>::value &&
|
||||
extension_traits::is_string<Into>::value &&
|
||||
std::is_same<typename From::value_type,typename Into::value_type>::value>::type> : value_converter_base<Into>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename value_converter_base<Into>::allocator_type;
|
||||
|
||||
Into convert(const From& value, semantic_tag, std::error_code&)
|
||||
{
|
||||
return Into(value.begin(),value.end(),this->get_allocator());
|
||||
}
|
||||
};
|
||||
|
||||
// From string or string_view, Into string, different character type
|
||||
template <class From, class Into>
|
||||
class value_converter<From, Into,
|
||||
typename std::enable_if<extension_traits::is_string_or_string_view<From>::value &&
|
||||
extension_traits::is_string<Into>::value &&
|
||||
!std::is_same<typename From::value_type,typename Into::value_type>::value>::type> : value_converter_base<Into>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename value_converter_base<Into>::allocator_type;
|
||||
|
||||
Into convert(const From& value, semantic_tag, std::error_code& ec)
|
||||
{
|
||||
Into ws(this->get_allocator());
|
||||
auto retval = unicode_traits::convert(value.data(), value.size(), ws);
|
||||
if (retval.ec != unicode_traits::conv_errc())
|
||||
{
|
||||
ec = conv_errc::not_wide_char;
|
||||
}
|
||||
|
||||
return ws;
|
||||
}
|
||||
};
|
||||
|
||||
// From string, Into byte_string
|
||||
template <class From, class Into>
|
||||
class value_converter<From, Into,
|
||||
typename std::enable_if<extension_traits::is_char_sequence<From>::value &&
|
||||
!extension_traits::is_string_or_string_view<Into>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<Into>::value>::type> : value_converter_base<Into>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename value_converter_base<Into>::allocator_type;
|
||||
|
||||
template <class CharT = typename From::value_type>
|
||||
typename std::enable_if<extension_traits::is_narrow_character<CharT>::value,Into>::type
|
||||
convert(const From& value, semantic_tag tag, std::error_code& ec)
|
||||
{
|
||||
Into bytes(this->get_allocator());
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::base16:
|
||||
{
|
||||
auto res = decode_base16(value.begin(), value.end(), bytes);
|
||||
if (res.ec != conv_errc::success)
|
||||
{
|
||||
ec = conv_errc::not_byte_string;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case semantic_tag::base64:
|
||||
{
|
||||
decode_base64(value.begin(), value.end(), bytes);
|
||||
break;
|
||||
}
|
||||
case semantic_tag::base64url:
|
||||
{
|
||||
decode_base64url(value.begin(), value.end(), bytes);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ec = conv_errc::not_byte_string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
template <class CharT = typename From::value_type>
|
||||
typename std::enable_if<extension_traits::is_wide_character<CharT>::value,Into>::type
|
||||
convert(const From& value, semantic_tag tag, std::error_code& ec)
|
||||
{
|
||||
Into bytes(this->get_allocator());
|
||||
|
||||
std::string s(this->get_allocator());
|
||||
auto retval = unicode_traits::convert(value.data(), value.size(), s);
|
||||
if (retval.ec != unicode_traits::conv_errc())
|
||||
{
|
||||
ec = conv_errc::not_wide_char;
|
||||
}
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::base16:
|
||||
{
|
||||
auto res = decode_base16(s.begin(), s.end(), bytes);
|
||||
if (res.ec != conv_errc::success)
|
||||
{
|
||||
ec = conv_errc::not_byte_string;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case semantic_tag::base64:
|
||||
{
|
||||
decode_base64(s.begin(), s.end(), bytes);
|
||||
break;
|
||||
}
|
||||
case semantic_tag::base64url:
|
||||
{
|
||||
decode_base64url(s.begin(), s.end(), bytes);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ec = conv_errc::not_byte_string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
};
|
||||
|
||||
// From integer, Into string
|
||||
template <class From, class Into>
|
||||
class value_converter<From, Into,
|
||||
typename std::enable_if<extension_traits::is_integer<From>::value &&
|
||||
extension_traits::is_string<Into>::value>::type> : value_converter_base<Into>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename value_converter_base<Into>::allocator_type;
|
||||
|
||||
Into convert(From value, semantic_tag, std::error_code&)
|
||||
{
|
||||
Into s(this->get_allocator());
|
||||
jsoncons::detail::from_integer(value, s);
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
// From integer, Into string
|
||||
template <class From, class Into>
|
||||
class value_converter<From, Into,
|
||||
typename std::enable_if<std::is_floating_point<From>::value &&
|
||||
extension_traits::is_string<Into>::value>::type> : value_converter_base<Into>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename value_converter_base<Into>::allocator_type;
|
||||
|
||||
Into convert(From value, semantic_tag, std::error_code&)
|
||||
{
|
||||
Into s(this->get_allocator());
|
||||
jsoncons::detail::write_double f{float_chars_format::general,0};
|
||||
f(value, s);
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
// From half, Into string
|
||||
template <class Into>
|
||||
class value_converter<half_arg_t, Into,
|
||||
typename std::enable_if<extension_traits::is_string<Into>::value>::type> : value_converter_base<Into>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename value_converter_base<Into>::allocator_type;
|
||||
|
||||
Into convert(uint16_t value, semantic_tag, std::error_code&)
|
||||
{
|
||||
Into s(this->get_allocator());
|
||||
jsoncons::detail::write_double f{float_chars_format::general,0};
|
||||
double x = binary::decode_half(value);
|
||||
f(x, s);
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
// From bool, Into string
|
||||
template <class From, class Into>
|
||||
class value_converter<From, Into,
|
||||
typename std::enable_if<extension_traits::is_bool<From>::value &&
|
||||
extension_traits::is_string<Into>::value>::type> : value_converter_base<Into>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename value_converter_base<Into>::allocator_type;
|
||||
using char_type = typename Into::value_type;
|
||||
|
||||
JSONCONS_CPP14_CONSTEXPR
|
||||
Into convert(From value, semantic_tag, std::error_code&)
|
||||
{
|
||||
constexpr const char_type* true_constant = JSONCONS_CSTRING_CONSTANT(char_type,"true");
|
||||
constexpr const char_type* false_constant = JSONCONS_CSTRING_CONSTANT(char_type,"false");
|
||||
|
||||
return value ? Into(true_constant,4) : Into(false_constant,5);
|
||||
}
|
||||
};
|
||||
|
||||
// From null, Into string
|
||||
template <class Into>
|
||||
class value_converter<null_type, Into, void> : value_converter_base<Into>
|
||||
{
|
||||
public:
|
||||
using allocator_type = typename value_converter_base<Into>::allocator_type;
|
||||
using char_type = typename Into::value_type;
|
||||
|
||||
JSONCONS_CPP14_CONSTEXPR
|
||||
Into convert(semantic_tag, std::error_code&)
|
||||
{
|
||||
constexpr const char_type* null_constant = JSONCONS_CSTRING_CONSTANT(char_type,"null");
|
||||
|
||||
return Into(null_constant,4);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
23
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson.hpp
Normal file
23
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson.hpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BSON_BSON_HPP
|
||||
#define JSONCONS_BSON_BSON_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <type_traits> // std::enable_if
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons_ext/bson/bson_encoder.hpp>
|
||||
#include <jsoncons_ext/bson/bson_reader.hpp>
|
||||
#include <jsoncons_ext/bson/bson_cursor.hpp>
|
||||
#include <jsoncons_ext/bson/encode_bson.hpp>
|
||||
#include <jsoncons_ext/bson/decode_bson.hpp>
|
||||
|
||||
#endif
|
||||
320
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp
Normal file
320
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BSON_BSON_CURSOR_HPP
|
||||
#define JSONCONS_BSON_BSON_CURSOR_HPP
|
||||
|
||||
#include <memory> // std::allocator
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <ios>
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/byte_string.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/staj_cursor.hpp>
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons_ext/bson/bson_parser.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace bson {
|
||||
|
||||
template<class Source=jsoncons::binary_stream_source,class Allocator=std::allocator<char>>
|
||||
class basic_bson_cursor : public basic_staj_cursor<char>, private virtual ser_context
|
||||
{
|
||||
using super_type = basic_staj_cursor<char>;
|
||||
public:
|
||||
using source_type = Source;
|
||||
using char_type = char;
|
||||
using allocator_type = Allocator;
|
||||
private:
|
||||
basic_bson_parser<Source,Allocator> parser_;
|
||||
basic_staj_visitor<char_type> cursor_visitor_;
|
||||
bool eof_;
|
||||
|
||||
// Noncopyable and nonmoveable
|
||||
basic_bson_cursor(const basic_bson_cursor&) = delete;
|
||||
basic_bson_cursor& operator=(const basic_bson_cursor&) = delete;
|
||||
|
||||
public:
|
||||
using string_view_type = string_view;
|
||||
|
||||
template <class Sourceable>
|
||||
basic_bson_cursor(Sourceable&& source,
|
||||
const bson_decode_options& options = bson_decode_options(),
|
||||
const Allocator& alloc = Allocator())
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
cursor_visitor_(accept_all),
|
||||
eof_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
// Constructors that set parse error codes
|
||||
|
||||
template <class Sourceable>
|
||||
basic_bson_cursor(Sourceable&& source,
|
||||
std::error_code& ec)
|
||||
: basic_bson_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
bson_decode_options(),
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_bson_cursor(Sourceable&& source,
|
||||
const bson_decode_options& options,
|
||||
std::error_code& ec)
|
||||
: basic_bson_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
options,
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_bson_cursor(std::allocator_arg_t, const Allocator& alloc,
|
||||
Sourceable&& source,
|
||||
const bson_decode_options& options,
|
||||
std::error_code& ec)
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
cursor_visitor_(accept_all),
|
||||
eof_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
parser_.reset();
|
||||
cursor_visitor_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
void reset(Sourceable&& source)
|
||||
{
|
||||
parser_.reset(std::forward<Sourceable>(source));
|
||||
cursor_visitor_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
void reset(std::error_code& ec)
|
||||
{
|
||||
parser_.reset();
|
||||
cursor_visitor_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
void reset(Sourceable&& source, std::error_code& ec)
|
||||
{
|
||||
parser_.reset(std::forward<Sourceable>(source));
|
||||
cursor_visitor_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
bool done() const override
|
||||
{
|
||||
return parser_.done();
|
||||
}
|
||||
|
||||
void array_expected(std::error_code& ec) override
|
||||
{
|
||||
if (cursor_visitor_.event().event_type() == staj_event_type::begin_object)
|
||||
{
|
||||
parser_.array_expected(cursor_visitor_, ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
super_type::array_expected(ec);
|
||||
}
|
||||
}
|
||||
|
||||
const staj_event& current() const override
|
||||
{
|
||||
return cursor_visitor_.event();
|
||||
}
|
||||
|
||||
void read_to(basic_json_visitor<char_type>& visitor) override
|
||||
{
|
||||
std::error_code ec;
|
||||
read_to(visitor, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read_to(basic_json_visitor<char_type>& visitor,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (send_json_event(cursor_visitor_.event(), visitor, *this, ec))
|
||||
{
|
||||
read_next(visitor, ec);
|
||||
}
|
||||
}
|
||||
|
||||
void next() override
|
||||
{
|
||||
std::error_code ec;
|
||||
next(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void next(std::error_code& ec) override
|
||||
{
|
||||
read_next(ec);
|
||||
}
|
||||
|
||||
const ser_context& context() const override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return eof_;
|
||||
}
|
||||
|
||||
std::size_t line() const override
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const override
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
|
||||
friend
|
||||
staj_filter_view operator|(basic_bson_cursor& cursor,
|
||||
std::function<bool(const staj_event&, const ser_context&)> pred)
|
||||
{
|
||||
return staj_filter_view(cursor, pred);
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
|
||||
template <class Sourceable>
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use pipe syntax for filter")
|
||||
basic_bson_cursor(Sourceable&& source,
|
||||
std::function<bool(const staj_event&, const ser_context&)> filter,
|
||||
std::error_code& ec)
|
||||
: basic_bson_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source), filter, ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use pipe syntax for filter")
|
||||
basic_bson_cursor(Sourceable&& source,
|
||||
std::function<bool(const staj_event&, const ser_context&)> filter,
|
||||
const bson_decode_options& options = bson_decode_options(),
|
||||
const Allocator& alloc = Allocator())
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
cursor_visitor_(filter),
|
||||
eof_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use pipe syntax for filter")
|
||||
basic_bson_cursor(std::allocator_arg_t, const Allocator& alloc,
|
||||
Sourceable&& source,
|
||||
std::function<bool(const staj_event&, const ser_context&)> filter,
|
||||
std::error_code& ec)
|
||||
: parser_(std::forward<Sourceable>(source),alloc),
|
||||
cursor_visitor_(filter),
|
||||
eof_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use read_to(basic_json_visitor<char_type>&)")
|
||||
void read(basic_json_visitor<char_type>& visitor)
|
||||
{
|
||||
read_to(visitor);
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use read_to(basic_json_visitor<char_type>&, std::error_code&)")
|
||||
void read(basic_json_visitor<char_type>& visitor,
|
||||
std::error_code& ec)
|
||||
{
|
||||
read_to(visitor, ec);
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
static bool accept_all(const staj_event&, const ser_context&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void read_next(std::error_code& ec)
|
||||
{
|
||||
parser_.restart();
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
parser_.parse(cursor_visitor_, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
|
||||
void read_next(basic_json_visitor<char_type>& visitor, std::error_code& ec)
|
||||
{
|
||||
parser_.restart();
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
parser_.parse(visitor, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using bson_stream_cursor = basic_bson_cursor<jsoncons::binary_stream_source>;
|
||||
using bson_bytes_cursor = basic_bson_cursor<jsoncons::bytes_source>;
|
||||
|
||||
} // namespace bson
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,865 @@
|
|||
#ifndef JSONCONS_BSON_BSON_DECIMAL128_HPP
|
||||
#define JSONCONS_BSON_BSON_DECIMAL128_HPP
|
||||
|
||||
/*
|
||||
* Implements decimal128_to_chars and decimal128_from_chars
|
||||
*
|
||||
* Based on the libjson functions bson_decimal128_to_string
|
||||
* and bson_decimal128_from_string_w_len, available at
|
||||
* https://github.com/mongodb/mongo-c-driver/blob/master/src/libbson/src/bson/bson-decimal128.h
|
||||
* and https://github.com/mongodb/mongo-c-driver/blob/master/src/libbson/src/bson/bson-decimal128.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2015 MongoDB, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
#include <ctype.h>
|
||||
#include <system_error>
|
||||
#include <algorithm>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
|
||||
namespace jsoncons { namespace bson {
|
||||
|
||||
struct decimal128_to_chars_result
|
||||
{
|
||||
char* ptr;
|
||||
std::errc ec;
|
||||
};
|
||||
|
||||
struct decimal128_from_chars_result
|
||||
{
|
||||
const char* ptr;
|
||||
std::errc ec;
|
||||
};
|
||||
|
||||
/**
|
||||
* BSON_DECIMAL128_STRING:
|
||||
*
|
||||
* The length of a decimal128 string (with null terminator).
|
||||
*
|
||||
* 1 for the sign
|
||||
* 35 for digits and radix
|
||||
* 2 for exponent indicator and sign
|
||||
* 4 for exponent digits
|
||||
*/
|
||||
#define BSON_DECIMAL128_STRING 43
|
||||
|
||||
struct TP1
|
||||
{
|
||||
uint64_t low;
|
||||
uint64_t high;
|
||||
|
||||
constexpr TP1() : low(0), high(0) {}
|
||||
constexpr TP1(uint64_t hi, uint64_t lo) : low(lo), high(hi) {}
|
||||
};
|
||||
struct TP2
|
||||
{
|
||||
uint64_t high;
|
||||
uint64_t low;
|
||||
|
||||
constexpr TP2() : high(0), low(0) {}
|
||||
constexpr TP2(uint64_t hi, uint64_t lo) : high(hi), low(lo) {}
|
||||
};
|
||||
|
||||
typedef std::conditional<
|
||||
jsoncons::endian::native == jsoncons::endian::little,
|
||||
TP1,
|
||||
TP2
|
||||
>::type decimal128_t;
|
||||
|
||||
inline
|
||||
bool operator==(const decimal128_t& lhs, const decimal128_t& rhs)
|
||||
{
|
||||
return lhs.high == rhs.high && lhs.low == rhs.low;
|
||||
}
|
||||
|
||||
inline
|
||||
bool operator!=(const decimal128_t& lhs, const decimal128_t& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
struct decimal128_limits
|
||||
{
|
||||
// The length of a decimal128 string (without null terminator).
|
||||
//
|
||||
// 1 for the sign
|
||||
// 35 for digits and radix
|
||||
// 2 for exponent indicator and sign
|
||||
// 4 for exponent digits
|
||||
static constexpr int buf_size = 42;
|
||||
static constexpr int exponent_max = 6111;
|
||||
static constexpr int exponent_min = -6176;
|
||||
static constexpr int exponent_bias = 6176;
|
||||
static constexpr int max_digits = 34;
|
||||
|
||||
static constexpr decimal128_t nan() {return decimal128_t(0x7c00000000000000ull, 0);}
|
||||
static constexpr decimal128_t infinity() {return decimal128_t(0x7800000000000000ull, 0);}
|
||||
static constexpr decimal128_t neg_infinity() {return decimal128_t(0x7800000000000000ull + 0x8000000000000000ull, 0);}
|
||||
};
|
||||
|
||||
inline
|
||||
bool is_nan(decimal128_t dec) { return dec == decimal128_limits::nan(); }
|
||||
|
||||
inline
|
||||
bool is_inf(decimal128_t dec) { return dec == decimal128_limits::infinity(); }
|
||||
|
||||
inline
|
||||
bool is_neg_inf(decimal128_t dec) { return dec == decimal128_limits::neg_infinity(); }
|
||||
|
||||
/**
|
||||
* bson_uint128_t:
|
||||
*
|
||||
* This struct represents a 128 bit integer.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t parts[4]; /* 32-bit words stored high to low. */
|
||||
} bson_uint128_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t high, low;
|
||||
} bson_uint128_6464_t;
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
*------------------------------------------------------------------------------
|
||||
*
|
||||
* bson_uint128_divide1B --
|
||||
*
|
||||
* This function divides a #bson_uint128_t by 1000000000 (1 billion) and
|
||||
* computes the quotient and remainder.
|
||||
*
|
||||
* The remainder will contain 9 decimal digits for conversion to string.
|
||||
*
|
||||
* @value The #bson_uint128_t operand.
|
||||
* @quotient A pointer to store the #bson_uint128_t quotient.
|
||||
* @rem A pointer to store the #uint64_t remainder.
|
||||
*
|
||||
* Returns:
|
||||
* The quotient at @quotient and the remainder at @rem.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline
|
||||
void bson_uint128_divide1B (bson_uint128_t value, /* IN */
|
||||
bson_uint128_t *quotient, /* OUT */
|
||||
uint32_t *rem) /* OUT */
|
||||
{
|
||||
const uint32_t DIVISOR = 1000 * 1000 * 1000;
|
||||
uint64_t _rem = 0;
|
||||
int i = 0;
|
||||
|
||||
if (!value.parts[0] && !value.parts[1] && !value.parts[2] &&
|
||||
!value.parts[3]) {
|
||||
*quotient = value;
|
||||
*rem = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i <= 3; i++) {
|
||||
_rem <<= 32; /* Adjust remainder to match value of next dividend */
|
||||
_rem += value.parts[i]; /* Add the divided to _rem */
|
||||
value.parts[i] = (uint32_t) (_rem / DIVISOR);
|
||||
_rem %= DIVISOR; /* Store the remainder */
|
||||
}
|
||||
|
||||
*quotient = value;
|
||||
*rem = (uint32_t) _rem;
|
||||
}
|
||||
|
||||
/**
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* mul64x64 --
|
||||
*
|
||||
* This function multiplies two &uint64_t into a &bson_uint128_6464_t.
|
||||
*
|
||||
* Returns:
|
||||
* The product of @left and @right.
|
||||
*
|
||||
* Side Effects:
|
||||
* None.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline
|
||||
void mul_64x64 (uint64_t left, /* IN */
|
||||
uint64_t right, /* IN */
|
||||
bson_uint128_6464_t *product) /* OUT */
|
||||
{
|
||||
uint64_t left_high, left_low, right_high, right_low, product_high,
|
||||
product_mid, product_mid2, product_low;
|
||||
bson_uint128_6464_t rt = {0,0};
|
||||
|
||||
if (!left && !right) {
|
||||
*product = rt;
|
||||
return;
|
||||
}
|
||||
|
||||
left_high = left >> 32;
|
||||
left_low = (uint32_t) left;
|
||||
right_high = right >> 32;
|
||||
right_low = (uint32_t) right;
|
||||
|
||||
product_high = left_high * right_high;
|
||||
product_mid = left_high * right_low;
|
||||
product_mid2 = left_low * right_high;
|
||||
product_low = left_low * right_low;
|
||||
|
||||
product_high += product_mid >> 32;
|
||||
product_mid = (uint32_t) product_mid + product_mid2 + (product_low >> 32);
|
||||
|
||||
product_high = product_high + (product_mid >> 32);
|
||||
product_low = (product_mid << 32) + (uint32_t) product_low;
|
||||
|
||||
rt.high = product_high;
|
||||
rt.low = product_low;
|
||||
*product = rt;
|
||||
}
|
||||
|
||||
/**
|
||||
*------------------------------------------------------------------------------
|
||||
*
|
||||
* dec128_tolower --
|
||||
*
|
||||
* This function converts the ASCII character @c to lowercase. It is locale
|
||||
* insensitive (unlike the stdlib tolower).
|
||||
*
|
||||
* Returns:
|
||||
* The lowercased character.
|
||||
*/
|
||||
|
||||
inline
|
||||
char dec128_tolower (char c)
|
||||
{
|
||||
if (isupper (c)) {
|
||||
c += 32;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
*------------------------------------------------------------------------------
|
||||
*
|
||||
* dec128_istreq --
|
||||
*
|
||||
* This function compares the null-terminated *ASCII* strings @a and @b
|
||||
* for case-insensitive equality.
|
||||
*
|
||||
* Returns:
|
||||
* true if the strings are equal, false otherwise.
|
||||
*/
|
||||
|
||||
inline
|
||||
bool dec128_istreq (const char* a, const char* lasta,
|
||||
const char* b, const char* lastb)
|
||||
{
|
||||
while (!(a == lasta && b == lastb))
|
||||
{
|
||||
// strings are different lengths
|
||||
if (a == lasta || b == lastb)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dec128_tolower (*a) != dec128_tolower (*b)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
/**
|
||||
*------------------------------------------------------------------------------
|
||||
*
|
||||
* decimal128_to_chars --
|
||||
*
|
||||
* This function converts a BID formatted decimal128 value to string,
|
||||
* accepting a &decimal128_t as @dec. The string is stored at @str.
|
||||
*
|
||||
* @dec : The BID formatted decimal to convert.
|
||||
* @str : The output decimal128 string. At least %BSON_DECIMAL128_STRING
|
||||
*characters.
|
||||
*
|
||||
* Returns:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline
|
||||
decimal128_to_chars_result decimal128_to_chars(char* first, char* last, const decimal128_t& dec)
|
||||
{
|
||||
const std::string bson_decimal128_inf = "Infinity";
|
||||
const std::string bson_decimal128_nan = "NaN";
|
||||
|
||||
const uint32_t combination_mask = 0x1f; /* Extract least significant 5 bits */
|
||||
const uint32_t exponent_mask = 0x3fff; /* Extract least significant 14 bits */
|
||||
const uint32_t combination_infinity = 30; /* Value of combination field for Inf */
|
||||
const uint32_t combination_nan = 31; /* Value of combination field for NaN */
|
||||
const uint32_t exponent_bias = 6176; /* decimal128 exponent bias */
|
||||
|
||||
char* str_out = first; /* output pointer in string */
|
||||
char significand_str[35]; /* decoded significand digits */
|
||||
|
||||
/* Note: bits in this routine are referred to starting at 0, */
|
||||
/* from the sign bit, towards the coefficient. */
|
||||
uint32_t high; /* bits 0 - 31 */
|
||||
uint32_t midh; /* bits 32 - 63 */
|
||||
uint32_t midl; /* bits 64 - 95 */
|
||||
uint32_t low; /* bits 96 - 127 */
|
||||
uint32_t combination; /* bits 1 - 5 */
|
||||
uint32_t biased_exponent; /* decoded biased exponent (14 bits) */
|
||||
uint32_t significand_digits = 0; /* the number of significand digits */
|
||||
uint32_t significand[36] = {0}; /* the base-10 digits in the significand */
|
||||
uint32_t *significand_read = significand; /* read pointer into significand */
|
||||
int32_t exponent; /* unbiased exponent */
|
||||
int32_t scientific_exponent; /* the exponent if scientific notation is
|
||||
* used */
|
||||
bool is_zero = false; /* true if the number is zero */
|
||||
|
||||
uint8_t significand_msb; /* the most signifcant significand bits (50-46) */
|
||||
bson_uint128_t
|
||||
significand128; /* temporary storage for significand decoding */
|
||||
|
||||
memset (significand_str, 0, sizeof (significand_str));
|
||||
|
||||
if ((int64_t) dec.high < 0) { /* negative */
|
||||
*(str_out++) = '-';
|
||||
}
|
||||
|
||||
low = (uint32_t) dec.low, midl = (uint32_t) (dec.low >> 32),
|
||||
midh = (uint32_t) dec.high, high = (uint32_t) (dec.high >> 32);
|
||||
|
||||
/* Decode combination field and exponent */
|
||||
combination = (high >> 26) & combination_mask;
|
||||
|
||||
if (JSONCONS_UNLIKELY ((combination >> 3) == 3)) {
|
||||
/* Check for 'special' values */
|
||||
if (combination == combination_infinity) { /* Infinity */
|
||||
if (last-str_out >= static_cast<ptrdiff_t >(bson_decimal128_inf.size()))
|
||||
{
|
||||
std::memcpy(str_out, bson_decimal128_inf.data(), bson_decimal128_inf.size());
|
||||
str_out += bson_decimal128_inf.size();
|
||||
}
|
||||
*str_out = 0;
|
||||
//strcpy_s (str_out, last-str_out, bson_decimal128_inf.c_str());
|
||||
return decimal128_to_chars_result{str_out, std::errc()};
|
||||
} else if (combination == combination_nan) { /* NaN */
|
||||
/* first, not str_out, to erase the sign */
|
||||
str_out = first;
|
||||
if (last-str_out >= static_cast<ptrdiff_t >(bson_decimal128_nan.size()))
|
||||
{
|
||||
std::memcpy(str_out, bson_decimal128_nan.data(), bson_decimal128_nan.size());
|
||||
str_out += bson_decimal128_nan.size();
|
||||
}
|
||||
*str_out = 0;
|
||||
//strcpy_s (first, last-first, bson_decimal128_nan.c_str());
|
||||
/* we don't care about the NaN payload. */
|
||||
return decimal128_to_chars_result{str_out, std::errc()};
|
||||
} else {
|
||||
biased_exponent = (high >> 15) & exponent_mask;
|
||||
significand_msb = 0x8 + ((high >> 14) & 0x1);
|
||||
}
|
||||
} else {
|
||||
significand_msb = (high >> 14) & 0x7;
|
||||
biased_exponent = (high >> 17) & exponent_mask;
|
||||
}
|
||||
|
||||
exponent = biased_exponent - exponent_bias;
|
||||
/* Create string of significand digits */
|
||||
|
||||
/* Convert the 114-bit binary number represented by */
|
||||
/* (high, midh, midl, low) to at most 34 decimal */
|
||||
/* digits through modulo and division. */
|
||||
significand128.parts[0] = (high & 0x3fff) + ((significand_msb & 0xf) << 14);
|
||||
significand128.parts[1] = midh;
|
||||
significand128.parts[2] = midl;
|
||||
significand128.parts[3] = low;
|
||||
|
||||
if (significand128.parts[0] == 0 && significand128.parts[1] == 0 &&
|
||||
significand128.parts[2] == 0 && significand128.parts[3] == 0) {
|
||||
is_zero = true;
|
||||
} else if (significand128.parts[0] >= (1 << 17)) {
|
||||
/* The significand is non-canonical or zero.
|
||||
* In order to preserve compatibility with the densely packed decimal
|
||||
* format, the maximum value for the significand of decimal128 is
|
||||
* 1e34 - 1. If the value is greater than 1e34 - 1, the IEEE 754
|
||||
* standard dictates that the significand is interpreted as zero.
|
||||
*/
|
||||
is_zero = true;
|
||||
} else {
|
||||
for (int k = 3; k >= 0; k--) {
|
||||
uint32_t least_digits = 0;
|
||||
detail::bson_uint128_divide1B (
|
||||
significand128, &significand128, &least_digits);
|
||||
|
||||
/* We now have the 9 least significant digits (in base 2). */
|
||||
/* Convert and output to string. */
|
||||
if (!least_digits) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 8; j >= 0; j--) {
|
||||
significand[k * 9 + j] = least_digits % 10;
|
||||
least_digits /= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Output format options: */
|
||||
/* Scientific - [-]d.dddE(+/-)dd or [-]dE(+/-)dd */
|
||||
/* Regular - ddd.ddd */
|
||||
|
||||
if (is_zero) {
|
||||
significand_digits = 1;
|
||||
*significand_read = 0;
|
||||
} else {
|
||||
significand_digits = 36;
|
||||
while (!(*significand_read)) {
|
||||
significand_digits--;
|
||||
significand_read++;
|
||||
}
|
||||
}
|
||||
|
||||
scientific_exponent = significand_digits - 1 + exponent;
|
||||
|
||||
/* The scientific exponent checks are dictated by the string conversion
|
||||
* specification and are somewhat arbitrary cutoffs.
|
||||
*
|
||||
* We must check exponent > 0, because if this is the case, the number
|
||||
* has trailing zeros. However, we *cannot* output these trailing zeros,
|
||||
* because doing so would change the precision of the value, and would
|
||||
* change stored data if the string converted number is round tripped.
|
||||
*/
|
||||
if (scientific_exponent < -6 || exponent > 0) {
|
||||
/* Scientific format */
|
||||
*(str_out++) = char(*(significand_read++)) + '0';
|
||||
significand_digits--;
|
||||
|
||||
if (significand_digits) {
|
||||
*(str_out++) = '.';
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < significand_digits && (str_out - first) < 36; i++) {
|
||||
*(str_out++) = char(*(significand_read++)) + '0';
|
||||
}
|
||||
/* Exponent */
|
||||
*(str_out++) = 'E';
|
||||
|
||||
std::string s;
|
||||
if (scientific_exponent >= 0) {
|
||||
s.push_back('+');
|
||||
}
|
||||
jsoncons::detail::from_integer(scientific_exponent, s);
|
||||
if (str_out + s.size() < last)
|
||||
{
|
||||
std::memcpy(str_out, s.data(), s.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
return decimal128_to_chars_result{str_out, std::errc::value_too_large};
|
||||
}
|
||||
str_out += s.size();
|
||||
} else {
|
||||
/* Regular format with no decimal place */
|
||||
if (exponent >= 0) {
|
||||
for (std::size_t i = 0; i < significand_digits && (str_out - first) < 36; i++) {
|
||||
*(str_out++) = char(*(significand_read++)) + '0';
|
||||
}
|
||||
} else {
|
||||
int32_t radix_position = significand_digits + exponent;
|
||||
|
||||
if (radix_position > 0) { /* non-zero digits before radix */
|
||||
for (int32_t i = 0;
|
||||
i < radix_position && (str_out < last);
|
||||
i++) {
|
||||
*(str_out++) = char(*(significand_read++)) + '0';
|
||||
}
|
||||
} else { /* leading zero before radix point */
|
||||
*(str_out++) = '0';
|
||||
}
|
||||
|
||||
*(str_out++) = '.';
|
||||
while (radix_position++ < 0) { /* add leading zeros after radix */
|
||||
*(str_out++) = '0';
|
||||
}
|
||||
|
||||
for (std::size_t i = 0;
|
||||
(i < significand_digits - (std::max) (radix_position - 1, 0)) &&
|
||||
(str_out < last);
|
||||
i++) {
|
||||
*(str_out++) = char(*(significand_read++)) + '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
return decimal128_to_chars_result{str_out, std::errc()};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*------------------------------------------------------------------------------
|
||||
*
|
||||
* bson_decimal128_from_string_w_len --
|
||||
*
|
||||
* This function converts @string in the format [+-]ddd[.]ddd[E][+-]dddd to
|
||||
* decimal128. Out of range values are converted to +/-Infinity. Invalid
|
||||
* strings are converted to NaN. @len is the length of the string, or -1
|
||||
* meaning the string is null-terminated.
|
||||
*
|
||||
* If more digits are provided than the available precision allows,
|
||||
* round to the nearest expressable decimal128 with ties going to even will
|
||||
* occur.
|
||||
*
|
||||
* Note: @string must be ASCII only!
|
||||
*
|
||||
* Returns:
|
||||
* true on success, or false on failure. @dec will be NaN if @str was invalid
|
||||
* The &decimal128_t converted from @string at @dec.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
inline
|
||||
decimal128_from_chars_result decimal128_from_chars(const char* first, const char* last, decimal128_t& dec)
|
||||
{
|
||||
const string_view inf_str = "inf";
|
||||
const string_view infinity_str = "infinity";
|
||||
const string_view nan_str = "nan";
|
||||
|
||||
ptrdiff_t len = last - first;
|
||||
|
||||
bson_uint128_6464_t significand = {0,0};
|
||||
|
||||
const char* str_read = first; /* Read pointer for consuming str. */
|
||||
|
||||
/* Parsing state tracking */
|
||||
bool is_negative = false;
|
||||
bool saw_radix = false;
|
||||
bool includes_sign = false; /* True if the input first contains a sign. */
|
||||
bool found_nonzero = false;
|
||||
|
||||
size_t significant_digits = 0; /* Total number of significant digits
|
||||
* (no leading or trailing zero) */
|
||||
size_t ndigits_read = 0; /* Total number of significand digits read */
|
||||
size_t ndigits = 0; /* Total number of digits (no leading zeros) */
|
||||
size_t radix_position = 0; /* The number of the digits after radix */
|
||||
size_t first_nonzero = 0; /* The index of the first non-zero in *str* */
|
||||
|
||||
uint16_t digits[decimal128_limits::max_digits] = {0};
|
||||
uint16_t ndigits_stored = 0; /* The number of digits in digits */
|
||||
uint16_t *digits_insert = digits; /* Insertion pointer for digits */
|
||||
size_t first_digit = 0; /* The index of the first non-zero digit */
|
||||
size_t last_digit = 0; /* The index of the last digit */
|
||||
|
||||
int32_t exponent = 0;
|
||||
uint64_t significand_high = 0; /* The high 17 digits of the significand */
|
||||
uint64_t significand_low = 0; /* The low 17 digits of the significand */
|
||||
uint16_t biased_exponent = 0; /* The biased exponent */
|
||||
|
||||
dec.high = 0;
|
||||
dec.low = 0;
|
||||
|
||||
if (*str_read == '+' || *str_read == '-') {
|
||||
is_negative = *(str_read++) == '-';
|
||||
includes_sign = true;
|
||||
}
|
||||
|
||||
/* Check for Infinity or NaN */
|
||||
if (!isdigit (*str_read) && *str_read != '.') {
|
||||
if (detail::dec128_istreq (str_read, last, inf_str.data(), inf_str.data()+inf_str.length()) ||
|
||||
detail::dec128_istreq (str_read, last, infinity_str.data(), infinity_str.data()+infinity_str.length()))
|
||||
{
|
||||
dec = is_negative ? decimal128_limits::neg_infinity() : decimal128_limits::infinity();
|
||||
return decimal128_from_chars_result{str_read,std::errc()};
|
||||
} else if (detail::dec128_istreq (str_read, last, nan_str.data(), nan_str.data()+nan_str.length())) {
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc()};
|
||||
}
|
||||
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
/* Read digits */
|
||||
while (((isdigit (*str_read) || *str_read == '.')) &&
|
||||
(len == -1 || str_read < first + len)) {
|
||||
if (*str_read == '.') {
|
||||
if (saw_radix) {
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
saw_radix = true;
|
||||
str_read++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ndigits_stored < 34) {
|
||||
if (*str_read != '0' || found_nonzero) {
|
||||
if (!found_nonzero) {
|
||||
first_nonzero = ndigits_read;
|
||||
}
|
||||
|
||||
found_nonzero = true;
|
||||
*(digits_insert++) = *(str_read) - '0'; /* Only store 34 digits */
|
||||
ndigits_stored++;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_nonzero) {
|
||||
ndigits++;
|
||||
}
|
||||
|
||||
if (saw_radix) {
|
||||
radix_position++;
|
||||
}
|
||||
|
||||
ndigits_read++;
|
||||
str_read++;
|
||||
}
|
||||
|
||||
if (saw_radix && !ndigits_read) {
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
/* Read exponent if exists */
|
||||
if (*str_read == 'e' || *str_read == 'E') {
|
||||
++str_read;
|
||||
if (*str_read == '+') {
|
||||
++str_read;
|
||||
}
|
||||
auto result = jsoncons::detail::to_integer(str_read, last - str_read, exponent);
|
||||
if (result.ec != jsoncons::detail::to_integer_errc())
|
||||
{
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
str_read = result.ptr;
|
||||
}
|
||||
|
||||
if ((len == -1 || str_read < first + len) && *str_read) {
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
/* Done reading input. */
|
||||
/* Find first non-zero digit in digits */
|
||||
first_digit = 0;
|
||||
|
||||
if (!ndigits_stored) { /* value is zero */
|
||||
first_digit = 0;
|
||||
last_digit = 0;
|
||||
digits[0] = 0;
|
||||
ndigits = 1;
|
||||
ndigits_stored = 1;
|
||||
significant_digits = 0;
|
||||
} else {
|
||||
last_digit = ndigits_stored - 1;
|
||||
significant_digits = ndigits;
|
||||
/* Mark trailing zeros as non-significant */
|
||||
while (first[first_nonzero + significant_digits - 1 + includes_sign +
|
||||
saw_radix] == '0') {
|
||||
significant_digits--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Normalization of exponent */
|
||||
/* Correct exponent based on radix position, and shift significand as needed
|
||||
*/
|
||||
/* to represent user input */
|
||||
|
||||
/* Overflow prevention */
|
||||
if (exponent <= static_cast<int32_t>(radix_position) && static_cast<int32_t>(radix_position) - exponent > (1 << 14)) {
|
||||
exponent = decimal128_limits::exponent_min;
|
||||
} else {
|
||||
exponent -= static_cast<int32_t>(radix_position);
|
||||
}
|
||||
|
||||
/* Attempt to normalize the exponent */
|
||||
while (exponent > decimal128_limits::exponent_max) {
|
||||
/* Shift exponent to significand and decrease */
|
||||
last_digit++;
|
||||
|
||||
if (last_digit - first_digit > decimal128_limits::max_digits) {
|
||||
/* The exponent is too great to shift into the significand. */
|
||||
if (significant_digits == 0) {
|
||||
/* Value is zero, we are allowed to clamp the exponent. */
|
||||
exponent = decimal128_limits::exponent_max;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Overflow is not permitted, error. */
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
exponent--;
|
||||
}
|
||||
|
||||
while (exponent < decimal128_limits::exponent_min || ndigits_stored < ndigits) {
|
||||
/* Shift last digit */
|
||||
if (last_digit == 0) {
|
||||
/* underflow is not allowed, but zero clamping is */
|
||||
if (significant_digits == 0) {
|
||||
exponent = decimal128_limits::exponent_min;
|
||||
break;
|
||||
}
|
||||
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
if (ndigits_stored < ndigits) {
|
||||
if (first[ndigits - 1 + includes_sign + saw_radix] - '0' != 0 &&
|
||||
significant_digits != 0) {
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
ndigits--; /* adjust to match digits not stored */
|
||||
} else {
|
||||
if (digits[last_digit] != 0) {
|
||||
/* Inexact rounding is not allowed. */
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
|
||||
|
||||
last_digit--; /* adjust to round */
|
||||
}
|
||||
|
||||
if (exponent < decimal128_limits::exponent_max) {
|
||||
exponent++;
|
||||
} else {
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
}
|
||||
|
||||
/* Round */
|
||||
/* We've normalized the exponent, but might still need to round. */
|
||||
if (last_digit - first_digit + 1 < significant_digits) {
|
||||
uint8_t round_digit;
|
||||
|
||||
/* There are non-zero digits after last_digit that need rounding. */
|
||||
/* We round to nearest, ties to even */
|
||||
round_digit =
|
||||
first[first_nonzero + last_digit + includes_sign + saw_radix + 1] -
|
||||
'0';
|
||||
|
||||
if (round_digit != 0) {
|
||||
/* Inexact (non-zero) rounding is not allowed */
|
||||
dec = decimal128_limits::nan();
|
||||
return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode significand */
|
||||
significand_high = 0, /* The high 17 digits of the significand */
|
||||
significand_low = 0; /* The low 17 digits of the significand */
|
||||
|
||||
if (significant_digits == 0) { /* read a zero */
|
||||
significand_high = 0;
|
||||
significand_low = 0;
|
||||
} else if (last_digit - first_digit < 17) {
|
||||
size_t d_idx = first_digit;
|
||||
significand_low = digits[d_idx++];
|
||||
|
||||
for (; d_idx <= last_digit; d_idx++) {
|
||||
significand_low *= 10;
|
||||
significand_low += digits[d_idx];
|
||||
significand_high = 0;
|
||||
}
|
||||
} else {
|
||||
size_t d_idx = first_digit;
|
||||
significand_high = digits[d_idx++];
|
||||
|
||||
for (; d_idx <= last_digit - 17; d_idx++) {
|
||||
significand_high *= 10;
|
||||
significand_high += digits[d_idx];
|
||||
}
|
||||
|
||||
significand_low = digits[d_idx++];
|
||||
|
||||
for (; d_idx <= last_digit; d_idx++) {
|
||||
significand_low *= 10;
|
||||
significand_low += digits[d_idx];
|
||||
}
|
||||
}
|
||||
|
||||
detail::mul_64x64 (significand_high, 100000000000000000ull, &significand);
|
||||
significand.low += significand_low;
|
||||
|
||||
if (significand.low < significand_low) {
|
||||
significand.high += 1;
|
||||
}
|
||||
|
||||
|
||||
biased_exponent = static_cast<uint16_t>(exponent + static_cast<int32_t>(decimal128_limits::exponent_bias));
|
||||
|
||||
/* Encode combination, exponent, and significand. */
|
||||
if ((significand.high >> 49) & 1) {
|
||||
/* Encode '11' into bits 1 to 3 */
|
||||
dec.high |= (0x3ull << 61);
|
||||
dec.high |= (biased_exponent & 0x3fffull) << 47;
|
||||
dec.high |= significand.high & 0x7fffffffffffull;
|
||||
} else {
|
||||
dec.high |= (biased_exponent & 0x3fffull) << 49;
|
||||
dec.high |= significand.high & 0x1ffffffffffffull;
|
||||
}
|
||||
|
||||
dec.low = significand.low;
|
||||
|
||||
/* Encode sign */
|
||||
if (is_negative) {
|
||||
dec.high |= 0x8000000000000000ull;
|
||||
}
|
||||
|
||||
return decimal128_from_chars_result{str_read,std::errc()};
|
||||
}
|
||||
|
||||
} // namespace bson
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
585
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp
Normal file
585
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp
Normal file
|
|
@ -0,0 +1,585 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BSON_BSON_ENCODER_HPP
|
||||
#define JSONCONS_BSON_BSON_ENCODER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <memory>
|
||||
#include <utility> // std::move
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/sink.hpp>
|
||||
#include <jsoncons/detail/parse_number.hpp>
|
||||
#include <jsoncons_ext/bson/bson_type.hpp>
|
||||
#include <jsoncons_ext/bson/bson_error.hpp>
|
||||
#include <jsoncons_ext/bson/bson_options.hpp>
|
||||
#include <jsoncons_ext/bson/bson_decimal128.hpp>
|
||||
#include <jsoncons_ext/bson/bson_oid.hpp>
|
||||
|
||||
namespace jsoncons { namespace bson {
|
||||
|
||||
template<class Sink=jsoncons::binary_stream_sink,class Allocator=std::allocator<char>>
|
||||
class basic_bson_encoder final : public basic_json_visitor<char>
|
||||
{
|
||||
enum class decimal_parse_state { start, integer, exp1, exp2, fraction1 };
|
||||
static constexpr int64_t nanos_in_milli = 1000000;
|
||||
static constexpr int64_t nanos_in_second = 1000000000;
|
||||
static constexpr int64_t millis_in_second = 1000;
|
||||
public:
|
||||
using allocator_type = Allocator;
|
||||
using char_type = char;
|
||||
using typename basic_json_visitor<char>::string_view_type;
|
||||
using sink_type = Sink;
|
||||
|
||||
private:
|
||||
struct stack_item
|
||||
{
|
||||
jsoncons::bson::bson_container_type type_;
|
||||
std::size_t offset_;
|
||||
std::size_t name_offset_;
|
||||
std::size_t index_;
|
||||
|
||||
stack_item(jsoncons::bson::bson_container_type type, std::size_t offset) noexcept
|
||||
: type_(type), offset_(offset), name_offset_(0), index_(0)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t offset() const
|
||||
{
|
||||
return offset_;
|
||||
}
|
||||
|
||||
std::size_t member_offset() const
|
||||
{
|
||||
return name_offset_;
|
||||
}
|
||||
|
||||
void member_offset(std::size_t offset)
|
||||
{
|
||||
name_offset_ = offset;
|
||||
}
|
||||
|
||||
std::size_t next_index()
|
||||
{
|
||||
return index_++;
|
||||
}
|
||||
|
||||
bool is_object() const
|
||||
{
|
||||
return type_ == jsoncons::bson::bson_container_type::document;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
sink_type sink_;
|
||||
const bson_encode_options options_;
|
||||
allocator_type alloc_;
|
||||
|
||||
std::vector<stack_item> stack_;
|
||||
std::vector<uint8_t> buffer_;
|
||||
int nesting_depth_;
|
||||
|
||||
// Noncopyable and nonmoveable
|
||||
basic_bson_encoder(const basic_bson_encoder&) = delete;
|
||||
basic_bson_encoder& operator=(const basic_bson_encoder&) = delete;
|
||||
public:
|
||||
explicit basic_bson_encoder(Sink&& sink,
|
||||
const Allocator& alloc = Allocator())
|
||||
: basic_bson_encoder(std::forward<Sink>(sink),
|
||||
bson_encode_options(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
explicit basic_bson_encoder(Sink&& sink,
|
||||
const bson_encode_options& options,
|
||||
const Allocator& alloc = Allocator())
|
||||
: sink_(std::forward<Sink>(sink)),
|
||||
options_(options),
|
||||
alloc_(alloc),
|
||||
nesting_depth_(0)
|
||||
{
|
||||
}
|
||||
|
||||
~basic_bson_encoder() noexcept
|
||||
{
|
||||
sink_.flush();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
stack_.clear();
|
||||
buffer_.clear();
|
||||
nesting_depth_ = 0;
|
||||
}
|
||||
|
||||
void reset(Sink&& sink)
|
||||
{
|
||||
sink_ = std::move(sink);
|
||||
reset();
|
||||
}
|
||||
|
||||
private:
|
||||
// Implementing methods
|
||||
|
||||
void visit_flush() override
|
||||
{
|
||||
sink_.flush();
|
||||
}
|
||||
|
||||
bool visit_begin_object(semantic_tag, const ser_context&, std::error_code& ec) override
|
||||
{
|
||||
if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth()))
|
||||
{
|
||||
ec = bson_errc::max_nesting_depth_exceeded;
|
||||
return false;
|
||||
}
|
||||
if (buffer_.size() > 0)
|
||||
{
|
||||
if (stack_.empty())
|
||||
{
|
||||
ec = bson_errc::expected_bson_document;
|
||||
return false;
|
||||
}
|
||||
before_value(jsoncons::bson::bson_type::document_type);
|
||||
}
|
||||
|
||||
stack_.emplace_back(jsoncons::bson::bson_container_type::document, buffer_.size());
|
||||
buffer_.insert(buffer_.end(), sizeof(int32_t), 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_end_object(const ser_context&, std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
--nesting_depth_;
|
||||
|
||||
buffer_.push_back(0x00);
|
||||
|
||||
std::size_t length = buffer_.size() - stack_.back().offset();
|
||||
binary::native_to_little(static_cast<uint32_t>(length), buffer_.begin()+stack_.back().offset());
|
||||
|
||||
stack_.pop_back();
|
||||
if (stack_.empty())
|
||||
{
|
||||
for (auto c : buffer_)
|
||||
{
|
||||
sink_.push_back(c);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_begin_array(semantic_tag, const ser_context&, std::error_code& ec) override
|
||||
{
|
||||
if (JSONCONS_UNLIKELY(++nesting_depth_ > options_.max_nesting_depth()))
|
||||
{
|
||||
ec = bson_errc::max_nesting_depth_exceeded;
|
||||
return false;
|
||||
}
|
||||
if (buffer_.size() > 0)
|
||||
{
|
||||
if (stack_.empty())
|
||||
{
|
||||
ec = bson_errc::expected_bson_document;
|
||||
return false;
|
||||
}
|
||||
before_value(jsoncons::bson::bson_type::array_type);
|
||||
}
|
||||
stack_.emplace_back(jsoncons::bson::bson_container_type::array, buffer_.size());
|
||||
buffer_.insert(buffer_.end(), sizeof(int32_t), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_end_array(const ser_context&, std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
--nesting_depth_;
|
||||
|
||||
buffer_.push_back(0x00);
|
||||
|
||||
std::size_t length = buffer_.size() - stack_.back().offset();
|
||||
binary::native_to_little(static_cast<uint32_t>(length), buffer_.begin()+stack_.back().offset());
|
||||
|
||||
stack_.pop_back();
|
||||
if (stack_.empty())
|
||||
{
|
||||
for (auto c : buffer_)
|
||||
{
|
||||
sink_.push_back(c);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_key(const string_view_type& name, const ser_context&, std::error_code&) override
|
||||
{
|
||||
stack_.back().member_offset(buffer_.size());
|
||||
buffer_.push_back(0x00); // reserve space for code
|
||||
for (auto c : name)
|
||||
{
|
||||
buffer_.push_back(c);
|
||||
}
|
||||
buffer_.push_back(0x00);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_null(semantic_tag tag, const ser_context&, std::error_code& ec) override
|
||||
{
|
||||
if (stack_.empty())
|
||||
{
|
||||
ec = bson_errc::expected_bson_document;
|
||||
return false;
|
||||
}
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::undefined:
|
||||
before_value(jsoncons::bson::bson_type::undefined_type);
|
||||
break;
|
||||
default:
|
||||
before_value(jsoncons::bson::bson_type::null_type);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_bool(bool val, semantic_tag, const ser_context&, std::error_code& ec) override
|
||||
{
|
||||
if (stack_.empty())
|
||||
{
|
||||
ec = bson_errc::expected_bson_document;
|
||||
return false;
|
||||
}
|
||||
before_value(jsoncons::bson::bson_type::bool_type);
|
||||
if (val)
|
||||
{
|
||||
buffer_.push_back(0x01);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_.push_back(0x00);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_string(const string_view_type& sv, semantic_tag tag, const ser_context&, std::error_code& ec) override
|
||||
{
|
||||
if (stack_.empty())
|
||||
{
|
||||
ec = bson_errc::expected_bson_document;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::float128:
|
||||
{
|
||||
before_value(jsoncons::bson::bson_type::decimal128_type);
|
||||
decimal128_t dec;
|
||||
auto rc = decimal128_from_chars(sv.data(), sv.data()+sv.size(), dec);
|
||||
if (rc.ec != std::errc())
|
||||
{
|
||||
ec = bson_errc::invalid_decimal128_string;
|
||||
return false;
|
||||
}
|
||||
binary::native_to_little(dec.low,std::back_inserter(buffer_));
|
||||
binary::native_to_little(dec.high,std::back_inserter(buffer_));
|
||||
break;
|
||||
}
|
||||
case semantic_tag::id:
|
||||
{
|
||||
before_value(jsoncons::bson::bson_type::object_id_type);
|
||||
oid_t oid(sv);
|
||||
for (auto b : oid)
|
||||
{
|
||||
buffer_.push_back(b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case semantic_tag::regex:
|
||||
{
|
||||
before_value(jsoncons::bson::bson_type::regex_type);
|
||||
std::size_t first = sv.find_first_of('/');
|
||||
std::size_t last = sv.find_last_of('/');
|
||||
if (first == string_view::npos || last == string_view::npos || first == last)
|
||||
{
|
||||
ec = bson_errc::invalid_regex_string;
|
||||
return false;
|
||||
}
|
||||
string_view regex = sv.substr(first+1,last-1);
|
||||
for (auto c : regex)
|
||||
{
|
||||
buffer_.push_back(c);
|
||||
}
|
||||
buffer_.push_back(0x00);
|
||||
string_view options = sv.substr(last+1);
|
||||
for (auto c : options)
|
||||
{
|
||||
buffer_.push_back(c);
|
||||
}
|
||||
buffer_.push_back(0x00);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::code:
|
||||
before_value(jsoncons::bson::bson_type::javascript_type);
|
||||
break;
|
||||
default:
|
||||
before_value(jsoncons::bson::bson_type::string_type);
|
||||
break;
|
||||
}
|
||||
std::size_t offset = buffer_.size();
|
||||
buffer_.insert(buffer_.end(), sizeof(int32_t), 0);
|
||||
std::size_t string_offset = buffer_.size();
|
||||
auto sink = unicode_traits::validate(sv.data(), sv.size());
|
||||
if (sink.ec != unicode_traits::conv_errc())
|
||||
{
|
||||
ec = bson_errc::invalid_utf8_text_string;
|
||||
return false;
|
||||
}
|
||||
for (auto c : sv)
|
||||
{
|
||||
buffer_.push_back(c);
|
||||
}
|
||||
buffer_.push_back(0x00);
|
||||
std::size_t length = buffer_.size() - string_offset;
|
||||
binary::native_to_little(static_cast<uint32_t>(length), buffer_.begin()+offset);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_byte_string(const byte_string_view& b,
|
||||
semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (stack_.empty())
|
||||
{
|
||||
ec = bson_errc::expected_bson_document;
|
||||
return false;
|
||||
}
|
||||
before_value(jsoncons::bson::bson_type::binary_type);
|
||||
|
||||
std::size_t offset = buffer_.size();
|
||||
buffer_.insert(buffer_.end(), sizeof(int32_t), 0);
|
||||
std::size_t string_offset = buffer_.size();
|
||||
|
||||
buffer_.push_back(0x80); // default subtype
|
||||
|
||||
for (auto c : b)
|
||||
{
|
||||
buffer_.push_back(c);
|
||||
}
|
||||
std::size_t length = buffer_.size() - string_offset - 1;
|
||||
binary::native_to_little(static_cast<uint32_t>(length), buffer_.begin()+offset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_byte_string(const byte_string_view& b,
|
||||
uint64_t ext_tag,
|
||||
const ser_context&,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (stack_.empty())
|
||||
{
|
||||
ec = bson_errc::expected_bson_document;
|
||||
return false;
|
||||
}
|
||||
before_value(jsoncons::bson::bson_type::binary_type);
|
||||
|
||||
std::size_t offset = buffer_.size();
|
||||
buffer_.insert(buffer_.end(), sizeof(int32_t), 0);
|
||||
std::size_t string_offset = buffer_.size();
|
||||
|
||||
buffer_.push_back(static_cast<uint8_t>(ext_tag)); // default subtype
|
||||
|
||||
for (auto c : b)
|
||||
{
|
||||
buffer_.push_back(c);
|
||||
}
|
||||
std::size_t length = buffer_.size() - string_offset - 1;
|
||||
binary::native_to_little(static_cast<uint32_t>(length), buffer_.begin()+offset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_int64(int64_t val,
|
||||
semantic_tag tag,
|
||||
const ser_context&,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
static constexpr int64_t min_value_div_1000 = (std::numeric_limits<int64_t>::min)() / 1000;
|
||||
static constexpr int64_t max_value_div_1000 = (std::numeric_limits<int64_t>::max)() / 1000;
|
||||
if (stack_.empty())
|
||||
{
|
||||
ec = bson_errc::expected_bson_document;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::epoch_second:
|
||||
if (val < min_value_div_1000)
|
||||
{
|
||||
ec = bson_errc::datetime_too_small;
|
||||
return false;
|
||||
}
|
||||
if (val > max_value_div_1000)
|
||||
{
|
||||
ec = bson_errc::datetime_too_large;
|
||||
return false;
|
||||
}
|
||||
before_value(jsoncons::bson::bson_type::datetime_type);
|
||||
binary::native_to_little(val*millis_in_second,std::back_inserter(buffer_));
|
||||
return true;
|
||||
case semantic_tag::epoch_milli:
|
||||
before_value(jsoncons::bson::bson_type::datetime_type);
|
||||
binary::native_to_little(val,std::back_inserter(buffer_));
|
||||
return true;
|
||||
case semantic_tag::epoch_nano:
|
||||
before_value(jsoncons::bson::bson_type::datetime_type);
|
||||
if (val != 0)
|
||||
{
|
||||
val /= nanos_in_milli;
|
||||
}
|
||||
binary::native_to_little(static_cast<int64_t>(val),std::back_inserter(buffer_));
|
||||
return true;
|
||||
default:
|
||||
{
|
||||
if (val >= (std::numeric_limits<int32_t>::lowest)() && val <= (std::numeric_limits<int32_t>::max)())
|
||||
{
|
||||
before_value(jsoncons::bson::bson_type::int32_type);
|
||||
binary::native_to_little(static_cast<uint32_t>(val),std::back_inserter(buffer_));
|
||||
}
|
||||
else
|
||||
{
|
||||
before_value(jsoncons::bson::bson_type::int64_type);
|
||||
binary::native_to_little(static_cast<int64_t>(val),std::back_inserter(buffer_));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool visit_uint64(uint64_t val,
|
||||
semantic_tag tag,
|
||||
const ser_context&,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
static constexpr uint64_t max_value_div_1000 = (std::numeric_limits<uint64_t>::max)() / 1000;
|
||||
if (stack_.empty())
|
||||
{
|
||||
ec = bson_errc::expected_bson_document;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::epoch_second:
|
||||
if (val > max_value_div_1000)
|
||||
{
|
||||
ec = bson_errc::datetime_too_large;
|
||||
return false;
|
||||
}
|
||||
before_value(jsoncons::bson::bson_type::datetime_type);
|
||||
binary::native_to_little(static_cast<int64_t>(val*millis_in_second),std::back_inserter(buffer_));
|
||||
return true;
|
||||
case semantic_tag::epoch_milli:
|
||||
before_value(jsoncons::bson::bson_type::datetime_type);
|
||||
binary::native_to_little(static_cast<int64_t>(val),std::back_inserter(buffer_));
|
||||
return true;
|
||||
case semantic_tag::epoch_nano:
|
||||
before_value(jsoncons::bson::bson_type::datetime_type);
|
||||
if (val != 0)
|
||||
{
|
||||
val /= nanos_in_second;
|
||||
}
|
||||
binary::native_to_little(static_cast<int64_t>(val),std::back_inserter(buffer_));
|
||||
return true;
|
||||
default:
|
||||
{
|
||||
bool more;
|
||||
if (val <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
|
||||
{
|
||||
before_value(jsoncons::bson::bson_type::int32_type);
|
||||
binary::native_to_little(static_cast<uint32_t>(val),std::back_inserter(buffer_));
|
||||
more = true;
|
||||
}
|
||||
else if (val <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
|
||||
{
|
||||
before_value(jsoncons::bson::bson_type::int64_type);
|
||||
binary::native_to_little(static_cast<uint64_t>(val),std::back_inserter(buffer_));
|
||||
more = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = bson_errc::number_too_large;
|
||||
more = false;
|
||||
}
|
||||
return more;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool visit_double(double val,
|
||||
semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (stack_.empty())
|
||||
{
|
||||
ec = bson_errc::expected_bson_document;
|
||||
return false;
|
||||
}
|
||||
before_value(jsoncons::bson::bson_type::double_type);
|
||||
binary::native_to_little(val,std::back_inserter(buffer_));
|
||||
return true;
|
||||
}
|
||||
|
||||
void before_value(uint8_t code)
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
if (stack_.back().is_object())
|
||||
{
|
||||
buffer_[stack_.back().member_offset()] = code;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_.push_back(code);
|
||||
std::string name = std::to_string(stack_.back().next_index());
|
||||
buffer_.insert(buffer_.end(), name.begin(), name.end());
|
||||
buffer_.push_back(0x00);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using bson_stream_encoder = basic_bson_encoder<jsoncons::binary_stream_sink>;
|
||||
using bson_bytes_encoder = basic_bson_encoder<jsoncons::bytes_sink<std::vector<uint8_t>>>;
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
template<class Sink=jsoncons::binary_stream_sink>
|
||||
using basic_bson_serializer = basic_bson_encoder<Sink>;
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use bson_stream_encoder") typedef bson_stream_encoder bson_encoder;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use bson_stream_encoder") typedef bson_stream_encoder bson_serializer;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use bson_bytes_encoder") typedef bson_bytes_encoder bson_buffer_serializer;
|
||||
|
||||
#endif
|
||||
|
||||
}}
|
||||
#endif
|
||||
103
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_error.hpp
Normal file
103
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_error.hpp
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BSON_BSON_ERROR_HPP
|
||||
#define JSONCONS_BSON_BSON_ERROR_HPP
|
||||
|
||||
#include <system_error>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
|
||||
namespace jsoncons { namespace bson {
|
||||
|
||||
enum class bson_errc
|
||||
{
|
||||
success = 0,
|
||||
unexpected_eof = 1,
|
||||
source_error,
|
||||
invalid_utf8_text_string,
|
||||
max_nesting_depth_exceeded,
|
||||
string_length_is_non_positive,
|
||||
length_is_negative,
|
||||
number_too_large,
|
||||
invalid_decimal128_string,
|
||||
datetime_too_small,
|
||||
datetime_too_large,
|
||||
expected_bson_document,
|
||||
invalid_regex_string,
|
||||
size_mismatch,
|
||||
unknown_type
|
||||
};
|
||||
|
||||
class bson_error_category_impl
|
||||
: public std::error_category
|
||||
{
|
||||
public:
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "jsoncons/bson";
|
||||
}
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<bson_errc>(ev))
|
||||
{
|
||||
case bson_errc::unexpected_eof:
|
||||
return "Unexpected end of file";
|
||||
case bson_errc::source_error:
|
||||
return "Source error";
|
||||
case bson_errc::invalid_utf8_text_string:
|
||||
return "Illegal UTF-8 encoding in text string";
|
||||
case bson_errc::max_nesting_depth_exceeded:
|
||||
return "Data item nesting exceeds limit in options";
|
||||
case bson_errc::string_length_is_non_positive:
|
||||
return "Request for the length of a string returned a non-positive result";
|
||||
case bson_errc::length_is_negative:
|
||||
return "Request for the length of a binary returned a negative result";
|
||||
case bson_errc::unknown_type:
|
||||
return "An unknown type was found in the stream";
|
||||
case bson_errc::number_too_large:
|
||||
return "Number too large";
|
||||
case bson_errc::invalid_decimal128_string:
|
||||
return "Invalid decimal128 string";
|
||||
case bson_errc::datetime_too_large:
|
||||
return "datetime too large";
|
||||
case bson_errc::datetime_too_small:
|
||||
return "datetime too small";
|
||||
case bson_errc::expected_bson_document:
|
||||
return "Expected BSON document";
|
||||
case bson_errc::invalid_regex_string:
|
||||
return "Invalid regex string";
|
||||
case bson_errc::size_mismatch:
|
||||
return "Document or array size doesn't match bytes read";
|
||||
default:
|
||||
return "Unknown BSON parser error";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
const std::error_category& bson_error_category()
|
||||
{
|
||||
static bson_error_category_impl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
inline
|
||||
std::error_code make_error_code(bson_errc result)
|
||||
{
|
||||
return std::error_code(static_cast<int>(result),bson_error_category());
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct is_error_code_enum<jsoncons::bson::bson_errc> : public true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
245
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp
Normal file
245
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
#ifndef JSONCONS_BSON_BSON_OID_HPP
|
||||
#define JSONCONS_BSON_BSON_OID_HPP
|
||||
|
||||
/*
|
||||
* Implements class oid_t and non member function bson_oid_to_string
|
||||
*
|
||||
* Based on the libjson functions bson_oid_to_string
|
||||
* and bson_oid_init_from_string_unsafe , available at
|
||||
* https://github.com/mongodb/mongo-c-driver/blob/master/src/libbson/src/bson/bson-oid.h
|
||||
* and https://github.com/mongodb/mongo-c-driver/blob/master/src/libbson/src/bson/bson-oid.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2015 MongoDB, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctype.h>
|
||||
#include <system_error>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <array>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
|
||||
namespace jsoncons { namespace bson {
|
||||
|
||||
class oid_t
|
||||
{
|
||||
std::array<uint8_t,12> bytes_;
|
||||
public:
|
||||
using iterator = std::array<uint8_t,12>::iterator;
|
||||
using const_iterator = std::array<uint8_t,12>::const_iterator;
|
||||
|
||||
oid_t(const std::array<uint8_t,12>& bytes)
|
||||
: bytes_(bytes)
|
||||
{
|
||||
}
|
||||
oid_t(uint8_t data[12])
|
||||
{
|
||||
std::memcpy(bytes_.data(),data,12);
|
||||
}
|
||||
|
||||
oid_t(const string_view& str)
|
||||
{
|
||||
for (std::size_t i = 0; i < bytes_.size(); i++)
|
||||
{
|
||||
bytes_[i] = ((parse_hex_char (str[2 * i]) << 4) |
|
||||
(parse_hex_char (str[2 * i + 1])));
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* data() const
|
||||
{
|
||||
return bytes_.data();
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return bytes_.size();
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return bytes_.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return bytes_.end();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return bytes_.begin();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return bytes_.end();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static uint8_t parse_hex_char (char hex)
|
||||
{
|
||||
switch (hex) {
|
||||
case '0':
|
||||
return 0;
|
||||
case '1':
|
||||
return 1;
|
||||
case '2':
|
||||
return 2;
|
||||
case '3':
|
||||
return 3;
|
||||
case '4':
|
||||
return 4;
|
||||
case '5':
|
||||
return 5;
|
||||
case '6':
|
||||
return 6;
|
||||
case '7':
|
||||
return 7;
|
||||
case '8':
|
||||
return 8;
|
||||
case '9':
|
||||
return 9;
|
||||
case 'a':
|
||||
case 'A':
|
||||
return 0xa;
|
||||
case 'b':
|
||||
case 'B':
|
||||
return 0xb;
|
||||
case 'c':
|
||||
case 'C':
|
||||
return 0xc;
|
||||
case 'd':
|
||||
case 'D':
|
||||
return 0xd;
|
||||
case 'e':
|
||||
case 'E':
|
||||
return 0xe;
|
||||
case 'f':
|
||||
case 'F':
|
||||
return 0xf;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline
|
||||
const uint16_t* get_hex_char_pairs(std::true_type) // big endian
|
||||
{
|
||||
static const uint16_t hex_char_pairs[] = {
|
||||
12336, 12337, 12338, 12339, 12340, 12341, 12342, 12343, 12344, 12345, 12385,
|
||||
12386, 12387, 12388, 12389, 12390, 12592, 12593, 12594, 12595, 12596, 12597,
|
||||
12598, 12599, 12600, 12601, 12641, 12642, 12643, 12644, 12645, 12646, 12848,
|
||||
12849, 12850, 12851, 12852, 12853, 12854, 12855, 12856, 12857, 12897, 12898,
|
||||
12899, 12900, 12901, 12902, 13104, 13105, 13106, 13107, 13108, 13109, 13110,
|
||||
13111, 13112, 13113, 13153, 13154, 13155, 13156, 13157, 13158, 13360, 13361,
|
||||
13362, 13363, 13364, 13365, 13366, 13367, 13368, 13369, 13409, 13410, 13411,
|
||||
13412, 13413, 13414, 13616, 13617, 13618, 13619, 13620, 13621, 13622, 13623,
|
||||
13624, 13625, 13665, 13666, 13667, 13668, 13669, 13670, 13872, 13873, 13874,
|
||||
13875, 13876, 13877, 13878, 13879, 13880, 13881, 13921, 13922, 13923, 13924,
|
||||
13925, 13926, 14128, 14129, 14130, 14131, 14132, 14133, 14134, 14135, 14136,
|
||||
14137, 14177, 14178, 14179, 14180, 14181, 14182, 14384, 14385, 14386, 14387,
|
||||
14388, 14389, 14390, 14391, 14392, 14393, 14433, 14434, 14435, 14436, 14437,
|
||||
14438, 14640, 14641, 14642, 14643, 14644, 14645, 14646, 14647, 14648, 14649,
|
||||
14689, 14690, 14691, 14692, 14693, 14694, 24880, 24881, 24882, 24883, 24884,
|
||||
24885, 24886, 24887, 24888, 24889, 24929, 24930, 24931, 24932, 24933, 24934,
|
||||
25136, 25137, 25138, 25139, 25140, 25141, 25142, 25143, 25144, 25145, 25185,
|
||||
25186, 25187, 25188, 25189, 25190, 25392, 25393, 25394, 25395, 25396, 25397,
|
||||
25398, 25399, 25400, 25401, 25441, 25442, 25443, 25444, 25445, 25446, 25648,
|
||||
25649, 25650, 25651, 25652, 25653, 25654, 25655, 25656, 25657, 25697, 25698,
|
||||
25699, 25700, 25701, 25702, 25904, 25905, 25906, 25907, 25908, 25909, 25910,
|
||||
25911, 25912, 25913, 25953, 25954, 25955, 25956, 25957, 25958, 26160, 26161,
|
||||
26162, 26163, 26164, 26165, 26166, 26167, 26168, 26169, 26209, 26210, 26211,
|
||||
26212, 26213, 26214};
|
||||
|
||||
return hex_char_pairs;
|
||||
}
|
||||
|
||||
inline
|
||||
const uint16_t* get_hex_char_pairs(std::false_type) // little endian
|
||||
{
|
||||
static const uint16_t hex_char_pairs[] = {
|
||||
12336, 12592, 12848, 13104, 13360, 13616, 13872, 14128, 14384, 14640, 24880,
|
||||
25136, 25392, 25648, 25904, 26160, 12337, 12593, 12849, 13105, 13361, 13617,
|
||||
13873, 14129, 14385, 14641, 24881, 25137, 25393, 25649, 25905, 26161, 12338,
|
||||
12594, 12850, 13106, 13362, 13618, 13874, 14130, 14386, 14642, 24882, 25138,
|
||||
25394, 25650, 25906, 26162, 12339, 12595, 12851, 13107, 13363, 13619, 13875,
|
||||
14131, 14387, 14643, 24883, 25139, 25395, 25651, 25907, 26163, 12340, 12596,
|
||||
12852, 13108, 13364, 13620, 13876, 14132, 14388, 14644, 24884, 25140, 25396,
|
||||
25652, 25908, 26164, 12341, 12597, 12853, 13109, 13365, 13621, 13877, 14133,
|
||||
14389, 14645, 24885, 25141, 25397, 25653, 25909, 26165, 12342, 12598, 12854,
|
||||
13110, 13366, 13622, 13878, 14134, 14390, 14646, 24886, 25142, 25398, 25654,
|
||||
25910, 26166, 12343, 12599, 12855, 13111, 13367, 13623, 13879, 14135, 14391,
|
||||
14647, 24887, 25143, 25399, 25655, 25911, 26167, 12344, 12600, 12856, 13112,
|
||||
13368, 13624, 13880, 14136, 14392, 14648, 24888, 25144, 25400, 25656, 25912,
|
||||
26168, 12345, 12601, 12857, 13113, 13369, 13625, 13881, 14137, 14393, 14649,
|
||||
24889, 25145, 25401, 25657, 25913, 26169, 12385, 12641, 12897, 13153, 13409,
|
||||
13665, 13921, 14177, 14433, 14689, 24929, 25185, 25441, 25697, 25953, 26209,
|
||||
12386, 12642, 12898, 13154, 13410, 13666, 13922, 14178, 14434, 14690, 24930,
|
||||
25186, 25442, 25698, 25954, 26210, 12387, 12643, 12899, 13155, 13411, 13667,
|
||||
13923, 14179, 14435, 14691, 24931, 25187, 25443, 25699, 25955, 26211, 12388,
|
||||
12644, 12900, 13156, 13412, 13668, 13924, 14180, 14436, 14692, 24932, 25188,
|
||||
25444, 25700, 25956, 26212, 12389, 12645, 12901, 13157, 13413, 13669, 13925,
|
||||
14181, 14437, 14693, 24933, 25189, 25445, 25701, 25957, 26213, 12390, 12646,
|
||||
12902, 13158, 13414, 13670, 13926, 14182, 14438, 14694, 24934, 25190, 25446,
|
||||
25702, 25958, 26214};
|
||||
|
||||
return hex_char_pairs;
|
||||
}
|
||||
|
||||
inline
|
||||
void init_hex_char_pairs(const oid_t& oid, uint16_t* data)
|
||||
{
|
||||
const uint8_t* bytes = oid.data();
|
||||
const uint16_t* gHexCharPairs = get_hex_char_pairs(std::integral_constant<bool, jsoncons::endian::native == jsoncons::endian::big>());
|
||||
|
||||
data[0] = gHexCharPairs[bytes[0]];
|
||||
data[1] = gHexCharPairs[bytes[1]];
|
||||
data[2] = gHexCharPairs[bytes[2]];
|
||||
data[3] = gHexCharPairs[bytes[3]];
|
||||
data[4] = gHexCharPairs[bytes[4]];
|
||||
data[5] = gHexCharPairs[bytes[5]];
|
||||
data[6] = gHexCharPairs[bytes[6]];
|
||||
data[7] = gHexCharPairs[bytes[7]];
|
||||
data[8] = gHexCharPairs[bytes[8]];
|
||||
data[9] = gHexCharPairs[bytes[9]];
|
||||
data[10] = gHexCharPairs[bytes[10]];
|
||||
data[11] = gHexCharPairs[bytes[11]];
|
||||
}
|
||||
|
||||
} // namsepace detail
|
||||
|
||||
template <typename StringT>
|
||||
inline
|
||||
void to_string(const oid_t& oid, StringT& s)
|
||||
{
|
||||
s.resize(24);
|
||||
detail::init_hex_char_pairs(oid, reinterpret_cast<uint16_t*>(&s[0]));
|
||||
}
|
||||
|
||||
} // namespace bson
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BSON_BSON_OPTIONS_HPP
|
||||
#define JSONCONS_BSON_BSON_OPTIONS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <cwchar>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons_ext/bson/bson_type.hpp>
|
||||
|
||||
namespace jsoncons { namespace bson {
|
||||
|
||||
class bson_options;
|
||||
|
||||
class bson_options_common
|
||||
{
|
||||
friend class bson_options;
|
||||
|
||||
int max_nesting_depth_;
|
||||
protected:
|
||||
virtual ~bson_options_common() = default;
|
||||
|
||||
bson_options_common()
|
||||
: max_nesting_depth_(1024)
|
||||
{
|
||||
}
|
||||
|
||||
bson_options_common(const bson_options_common&) = default;
|
||||
bson_options_common& operator=(const bson_options_common&) = default;
|
||||
bson_options_common(bson_options_common&&) = default;
|
||||
bson_options_common& operator=(bson_options_common&&) = default;
|
||||
public:
|
||||
int max_nesting_depth() const
|
||||
{
|
||||
return max_nesting_depth_;
|
||||
}
|
||||
};
|
||||
|
||||
class bson_decode_options : public virtual bson_options_common
|
||||
{
|
||||
friend class bson_options;
|
||||
public:
|
||||
bson_decode_options()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class bson_encode_options : public virtual bson_options_common
|
||||
{
|
||||
friend class bson_options;
|
||||
public:
|
||||
bson_encode_options()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class bson_options final : public bson_decode_options, public bson_encode_options
|
||||
{
|
||||
public:
|
||||
using bson_options_common::max_nesting_depth;
|
||||
|
||||
bson_options& max_nesting_depth(int value)
|
||||
{
|
||||
this->max_nesting_depth_ = value;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
#endif
|
||||
645
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp
Normal file
645
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp
Normal file
|
|
@ -0,0 +1,645 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BSON_BSON_PARSER_HPP
|
||||
#define JSONCONS_BSON_BSON_PARSER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <utility> // std::move
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons_ext/bson/bson_type.hpp>
|
||||
#include <jsoncons_ext/bson/bson_decimal128.hpp>
|
||||
#include <jsoncons_ext/bson/bson_error.hpp>
|
||||
#include <jsoncons_ext/bson/bson_options.hpp>
|
||||
#include <jsoncons_ext/bson/bson_oid.hpp>
|
||||
|
||||
namespace jsoncons { namespace bson {
|
||||
|
||||
enum class parse_mode {root,accept,document,array,value};
|
||||
|
||||
struct parse_state
|
||||
{
|
||||
parse_mode mode;
|
||||
std::size_t length;
|
||||
std::size_t pos;
|
||||
uint8_t type;
|
||||
std::size_t index;
|
||||
|
||||
parse_state(parse_mode mode_, std::size_t length_, std::size_t pos_, uint8_t type_ = 0) noexcept
|
||||
: mode(mode_), length(length_), pos(pos_), type(type_), index(0)
|
||||
{
|
||||
}
|
||||
|
||||
parse_state(const parse_state&) = default;
|
||||
parse_state(parse_state&&) = default;
|
||||
parse_state& operator=(const parse_state&) = default;
|
||||
parse_state& operator=(parse_state&&) = default;
|
||||
};
|
||||
|
||||
template <class Source,class Allocator=std::allocator<char>>
|
||||
class basic_bson_parser : public ser_context
|
||||
{
|
||||
using char_type = char;
|
||||
using char_traits_type = std::char_traits<char>;
|
||||
using temp_allocator_type = Allocator;
|
||||
using char_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<char_type>;
|
||||
using byte_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<uint8_t>;
|
||||
using parse_state_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<parse_state>;
|
||||
|
||||
Source source_;
|
||||
bson_decode_options options_;
|
||||
bool more_;
|
||||
bool done_;
|
||||
std::vector<uint8_t,byte_allocator_type> bytes_buffer_;
|
||||
std::basic_string<char,std::char_traits<char>,char_allocator_type> text_buffer_;
|
||||
std::vector<parse_state,parse_state_allocator_type> state_stack_;
|
||||
public:
|
||||
template <class Sourceable>
|
||||
basic_bson_parser(Sourceable&& source,
|
||||
const bson_decode_options& options = bson_decode_options(),
|
||||
const Allocator alloc = Allocator())
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
options_(options),
|
||||
more_(true),
|
||||
done_(false),
|
||||
text_buffer_(alloc),
|
||||
state_stack_(alloc)
|
||||
{
|
||||
state_stack_.emplace_back(parse_mode::root,0,0);
|
||||
}
|
||||
|
||||
void restart()
|
||||
{
|
||||
more_ = true;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
more_ = true;
|
||||
done_ = false;
|
||||
bytes_buffer_.clear();
|
||||
text_buffer_.clear();
|
||||
state_stack_.clear();
|
||||
state_stack_.emplace_back(parse_mode::root,0,0);
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
void reset(Sourceable&& source)
|
||||
{
|
||||
source_ = std::forward<Sourceable>(source);
|
||||
reset();
|
||||
}
|
||||
|
||||
bool done() const
|
||||
{
|
||||
return done_;
|
||||
}
|
||||
|
||||
bool stopped() const
|
||||
{
|
||||
return !more_;
|
||||
}
|
||||
|
||||
std::size_t line() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t column() const override
|
||||
{
|
||||
return source_.position();
|
||||
}
|
||||
|
||||
void array_expected(json_visitor& visitor, std::error_code& ec)
|
||||
{
|
||||
if (state_stack_.size() == 2 && state_stack_.back().mode == parse_mode::document)
|
||||
{
|
||||
state_stack_.back().mode = parse_mode::array;
|
||||
more_ = visitor.begin_array(semantic_tag::none, *this, ec);
|
||||
}
|
||||
}
|
||||
|
||||
void parse(json_visitor& visitor, std::error_code& ec)
|
||||
{
|
||||
if (JSONCONS_UNLIKELY(source_.is_error()))
|
||||
{
|
||||
ec = bson_errc::source_error;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
while (!done_ && more_)
|
||||
{
|
||||
switch (state_stack_.back().mode)
|
||||
{
|
||||
case parse_mode::root:
|
||||
state_stack_.back().mode = parse_mode::accept;
|
||||
begin_document(visitor, ec);
|
||||
break;
|
||||
case parse_mode::document:
|
||||
{
|
||||
uint8_t type;
|
||||
std::size_t n = source_.read(&type, 1);
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != 1))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
if (type != 0x00)
|
||||
{
|
||||
read_e_name(visitor,jsoncons::bson::bson_container_type::document,ec);
|
||||
state_stack_.back().mode = parse_mode::value;
|
||||
state_stack_.back().type = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
end_document(visitor,ec);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case parse_mode::array:
|
||||
{
|
||||
uint8_t type;
|
||||
std::size_t n = source_.read(&type, 1);
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != 1))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
if (type != 0x00)
|
||||
{
|
||||
read_e_name(visitor,jsoncons::bson::bson_container_type::array,ec);
|
||||
read_value(visitor, type, ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
end_array(visitor,ec);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case parse_mode::value:
|
||||
state_stack_.back().mode = parse_mode::document;
|
||||
read_value(visitor,state_stack_.back().type,ec);
|
||||
break;
|
||||
case parse_mode::accept:
|
||||
{
|
||||
JSONCONS_ASSERT(state_stack_.size() == 1);
|
||||
state_stack_.clear();
|
||||
more_ = false;
|
||||
done_ = true;
|
||||
visitor.flush();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void begin_document(json_visitor& visitor, std::error_code& ec)
|
||||
{
|
||||
if (JSONCONS_UNLIKELY(static_cast<int>(state_stack_.size()) > options_.max_nesting_depth()))
|
||||
{
|
||||
ec = bson_errc::max_nesting_depth_exceeded;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t buf[sizeof(int32_t)];
|
||||
size_t n = source_.read(buf, sizeof(int32_t));
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto length = binary::little_to_native<int32_t>(buf, sizeof(buf));
|
||||
|
||||
more_ = visitor.begin_object(semantic_tag::none, *this, ec);
|
||||
state_stack_.emplace_back(parse_mode::document,length,n);
|
||||
}
|
||||
|
||||
void end_document(json_visitor& visitor, std::error_code& ec)
|
||||
{
|
||||
JSONCONS_ASSERT(state_stack_.size() >= 2);
|
||||
|
||||
more_ = visitor.end_object(*this,ec);
|
||||
if (JSONCONS_UNLIKELY(state_stack_.back().pos != state_stack_.back().length))
|
||||
{
|
||||
ec = bson_errc::size_mismatch;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
std::size_t pos = state_stack_.back().pos;
|
||||
state_stack_.pop_back();
|
||||
state_stack_.back().pos += pos;
|
||||
}
|
||||
|
||||
void begin_array(json_visitor& visitor, std::error_code& ec)
|
||||
{
|
||||
if (JSONCONS_UNLIKELY(static_cast<int>(state_stack_.size()) > options_.max_nesting_depth()))
|
||||
{
|
||||
ec = bson_errc::max_nesting_depth_exceeded;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
uint8_t buf[sizeof(int32_t)];
|
||||
std::size_t n = source_.read(buf, sizeof(int32_t));
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
auto length = binary::little_to_native<int32_t>(buf, sizeof(buf));
|
||||
|
||||
more_ = visitor.begin_array(semantic_tag::none, *this, ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
state_stack_.emplace_back(parse_mode::array, length, n);
|
||||
}
|
||||
|
||||
void end_array(json_visitor& visitor, std::error_code& ec)
|
||||
{
|
||||
JSONCONS_ASSERT(state_stack_.size() >= 2);
|
||||
|
||||
more_ = visitor.end_array(*this, ec);
|
||||
if (JSONCONS_UNLIKELY(state_stack_.back().pos != state_stack_.back().length))
|
||||
{
|
||||
ec = bson_errc::size_mismatch;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
std::size_t pos = state_stack_.back().pos;
|
||||
state_stack_.pop_back();
|
||||
state_stack_.back().pos += pos;
|
||||
}
|
||||
|
||||
void read_e_name(json_visitor& visitor, jsoncons::bson::bson_container_type type, std::error_code& ec)
|
||||
{
|
||||
text_buffer_.clear();
|
||||
read_cstring(ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (type == jsoncons::bson::bson_container_type::document)
|
||||
{
|
||||
auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size());
|
||||
if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc()))
|
||||
{
|
||||
ec = bson_errc::invalid_utf8_text_string;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
more_ = visitor.key(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), *this, ec);
|
||||
}
|
||||
}
|
||||
|
||||
void read_value(json_visitor& visitor, uint8_t type, std::error_code& ec)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case jsoncons::bson::bson_type::double_type:
|
||||
{
|
||||
uint8_t buf[sizeof(double)];
|
||||
std::size_t n = source_.read(buf, sizeof(double));
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(double)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
double res = binary::little_to_native<double>(buf, sizeof(buf));
|
||||
more_ = visitor.double_value(res, semantic_tag::none, *this, ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::symbol_type:
|
||||
case jsoncons::bson::bson_type::min_key_type:
|
||||
case jsoncons::bson::bson_type::max_key_type:
|
||||
case jsoncons::bson::bson_type::string_type:
|
||||
{
|
||||
text_buffer_.clear();
|
||||
read_string(ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto result = unicode_traits::validate(text_buffer_.data(), text_buffer_.size());
|
||||
if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc()))
|
||||
{
|
||||
ec = bson_errc::invalid_utf8_text_string;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
more_ = visitor.string_value(text_buffer_, semantic_tag::none, *this, ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::javascript_type:
|
||||
{
|
||||
text_buffer_.clear();
|
||||
read_string(ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto result = unicode_traits::validate(text_buffer_.data(), text_buffer_.size());
|
||||
if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc()))
|
||||
{
|
||||
ec = bson_errc::invalid_utf8_text_string;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
more_ = visitor.string_value(text_buffer_, semantic_tag::code, *this, ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::regex_type:
|
||||
{
|
||||
text_buffer_.clear();
|
||||
text_buffer_.push_back('/');
|
||||
read_cstring(ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
text_buffer_.push_back('/');
|
||||
read_cstring(ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
more_ = visitor.string_value(text_buffer_, semantic_tag::regex, *this, ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::document_type:
|
||||
{
|
||||
begin_document(visitor,ec);
|
||||
break;
|
||||
}
|
||||
|
||||
case jsoncons::bson::bson_type::array_type:
|
||||
{
|
||||
begin_array(visitor,ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::undefined_type:
|
||||
{
|
||||
more_ = visitor.null_value(semantic_tag::undefined, *this, ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::null_type:
|
||||
{
|
||||
more_ = visitor.null_value(semantic_tag::none, *this, ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::bool_type:
|
||||
{
|
||||
uint8_t c;
|
||||
std::size_t n = source_.read(&c, 1);
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != 1))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
more_ = visitor.bool_value(c != 0, semantic_tag::none, *this, ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::int32_type:
|
||||
{
|
||||
uint8_t buf[sizeof(int32_t)];
|
||||
std::size_t n = source_.read(buf, sizeof(int32_t));
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
auto val = binary::little_to_native<int32_t>(buf, sizeof(buf));
|
||||
more_ = visitor.int64_value(val, semantic_tag::none, *this, ec);
|
||||
break;
|
||||
}
|
||||
|
||||
case jsoncons::bson::bson_type::timestamp_type:
|
||||
{
|
||||
uint8_t buf[sizeof(uint64_t)];
|
||||
std::size_t n = source_.read(buf, sizeof(uint64_t));
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(uint64_t)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
auto val = binary::little_to_native<uint64_t>(buf, sizeof(buf));
|
||||
more_ = visitor.uint64_value(val, semantic_tag::none, *this, ec);
|
||||
break;
|
||||
}
|
||||
|
||||
case jsoncons::bson::bson_type::int64_type:
|
||||
{
|
||||
uint8_t buf[sizeof(int64_t)];
|
||||
std::size_t n = source_.read(buf, sizeof(int64_t));
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(int64_t)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
auto val = binary::little_to_native<int64_t>(buf, sizeof(buf));
|
||||
more_ = visitor.int64_value(val, semantic_tag::none, *this, ec);
|
||||
break;
|
||||
}
|
||||
|
||||
case jsoncons::bson::bson_type::datetime_type:
|
||||
{
|
||||
uint8_t buf[sizeof(int64_t)];
|
||||
std::size_t n = source_.read(buf, sizeof(int64_t));
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(int64_t)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
auto val = binary::little_to_native<int64_t>(buf, sizeof(buf));
|
||||
more_ = visitor.int64_value(val, semantic_tag::epoch_milli, *this, ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::binary_type:
|
||||
{
|
||||
uint8_t buf[sizeof(int32_t)];
|
||||
std::size_t n = source_.read(buf, sizeof(int32_t));
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
const auto len = binary::little_to_native<int32_t>(buf, sizeof(buf));
|
||||
if (JSONCONS_UNLIKELY(len < 0))
|
||||
{
|
||||
ec = bson_errc::length_is_negative;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
uint8_t subtype;
|
||||
n = source_.read(&subtype, 1);
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != 1))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_buffer_.clear();
|
||||
n = source_reader<Source>::read(source_, bytes_buffer_, len);
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != static_cast<std::size_t>(len)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
more_ = visitor.byte_string_value(bytes_buffer_,
|
||||
subtype,
|
||||
*this,
|
||||
ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::decimal128_type:
|
||||
{
|
||||
uint8_t buf[sizeof(uint64_t)*2];
|
||||
std::size_t n = source_.read(buf, sizeof(buf));
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(buf)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
decimal128_t dec;
|
||||
dec.low = binary::little_to_native<uint64_t>(buf, sizeof(uint64_t));
|
||||
dec.high = binary::little_to_native<uint64_t>(buf+sizeof(uint64_t), sizeof(uint64_t));
|
||||
|
||||
text_buffer_.clear();
|
||||
text_buffer_.resize(bson::decimal128_limits::buf_size);
|
||||
auto r = bson::decimal128_to_chars(&text_buffer_[0], &text_buffer_[0]+text_buffer_.size(), dec);
|
||||
more_ = visitor.string_value(string_view(text_buffer_.data(),static_cast<std::size_t>(r.ptr-text_buffer_.data())), semantic_tag::float128, *this, ec);
|
||||
break;
|
||||
}
|
||||
case jsoncons::bson::bson_type::object_id_type:
|
||||
{
|
||||
uint8_t buf[12];
|
||||
std::size_t n = source_.read(buf, sizeof(buf));
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(buf)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
oid_t oid(buf);
|
||||
to_string(oid, text_buffer_);
|
||||
|
||||
more_ = visitor.string_value(text_buffer_, semantic_tag::id, *this, ec);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ec = bson_errc::unknown_type;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void read_cstring(std::error_code& ec)
|
||||
{
|
||||
uint8_t c = 0xff;
|
||||
while (true)
|
||||
{
|
||||
std::size_t n = source_.read(&c, 1);
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != 1))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
if (c == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
text_buffer_.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
void read_string(std::error_code& ec)
|
||||
{
|
||||
uint8_t buf[sizeof(int32_t)];
|
||||
std::size_t n = source_.read(buf, sizeof(int32_t));
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != sizeof(int32_t)))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
auto len = binary::little_to_native<int32_t>(buf, sizeof(buf));
|
||||
if (JSONCONS_UNLIKELY(len < 1))
|
||||
{
|
||||
ec = bson_errc::string_length_is_non_positive;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
std::size_t size = static_cast<std::size_t>(len) - static_cast<std::size_t>(1);
|
||||
n = source_reader<Source>::read(source_, text_buffer_, size);
|
||||
state_stack_.back().pos += n;
|
||||
|
||||
if (JSONCONS_UNLIKELY(n != size))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
uint8_t c;
|
||||
n = source_.read(&c, 1);
|
||||
state_stack_.back().pos += n;
|
||||
if (JSONCONS_UNLIKELY(n != 1))
|
||||
{
|
||||
ec = bson_errc::unexpected_eof;
|
||||
more_ = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BSON_BSON_READER_HPP
|
||||
#define JSONCONS_BSON_BSON_READER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <utility> // std::move
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons_ext/bson/bson_type.hpp>
|
||||
#include <jsoncons_ext/bson/bson_error.hpp>
|
||||
#include <jsoncons_ext/bson/bson_parser.hpp>
|
||||
|
||||
namespace jsoncons { namespace bson {
|
||||
|
||||
template <class Source,class Allocator=std::allocator<char>>
|
||||
class basic_bson_reader
|
||||
{
|
||||
basic_bson_parser<Source,Allocator> parser_;
|
||||
json_visitor& visitor_;
|
||||
public:
|
||||
template <class Sourceable>
|
||||
basic_bson_reader(Sourceable&& source,
|
||||
json_visitor& visitor,
|
||||
const Allocator alloc)
|
||||
: basic_bson_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
bson_decode_options(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_bson_reader(Sourceable&& source,
|
||||
json_visitor& visitor,
|
||||
const bson_decode_options& options = bson_decode_options(),
|
||||
const Allocator alloc=Allocator())
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
visitor_(visitor)
|
||||
{
|
||||
}
|
||||
|
||||
void read()
|
||||
{
|
||||
std::error_code ec;
|
||||
read(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,line(),column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read(std::error_code& ec)
|
||||
{
|
||||
parser_.reset();
|
||||
parser_.parse(visitor_, ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t line() const
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
};
|
||||
|
||||
using bson_stream_reader = basic_bson_reader<jsoncons::binary_stream_source>;
|
||||
using bson_bytes_reader = basic_bson_reader<jsoncons::bytes_source>;
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use bson_stream_reader") typedef bson_stream_reader bson_reader;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use bson_bytes_reader") typedef bson_bytes_reader bson_buffer_reader;
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
44
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_type.hpp
Normal file
44
scripts/exe/jsoncons/include/jsoncons_ext/bson/bson_type.hpp
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BSON_BSON_TYPE_HPP
|
||||
#define JSONCONS_BSON_BSON_TYPE_HPP
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
|
||||
namespace jsoncons { namespace bson {
|
||||
|
||||
namespace bson_type
|
||||
{
|
||||
const uint8_t double_type = 0x01;
|
||||
const uint8_t string_type = 0x02; // UTF-8 string
|
||||
const uint8_t document_type = 0x03;
|
||||
const uint8_t array_type = 0x04;
|
||||
const uint8_t binary_type = 0x05;
|
||||
const uint8_t undefined_type = 0x06; // map to null
|
||||
const uint8_t object_id_type = 0x07;
|
||||
const uint8_t bool_type = 0x08;
|
||||
const uint8_t datetime_type = 0x09;
|
||||
const uint8_t null_type = 0x0a;
|
||||
const uint8_t regex_type = 0x0b;
|
||||
const uint8_t javascript_type = 0x0d;
|
||||
const uint8_t symbol_type = 0x0e; // deprecated, mapped to string
|
||||
const uint8_t javascript_with_scope_type = 0x0f; // unsupported
|
||||
const uint8_t int32_type = 0x10;
|
||||
const uint8_t timestamp_type = 0x11; // MongoDB internal Timestamp, uint64
|
||||
const uint8_t int64_type = 0x12;
|
||||
const uint8_t decimal128_type = 0x13;
|
||||
const uint8_t min_key_type = 0xff;
|
||||
const uint8_t max_key_type = 0x7f;
|
||||
}
|
||||
|
||||
enum class bson_container_type {document, array};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
201
scripts/exe/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp
Normal file
201
scripts/exe/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BSON_DECODE_BSON_HPP
|
||||
#define JSONCONS_BSON_DECODE_BSON_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <type_traits> // std::enable_if
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons_ext/bson/bson_reader.hpp>
|
||||
#include <jsoncons_ext/bson/bson_cursor.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace bson {
|
||||
|
||||
template<class T, class Source>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_byte_sequence<Source>::value,T>::type
|
||||
decode_bson(const Source& v,
|
||||
const bson_decode_options& options = bson_decode_options())
|
||||
{
|
||||
jsoncons::json_decoder<T> decoder;
|
||||
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
||||
basic_bson_reader<jsoncons::bytes_source> reader(v, adaptor, options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template<class T, class Source>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_byte_sequence<Source>::value,T>::type
|
||||
decode_bson(const Source& v,
|
||||
const bson_decode_options& options = bson_decode_options())
|
||||
{
|
||||
basic_bson_cursor<bytes_source> cursor(v, options);
|
||||
json_decoder<basic_json<char,sorted_policy>> decoder{};
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_bson(std::istream& is,
|
||||
const bson_decode_options& options = bson_decode_options())
|
||||
{
|
||||
jsoncons::json_decoder<T> decoder;
|
||||
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
||||
bson_stream_reader reader(is, adaptor, options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_bson(std::istream& is,
|
||||
const bson_decode_options& options = bson_decode_options())
|
||||
{
|
||||
basic_bson_cursor<binary_stream_source> cursor(is, options);
|
||||
json_decoder<basic_json<char,sorted_policy>> decoder{};
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T, class InputIt>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_bson(InputIt first, InputIt last,
|
||||
const bson_decode_options& options = bson_decode_options())
|
||||
{
|
||||
jsoncons::json_decoder<T> decoder;
|
||||
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
||||
basic_bson_reader<binary_iterator_source<InputIt>> reader(binary_iterator_source<InputIt>(first, last), adaptor, options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template<class T, class InputIt>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_bson(InputIt first, InputIt last,
|
||||
const bson_decode_options& options = bson_decode_options())
|
||||
{
|
||||
basic_bson_cursor<binary_iterator_source<InputIt>> cursor(binary_iterator_source<InputIt>(first, last), options);
|
||||
json_decoder<basic_json<char,sorted_policy>> decoder{};
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// With leading allocator parameter
|
||||
|
||||
template<class T, class Source, class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_byte_sequence<Source>::value,T>::type
|
||||
decode_bson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const Source& v,
|
||||
const bson_decode_options& options = bson_decode_options())
|
||||
{
|
||||
json_decoder<T,TempAllocator> decoder(temp_alloc);
|
||||
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
||||
basic_bson_reader<jsoncons::bytes_source,TempAllocator> reader(v, adaptor, options, temp_alloc);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template<class T, class Source, class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_byte_sequence<Source>::value,T>::type
|
||||
decode_bson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const Source& v,
|
||||
const bson_decode_options& options = bson_decode_options())
|
||||
{
|
||||
basic_bson_cursor<bytes_source,TempAllocator> cursor(v, options, temp_alloc);
|
||||
json_decoder<basic_json<char,sorted_policy,TempAllocator>,TempAllocator> decoder(temp_alloc, temp_alloc);
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T,class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_bson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
std::istream& is,
|
||||
const bson_decode_options& options = bson_decode_options())
|
||||
{
|
||||
json_decoder<T,TempAllocator> decoder(temp_alloc);
|
||||
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
||||
basic_bson_reader<jsoncons::binary_stream_source,TempAllocator> reader(is, adaptor, options, temp_alloc);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template<class T,class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_bson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
std::istream& is,
|
||||
const bson_decode_options& options = bson_decode_options())
|
||||
{
|
||||
basic_bson_cursor<binary_stream_source,TempAllocator> cursor(is, options, temp_alloc);
|
||||
json_decoder<basic_json<char,sorted_policy,TempAllocator>,TempAllocator> decoder(temp_alloc, temp_alloc);
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
} // bson
|
||||
} // jsoncons
|
||||
|
||||
#endif
|
||||
144
scripts/exe/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp
Normal file
144
scripts/exe/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_BSON_ENCODE_BSON_HPP
|
||||
#define JSONCONS_BSON_ENCODE_BSON_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <type_traits> // std::enable_if
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons_ext/bson/bson_encoder.hpp>
|
||||
#include <jsoncons_ext/bson/bson_reader.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace bson {
|
||||
|
||||
template<class T, class Container>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<Container>::value,void>::type
|
||||
encode_bson(const T& j,
|
||||
Container& v,
|
||||
const bson_encode_options& options = bson_encode_options())
|
||||
{
|
||||
using char_type = typename T::char_type;
|
||||
basic_bson_encoder<jsoncons::bytes_sink<Container>> encoder(v, options);
|
||||
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
||||
j.dump(adaptor);
|
||||
}
|
||||
|
||||
template<class T, class Container>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<Container>::value,void>::type
|
||||
encode_bson(const T& val,
|
||||
Container& v,
|
||||
const bson_encode_options& options = bson_encode_options())
|
||||
{
|
||||
basic_bson_encoder<jsoncons::bytes_sink<Container>> encoder(v, options);
|
||||
std::error_code ec;
|
||||
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_bson(const T& j,
|
||||
std::ostream& os,
|
||||
const bson_encode_options& options = bson_encode_options())
|
||||
{
|
||||
using char_type = typename T::char_type;
|
||||
bson_stream_encoder encoder(os, options);
|
||||
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
||||
j.dump(adaptor);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_bson(const T& val,
|
||||
std::ostream& os,
|
||||
const bson_encode_options& options = bson_encode_options())
|
||||
{
|
||||
bson_stream_encoder encoder(os, options);
|
||||
std::error_code ec;
|
||||
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
// with temp_allocator_rag
|
||||
|
||||
template<class T, class Container, class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<Container>::value,void>::type
|
||||
encode_bson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& j,
|
||||
Container& v,
|
||||
const bson_encode_options& options = bson_encode_options())
|
||||
{
|
||||
using char_type = typename T::char_type;
|
||||
basic_bson_encoder<jsoncons::bytes_sink<Container>,TempAllocator> encoder(v, options, temp_alloc);
|
||||
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
||||
j.dump(adaptor);
|
||||
}
|
||||
|
||||
template<class T, class Container, class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<Container>::value,void>::type
|
||||
encode_bson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
Container& v,
|
||||
const bson_encode_options& options = bson_encode_options())
|
||||
{
|
||||
basic_bson_encoder<jsoncons::bytes_sink<Container>,TempAllocator> encoder(v, options, temp_alloc);
|
||||
std::error_code ec;
|
||||
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
template<class T,class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_bson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& j,
|
||||
std::ostream& os,
|
||||
const bson_encode_options& options = bson_encode_options())
|
||||
{
|
||||
using char_type = typename T::char_type;
|
||||
basic_bson_encoder<jsoncons::binary_stream_sink,TempAllocator> encoder(os, options, temp_alloc);
|
||||
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
||||
j.dump(adaptor);
|
||||
}
|
||||
|
||||
template<class T,class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_bson(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
std::ostream& os,
|
||||
const bson_encode_options& options = bson_encode_options())
|
||||
{
|
||||
basic_bson_encoder<jsoncons::binary_stream_sink,TempAllocator> encoder(os, options, temp_alloc);
|
||||
std::error_code ec;
|
||||
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
} // bson
|
||||
} // jsoncons
|
||||
|
||||
#endif
|
||||
26
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor.hpp
Normal file
26
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor.hpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2017-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
|
||||
#ifndef JSONCONS_CBOR_CBOR_HPP
|
||||
#define JSONCONS_CBOR_CBOR_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <type_traits> // std::enable_if
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/json_filter.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_reader.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_cursor.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_encoder.hpp>
|
||||
#include <jsoncons_ext/cbor/encode_cbor.hpp>
|
||||
#include <jsoncons_ext/cbor/decode_cbor.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
351
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp
Normal file
351
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CBOR_CBOR_CURSOR_HPP
|
||||
#define JSONCONS_CBOR_CBOR_CURSOR_HPP
|
||||
|
||||
#include <memory> // std::allocator
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <ios>
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/byte_string.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/staj_cursor.hpp>
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_parser.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace cbor {
|
||||
|
||||
template<class Source=jsoncons::binary_stream_source,class Allocator=std::allocator<char>>
|
||||
class basic_cbor_cursor : public basic_staj_cursor<char>, private virtual ser_context
|
||||
{
|
||||
public:
|
||||
using source_type = Source;
|
||||
using char_type = char;
|
||||
using allocator_type = Allocator;
|
||||
private:
|
||||
basic_cbor_parser<Source,Allocator> parser_;
|
||||
basic_staj_visitor<char_type> cursor_visitor_;
|
||||
basic_item_event_visitor_to_json_visitor<char_type,Allocator> cursor_handler_adaptor_;
|
||||
bool eof_;
|
||||
|
||||
// Noncopyable and nonmoveable
|
||||
basic_cbor_cursor(const basic_cbor_cursor&) = delete;
|
||||
basic_cbor_cursor& operator=(const basic_cbor_cursor&) = delete;
|
||||
|
||||
public:
|
||||
using string_view_type = string_view;
|
||||
|
||||
template <class Sourceable>
|
||||
basic_cbor_cursor(Sourceable&& source,
|
||||
const cbor_decode_options& options = cbor_decode_options(),
|
||||
const Allocator& alloc = Allocator())
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
cursor_visitor_(accept_all),
|
||||
cursor_handler_adaptor_(cursor_visitor_, alloc),
|
||||
eof_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
// Constructors that set parse error codes
|
||||
|
||||
template <class Sourceable>
|
||||
basic_cbor_cursor(Sourceable&& source,
|
||||
std::error_code& ec)
|
||||
: basic_cbor_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
cbor_decode_options(),
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_cbor_cursor(Sourceable&& source,
|
||||
const cbor_decode_options& options,
|
||||
std::error_code& ec)
|
||||
: basic_cbor_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
options,
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_cbor_cursor(std::allocator_arg_t, const Allocator& alloc,
|
||||
Sourceable&& source,
|
||||
const cbor_decode_options& options,
|
||||
std::error_code& ec)
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
cursor_visitor_(accept_all),
|
||||
cursor_handler_adaptor_(cursor_visitor_, alloc),
|
||||
eof_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
parser_.reset();
|
||||
cursor_visitor_.reset();
|
||||
cursor_handler_adaptor_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
void reset(Sourceable&& source)
|
||||
{
|
||||
parser_.reset(std::forward<Sourceable>(source));
|
||||
cursor_visitor_.reset();
|
||||
cursor_handler_adaptor_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
void reset(std::error_code& ec)
|
||||
{
|
||||
parser_.reset();
|
||||
cursor_visitor_.reset();
|
||||
cursor_handler_adaptor_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
void reset(Sourceable&& source, std::error_code& ec)
|
||||
{
|
||||
parser_.reset(std::forward<Sourceable>(source));
|
||||
cursor_visitor_.reset();
|
||||
cursor_handler_adaptor_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
bool done() const override
|
||||
{
|
||||
return parser_.done();
|
||||
}
|
||||
|
||||
bool is_typed_array() const
|
||||
{
|
||||
return cursor_visitor_.is_typed_array();
|
||||
}
|
||||
|
||||
const staj_event& current() const override
|
||||
{
|
||||
return cursor_visitor_.event();
|
||||
}
|
||||
|
||||
void read_to(basic_json_visitor<char_type>& visitor) override
|
||||
{
|
||||
std::error_code ec;
|
||||
read_to(visitor, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read_to(basic_json_visitor<char_type>& visitor,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (cursor_visitor_.dump(visitor, *this, ec))
|
||||
{
|
||||
read_next(visitor, ec);
|
||||
}
|
||||
}
|
||||
|
||||
void next() override
|
||||
{
|
||||
std::error_code ec;
|
||||
next(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void next(std::error_code& ec) override
|
||||
{
|
||||
read_next(ec);
|
||||
}
|
||||
|
||||
const ser_context& context() const override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return eof_;
|
||||
}
|
||||
|
||||
std::size_t line() const override
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const override
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
|
||||
friend
|
||||
staj_filter_view operator|(basic_cbor_cursor& cursor,
|
||||
std::function<bool(const staj_event&, const ser_context&)> pred)
|
||||
{
|
||||
return staj_filter_view(cursor, pred);
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
|
||||
template <class Sourceable>
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use pipe syntax for filter")
|
||||
basic_cbor_cursor(Sourceable&& source,
|
||||
std::function<bool(const staj_event&, const ser_context&)> filter,
|
||||
const cbor_decode_options& options = cbor_decode_options(),
|
||||
const Allocator& alloc = Allocator())
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
cursor_visitor_(filter),
|
||||
cursor_handler_adaptor_(cursor_visitor_, alloc),
|
||||
eof_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use pipe syntax for filter")
|
||||
basic_cbor_cursor(Sourceable&& source,
|
||||
std::function<bool(const staj_event&, const ser_context&)> filter,
|
||||
std::error_code& ec)
|
||||
: basic_cbor_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source), filter, ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use pipe syntax for filter")
|
||||
basic_cbor_cursor(std::allocator_arg_t, const Allocator& alloc,
|
||||
Sourceable&& source,
|
||||
std::function<bool(const staj_event&, const ser_context&)> filter,
|
||||
std::error_code& ec)
|
||||
: parser_(std::forward<Sourceable>(source), alloc),
|
||||
cursor_visitor_(filter),
|
||||
cursor_handler_adaptor_(cursor_visitor_, alloc),
|
||||
eof_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use read_to(basic_json_visitor<char_type>&)")
|
||||
void read(basic_json_visitor<char_type>& visitor)
|
||||
{
|
||||
read_to(visitor);
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use read_to(basic_json_visitor<char_type>&, std::error_code&)")
|
||||
void read(basic_json_visitor<char_type>& visitor,
|
||||
std::error_code& ec)
|
||||
{
|
||||
read_to(visitor, ec);
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
static bool accept_all(const staj_event&, const ser_context&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void read_next(std::error_code& ec)
|
||||
{
|
||||
if (cursor_visitor_.in_available())
|
||||
{
|
||||
cursor_visitor_.send_available(ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_.restart();
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
parser_.parse(cursor_handler_adaptor_, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void read_next(basic_json_visitor<char_type>& visitor, std::error_code& ec)
|
||||
{
|
||||
{
|
||||
struct resource_wrapper
|
||||
{
|
||||
basic_item_event_visitor_to_json_visitor<char_type,Allocator>& adaptor;
|
||||
basic_json_visitor<char_type>& original;
|
||||
|
||||
resource_wrapper(basic_item_event_visitor_to_json_visitor<char_type,Allocator>& adaptor,
|
||||
basic_json_visitor<char_type>& visitor)
|
||||
: adaptor(adaptor), original(adaptor.destination())
|
||||
{
|
||||
adaptor.destination(visitor);
|
||||
}
|
||||
|
||||
~resource_wrapper()
|
||||
{
|
||||
adaptor.destination(original);
|
||||
}
|
||||
} wrapper(cursor_handler_adaptor_, visitor);
|
||||
|
||||
parser_.restart();
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
parser_.parse(cursor_handler_adaptor_, ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using cbor_stream_cursor = basic_cbor_cursor<jsoncons::binary_stream_source>;
|
||||
using cbor_bytes_cursor = basic_cbor_cursor<jsoncons::bytes_source>;
|
||||
|
||||
} // namespace cbor
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CBOR_CBOR_DETAIL_HPP
|
||||
#define JSONCONS_CBOR_CBOR_DETAIL_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <iterator> // std::forward_iterator_tag
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <utility> // std::move
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
|
||||
// 0x00..0x17 (0..23)
|
||||
#define JSONCONS_CBOR_0x00_0x17 \
|
||||
0x00:case 0x01:case 0x02:case 0x03:case 0x04:case 0x05:case 0x06:case 0x07:case 0x08:case 0x09:case 0x0a:case 0x0b:case 0x0c:case 0x0d:case 0x0e:case 0x0f:case 0x10:case 0x11:case 0x12:case 0x13:case 0x14:case 0x15:case 0x16:case 0x17
|
||||
|
||||
#define JSONCONS_CBOR_ARRAY_TAGS \
|
||||
0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47:case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f:case 0x50:case 0x51:case 0x52:case 0x53:case 0x54:case 0x55:case 0x56:case 0x57
|
||||
|
||||
namespace jsoncons { namespace cbor { namespace detail {
|
||||
|
||||
//const uint8_t cbor_array_tags_010_mask = 0b11100000;
|
||||
//const uint8_t cbor_array_tags_f_mask = 0b00010000;
|
||||
//const uint8_t cbor_array_tags_s_mask = 0b00001000;
|
||||
//const uint8_t cbor_array_tags_e_mask = 0b00000100;
|
||||
//const uint8_t cbor_array_tags_ll_mask = 0b00000011;
|
||||
|
||||
const uint8_t cbor_array_tags_010_mask = 0xE0;
|
||||
const uint8_t cbor_array_tags_f_mask = 0x10;
|
||||
const uint8_t cbor_array_tags_s_mask = 0x08;
|
||||
const uint8_t cbor_array_tags_e_mask = 0x04;
|
||||
const uint8_t cbor_array_tags_ll_mask = 0x03;
|
||||
|
||||
const uint8_t cbor_array_tags_010_shift = 5;
|
||||
const uint8_t cbor_array_tags_f_shift = 4;
|
||||
const uint8_t cbor_array_tags_s_shift = 3;
|
||||
const uint8_t cbor_array_tags_e_shift = 2;
|
||||
const uint8_t cbor_array_tags_ll_shift = 0;
|
||||
|
||||
enum class cbor_major_type : uint8_t
|
||||
{
|
||||
unsigned_integer = 0x00,
|
||||
negative_integer = 0x01,
|
||||
byte_string = 0x02,
|
||||
text_string = 0x03,
|
||||
array = 0x04,
|
||||
map = 0x05,
|
||||
semantic_tag = 0x06,
|
||||
simple = 0x7
|
||||
};
|
||||
|
||||
namespace additional_info
|
||||
{
|
||||
const uint8_t indefinite_length = 0x1f;
|
||||
}
|
||||
|
||||
inline
|
||||
size_t min_length_for_stringref(uint64_t index)
|
||||
{
|
||||
std::size_t n;
|
||||
if (index <= 23)
|
||||
{
|
||||
n = 3;
|
||||
}
|
||||
else if (index <= 255)
|
||||
{
|
||||
n = 4;
|
||||
}
|
||||
else if (index <= 65535)
|
||||
{
|
||||
n = 5;
|
||||
}
|
||||
else if (index <= 4294967295)
|
||||
{
|
||||
n = 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
n = 11;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
1757
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp
Normal file
1757
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp
Normal file
File diff suppressed because it is too large
Load diff
105
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp
Normal file
105
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CBOR_CBOR_ERROR_HPP
|
||||
#define JSONCONS_CBOR_CBOR_ERROR_HPP
|
||||
|
||||
#include <system_error>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/json_exception.hpp> // jsoncons::ser_error
|
||||
|
||||
namespace jsoncons { namespace cbor {
|
||||
|
||||
enum class cbor_errc
|
||||
{
|
||||
success = 0,
|
||||
unexpected_eof,
|
||||
source_error,
|
||||
invalid_decimal_fraction,
|
||||
invalid_bigfloat,
|
||||
invalid_utf8_text_string,
|
||||
too_many_items,
|
||||
too_few_items,
|
||||
number_too_large,
|
||||
stringref_too_large,
|
||||
max_nesting_depth_exceeded,
|
||||
unknown_type,
|
||||
illegal_chunked_string
|
||||
};
|
||||
|
||||
class cbor_error_category_impl
|
||||
: public std::error_category
|
||||
{
|
||||
public:
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "jsoncons/cbor";
|
||||
}
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<cbor_errc>(ev))
|
||||
{
|
||||
case cbor_errc::unexpected_eof:
|
||||
return "Unexpected end of file";
|
||||
case cbor_errc::source_error:
|
||||
return "Source error";
|
||||
case cbor_errc::invalid_decimal_fraction:
|
||||
return "Invalid decimal fraction";
|
||||
case cbor_errc::invalid_bigfloat:
|
||||
return "Invalid bigfloat";
|
||||
case cbor_errc::invalid_utf8_text_string:
|
||||
return "Illegal UTF-8 encoding in text string";
|
||||
case cbor_errc::too_many_items:
|
||||
return "Too many items were added to a CBOR map or array of known length";
|
||||
case cbor_errc::too_few_items:
|
||||
return "Too few items were added to a CBOR map or array of known length";
|
||||
case cbor_errc::number_too_large:
|
||||
return "Number exceeds implementation limits";
|
||||
case cbor_errc::stringref_too_large:
|
||||
return "stringref exceeds stringref map size";
|
||||
case cbor_errc::max_nesting_depth_exceeded:
|
||||
return "Data item nesting exceeds limit in options";
|
||||
case cbor_errc::unknown_type:
|
||||
return "An unknown type was found in the stream";
|
||||
case cbor_errc::illegal_chunked_string:
|
||||
return "An illegal type was found while parsing an indefinite length string";
|
||||
default:
|
||||
return "Unknown CBOR parser error";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
const std::error_category& cbor_error_category()
|
||||
{
|
||||
static cbor_error_category_impl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
inline
|
||||
std::error_code make_error_code(cbor_errc e)
|
||||
{
|
||||
return std::error_code(static_cast<int>(e),cbor_error_category());
|
||||
}
|
||||
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_error") typedef ser_error cbor_error;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_error") typedef ser_error cbor_decode_error;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use ser_error") typedef ser_error cbor_reader_errc;
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct is_error_code_enum<jsoncons::cbor::cbor_errc> : public true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,262 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CBOR_EVENT_READER_HPP
|
||||
#define JSONCONS_CBOR_EVENT_READER_HPP
|
||||
|
||||
#include <memory> // std::allocator
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <ios>
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/byte_string.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/item_event_visitor.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/item_event_reader.hpp>
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_parser.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace cbor {
|
||||
|
||||
template<class Source=jsoncons::binary_stream_source,class Allocator=std::allocator<char>>
|
||||
class cbor_event_reader : public basic_item_event_reader<char>, private virtual ser_context
|
||||
{
|
||||
public:
|
||||
using source_type = Source;
|
||||
using char_type = char;
|
||||
using allocator_type = Allocator;
|
||||
private:
|
||||
basic_cbor_parser<Source,Allocator> parser_;
|
||||
basic_item_event_receiver<char_type> event_receiver_;
|
||||
bool eof_;
|
||||
|
||||
// Noncopyable and nonmoveable
|
||||
cbor_event_reader(const cbor_event_reader&) = delete;
|
||||
cbor_event_reader& operator=(const cbor_event_reader&) = delete;
|
||||
|
||||
public:
|
||||
using string_view_type = string_view;
|
||||
|
||||
template <class Sourceable>
|
||||
cbor_event_reader(Sourceable&& source,
|
||||
const cbor_decode_options& options = cbor_decode_options(),
|
||||
const Allocator& alloc = Allocator())
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
event_receiver_(accept_all),
|
||||
eof_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
// Constructors that set parse error codes
|
||||
|
||||
template <class Sourceable>
|
||||
cbor_event_reader(Sourceable&& source,
|
||||
std::error_code& ec)
|
||||
: cbor_event_reader(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
cbor_decode_options(),
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
cbor_event_reader(Sourceable&& source,
|
||||
const cbor_decode_options& options,
|
||||
std::error_code& ec)
|
||||
: cbor_event_reader(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
options,
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
cbor_event_reader(std::allocator_arg_t, const Allocator& alloc,
|
||||
Sourceable&& source,
|
||||
const cbor_decode_options& options,
|
||||
std::error_code& ec)
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
event_receiver_(accept_all),
|
||||
eof_(false)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
parser_.reset();
|
||||
event_receiver_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
void reset(Sourceable&& source)
|
||||
{
|
||||
parser_.reset(std::forward<Sourceable>(source));
|
||||
event_receiver_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
void reset(std::error_code& ec)
|
||||
{
|
||||
parser_.reset();
|
||||
event_receiver_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
void reset(Sourceable&& source, std::error_code& ec)
|
||||
{
|
||||
parser_.reset(std::forward<Sourceable>(source));
|
||||
event_receiver_.reset();
|
||||
eof_ = false;
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
bool done() const override
|
||||
{
|
||||
return parser_.done();
|
||||
}
|
||||
|
||||
bool is_typed_array() const
|
||||
{
|
||||
return event_receiver_.is_typed_array();
|
||||
}
|
||||
|
||||
const basic_item_event<char_type>& current() const override
|
||||
{
|
||||
return event_receiver_.event();
|
||||
}
|
||||
|
||||
void read_to(basic_item_event_visitor<char_type>& visitor) override
|
||||
{
|
||||
std::error_code ec;
|
||||
read_to(visitor, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read_to(basic_item_event_visitor<char_type>& visitor,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (event_receiver_.dump(visitor, *this, ec))
|
||||
{
|
||||
read_next(visitor, ec);
|
||||
}
|
||||
}
|
||||
|
||||
void next() override
|
||||
{
|
||||
std::error_code ec;
|
||||
next(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void next(std::error_code& ec) override
|
||||
{
|
||||
read_next(ec);
|
||||
}
|
||||
|
||||
const ser_context& context() const override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return eof_;
|
||||
}
|
||||
|
||||
std::size_t line() const override
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const override
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
|
||||
friend
|
||||
staj2_filter_view operator|(cbor_event_reader& cursor,
|
||||
std::function<bool(const item_event&, const ser_context&)> pred)
|
||||
{
|
||||
return staj2_filter_view(cursor, pred);
|
||||
}
|
||||
|
||||
private:
|
||||
static bool accept_all(const item_event&, const ser_context&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void read_next(std::error_code& ec)
|
||||
{
|
||||
if (event_receiver_.in_available())
|
||||
{
|
||||
event_receiver_.send_available(ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_.restart();
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
parser_.parse(event_receiver_, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void read_next(basic_item_event_visitor<char_type>& visitor, std::error_code& ec)
|
||||
{
|
||||
parser_.restart();
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
parser_.parse(visitor, ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace cbor
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
|
||||
113
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp
Normal file
113
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CBOR_CBOR_OPTIONS_HPP
|
||||
#define JSONCONS_CBOR_CBOR_OPTIONS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <cwchar>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_detail.hpp>
|
||||
|
||||
namespace jsoncons { namespace cbor {
|
||||
|
||||
class cbor_options;
|
||||
|
||||
class cbor_options_common
|
||||
{
|
||||
friend class cbor_options;
|
||||
|
||||
int max_nesting_depth_;
|
||||
protected:
|
||||
virtual ~cbor_options_common() = default;
|
||||
|
||||
cbor_options_common()
|
||||
: max_nesting_depth_(1024)
|
||||
{
|
||||
}
|
||||
|
||||
cbor_options_common(const cbor_options_common&) = default;
|
||||
cbor_options_common& operator=(const cbor_options_common&) = default;
|
||||
cbor_options_common(cbor_options_common&&) = default;
|
||||
cbor_options_common& operator=(cbor_options_common&&) = default;
|
||||
public:
|
||||
int max_nesting_depth() const
|
||||
{
|
||||
return max_nesting_depth_;
|
||||
}
|
||||
};
|
||||
|
||||
class cbor_decode_options : public virtual cbor_options_common
|
||||
{
|
||||
friend class cbor_options;
|
||||
public:
|
||||
cbor_decode_options()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class cbor_encode_options : public virtual cbor_options_common
|
||||
{
|
||||
friend class cbor_options;
|
||||
|
||||
bool use_stringref_;
|
||||
bool use_typed_arrays_;
|
||||
public:
|
||||
cbor_encode_options()
|
||||
: use_stringref_(false),
|
||||
use_typed_arrays_(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool pack_strings() const
|
||||
{
|
||||
return use_stringref_;
|
||||
}
|
||||
|
||||
bool use_typed_arrays() const
|
||||
{
|
||||
return use_typed_arrays_;
|
||||
}
|
||||
};
|
||||
|
||||
class cbor_options final : public cbor_decode_options, public cbor_encode_options
|
||||
{
|
||||
public:
|
||||
using cbor_options_common::max_nesting_depth;
|
||||
using cbor_encode_options::pack_strings;
|
||||
using cbor_encode_options::use_typed_arrays;
|
||||
|
||||
cbor_options& max_nesting_depth(int value)
|
||||
{
|
||||
this->max_nesting_depth_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
cbor_options& pack_strings(bool value)
|
||||
{
|
||||
this->use_stringref_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
cbor_options& use_typed_arrays(bool value)
|
||||
{
|
||||
this->use_typed_arrays_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use use_typed_arrays(bool)")
|
||||
cbor_options& enable_typed_arrays(bool value)
|
||||
{
|
||||
this->use_typed_arrays_ = value;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
}}
|
||||
#endif
|
||||
1942
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp
Normal file
1942
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp
Normal file
File diff suppressed because it is too large
Load diff
116
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp
Normal file
116
scripts/exe/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CBOR_CBOR_READER_HPP
|
||||
#define JSONCONS_CBOR_CBOR_READER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <utility> // std::move
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_encoder.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_error.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_detail.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_parser.hpp>
|
||||
|
||||
namespace jsoncons { namespace cbor {
|
||||
|
||||
template <class Source,class Allocator=std::allocator<char>>
|
||||
class basic_cbor_reader
|
||||
{
|
||||
using char_type = char;
|
||||
|
||||
basic_cbor_parser<Source,Allocator> parser_;
|
||||
basic_item_event_visitor_to_json_visitor<char_type,Allocator> adaptor_;
|
||||
item_event_visitor& visitor_;
|
||||
public:
|
||||
template <class Sourceable>
|
||||
basic_cbor_reader(Sourceable&& source,
|
||||
json_visitor& visitor,
|
||||
const Allocator alloc)
|
||||
: basic_cbor_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
cbor_decode_options(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_cbor_reader(Sourceable&& source,
|
||||
json_visitor& visitor,
|
||||
const cbor_decode_options& options = cbor_decode_options(),
|
||||
const Allocator alloc=Allocator())
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
adaptor_(visitor, alloc), visitor_(adaptor_)
|
||||
{
|
||||
}
|
||||
template <class Sourceable>
|
||||
basic_cbor_reader(Sourceable&& source,
|
||||
item_event_visitor& visitor,
|
||||
const Allocator alloc)
|
||||
: basic_cbor_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
cbor_decode_options(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_cbor_reader(Sourceable&& source,
|
||||
item_event_visitor& visitor,
|
||||
const cbor_decode_options& options = cbor_decode_options(),
|
||||
const Allocator alloc=Allocator())
|
||||
: parser_(std::forward<Sourceable>(source), options, alloc),
|
||||
visitor_(visitor)
|
||||
{
|
||||
}
|
||||
|
||||
void read()
|
||||
{
|
||||
std::error_code ec;
|
||||
read(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,line(),column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read(std::error_code& ec)
|
||||
{
|
||||
parser_.reset();
|
||||
parser_.parse(visitor_, ec);
|
||||
if (ec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t line() const
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
};
|
||||
|
||||
using cbor_stream_reader = basic_cbor_reader<jsoncons::binary_stream_source>;
|
||||
|
||||
using cbor_bytes_reader = basic_cbor_reader<jsoncons::bytes_source>;
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use cbor_stream_reader") typedef cbor_stream_reader cbor_reader;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use cbor_bytes_reader") typedef cbor_bytes_reader cbor_buffer_reader;
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
203
scripts/exe/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp
Normal file
203
scripts/exe/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
// Copyright 2017-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CBOR_DECODE_CBOR_HPP
|
||||
#define JSONCONS_CBOR_DECODE_CBOR_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <type_traits> // std::enable_if
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/json_filter.hpp>
|
||||
#include <jsoncons/decode_traits.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_reader.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_cursor.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace cbor {
|
||||
|
||||
template<class T, class Source>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_byte_sequence<Source>::value,T>::type
|
||||
decode_cbor(const Source& v,
|
||||
const cbor_decode_options& options = cbor_decode_options())
|
||||
{
|
||||
jsoncons::json_decoder<T> decoder;
|
||||
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
||||
basic_cbor_reader<jsoncons::bytes_source> reader(v, adaptor, options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template<class T, class Source>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_byte_sequence<Source>::value,T>::type
|
||||
decode_cbor(const Source& v,
|
||||
const cbor_decode_options& options = cbor_decode_options())
|
||||
{
|
||||
basic_cbor_cursor<bytes_source> cursor(v, options);
|
||||
json_decoder<basic_json<char,sorted_policy>> decoder{};
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_cbor(std::istream& is,
|
||||
const cbor_decode_options& options = cbor_decode_options())
|
||||
{
|
||||
jsoncons::json_decoder<T> decoder;
|
||||
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
||||
cbor_stream_reader reader(is, adaptor, options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_cbor(std::istream& is,
|
||||
const cbor_decode_options& options = cbor_decode_options())
|
||||
{
|
||||
basic_cbor_cursor<binary_stream_source> cursor(is, options);
|
||||
json_decoder<basic_json<char,sorted_policy>> decoder{};
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T, class InputIt>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_cbor(InputIt first, InputIt last,
|
||||
const cbor_decode_options& options = cbor_decode_options())
|
||||
{
|
||||
jsoncons::json_decoder<T> decoder;
|
||||
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
||||
basic_cbor_reader<binary_iterator_source<InputIt>> reader(binary_iterator_source<InputIt>(first, last), adaptor, options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template<class T, class InputIt>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_cbor(InputIt first, InputIt last,
|
||||
const cbor_decode_options& options = cbor_decode_options())
|
||||
{
|
||||
basic_cbor_cursor<binary_iterator_source<InputIt>> cursor(binary_iterator_source<InputIt>(first, last), options);
|
||||
json_decoder<basic_json<char,sorted_policy>> decoder{};
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// With leading allocator parameter
|
||||
|
||||
template<class T, class Source, class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_byte_sequence<Source>::value,T>::type
|
||||
decode_cbor(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const Source& v,
|
||||
const cbor_decode_options& options = cbor_decode_options())
|
||||
{
|
||||
json_decoder<T,TempAllocator> decoder(temp_alloc);
|
||||
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
||||
basic_cbor_reader<jsoncons::bytes_source,TempAllocator> reader(v, adaptor, options, temp_alloc);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template<class T, class Source, class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_byte_sequence<Source>::value,T>::type
|
||||
decode_cbor(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const Source& v,
|
||||
const cbor_decode_options& options = cbor_decode_options())
|
||||
{
|
||||
basic_cbor_cursor<bytes_source,TempAllocator> cursor(v, options, temp_alloc);
|
||||
json_decoder<basic_json<char,sorted_policy,TempAllocator>,TempAllocator> decoder(temp_alloc, temp_alloc);
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T,class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_cbor(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
std::istream& is,
|
||||
const cbor_decode_options& options = cbor_decode_options())
|
||||
{
|
||||
json_decoder<T,TempAllocator> decoder(temp_alloc);
|
||||
auto adaptor = make_json_visitor_adaptor<json_visitor>(decoder);
|
||||
basic_cbor_reader<jsoncons::binary_stream_source,TempAllocator> reader(is, adaptor, options, temp_alloc);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template<class T,class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_cbor(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
std::istream& is,
|
||||
const cbor_decode_options& options = cbor_decode_options())
|
||||
{
|
||||
basic_cbor_cursor<binary_stream_source,TempAllocator> cursor(is, options, temp_alloc);
|
||||
json_decoder<basic_json<char,sorted_policy,TempAllocator>,TempAllocator> decoder(temp_alloc, temp_alloc);
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
} // namespace cbor
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
151
scripts/exe/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp
Normal file
151
scripts/exe/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Copyright 2017-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CBOR_ENCODE_CBOR_HPP
|
||||
#define JSONCONS_CBOR_ENCODE_CBOR_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <type_traits> // std::enable_if
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/json_filter.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/encode_traits.hpp>
|
||||
#include <jsoncons_ext/cbor/cbor_encoder.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace cbor {
|
||||
|
||||
// to bytes
|
||||
|
||||
template<class T, class Container>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<Container>::value,void>::type
|
||||
encode_cbor(const T& j,
|
||||
Container& v,
|
||||
const cbor_encode_options& options = cbor_encode_options())
|
||||
{
|
||||
using char_type = typename T::char_type;
|
||||
basic_cbor_encoder<jsoncons::bytes_sink<Container>> encoder(v, options);
|
||||
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
||||
j.dump(adaptor);
|
||||
}
|
||||
|
||||
template<class T, class Container>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<Container>::value,void>::type
|
||||
encode_cbor(const T& val, Container& v,
|
||||
const cbor_encode_options& options = cbor_encode_options())
|
||||
{
|
||||
basic_cbor_encoder<jsoncons::bytes_sink<Container>> encoder(v, options);
|
||||
std::error_code ec;
|
||||
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
// stream
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_cbor(const T& j,
|
||||
std::ostream& os,
|
||||
const cbor_encode_options& options = cbor_encode_options())
|
||||
{
|
||||
using char_type = typename T::char_type;
|
||||
cbor_stream_encoder encoder(os, options);
|
||||
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
||||
j.dump(adaptor);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_cbor(const T& val,
|
||||
std::ostream& os,
|
||||
const cbor_encode_options& options = cbor_encode_options())
|
||||
{
|
||||
cbor_stream_encoder encoder(os, options);
|
||||
std::error_code ec;
|
||||
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
// temp_allocator_arg
|
||||
|
||||
// to bytes
|
||||
|
||||
template<class T, class Container, class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<Container>::value,void>::type
|
||||
encode_cbor(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& j,
|
||||
Container& v,
|
||||
const cbor_encode_options& options = cbor_encode_options())
|
||||
{
|
||||
using char_type = typename T::char_type;
|
||||
basic_cbor_encoder<bytes_sink<Container>,TempAllocator> encoder(v, options, temp_alloc);
|
||||
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
||||
j.dump(adaptor);
|
||||
}
|
||||
|
||||
template<class T, class Container, class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_byte_container<Container>::value,void>::type
|
||||
encode_cbor(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
Container& v,
|
||||
const cbor_encode_options& options = cbor_encode_options())
|
||||
{
|
||||
basic_cbor_encoder<jsoncons::bytes_sink<Container>,TempAllocator> encoder(v, options, temp_alloc);
|
||||
std::error_code ec;
|
||||
encode_traits<T,char>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
// stream
|
||||
|
||||
template<class T,class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_cbor(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& j,
|
||||
std::ostream& os,
|
||||
const cbor_encode_options& options = cbor_encode_options())
|
||||
{
|
||||
using char_type = typename T::char_type;
|
||||
basic_cbor_encoder<binary_stream_sink,TempAllocator> encoder(os, options, temp_alloc);
|
||||
auto adaptor = make_json_visitor_adaptor<basic_json_visitor<char_type>>(encoder);
|
||||
j.dump(adaptor);
|
||||
}
|
||||
|
||||
template<class T,class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_cbor(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val,
|
||||
std::ostream& os,
|
||||
const cbor_encode_options& options = cbor_encode_options())
|
||||
{
|
||||
std::error_code ec;
|
||||
encode_cbor(temp_allocator_arg, temp_alloc, val, os, options, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cbor
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
17
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv.hpp
Normal file
17
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CSV_CSV_HPP
|
||||
#define JSONCONS_CSV_CSV_HPP
|
||||
|
||||
#include <jsoncons_ext/csv/csv_options.hpp>
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
#include <jsoncons_ext/csv/csv_encoder.hpp>
|
||||
#include <jsoncons_ext/csv/csv_cursor.hpp>
|
||||
#include <jsoncons_ext/csv/decode_csv.hpp>
|
||||
#include <jsoncons_ext/csv/encode_csv.hpp>
|
||||
|
||||
#endif
|
||||
358
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp
Normal file
358
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CSV_CSV_CURSOR_HPP
|
||||
#define JSONCONS_CSV_CSV_CURSOR_HPP
|
||||
|
||||
#include <memory> // std::allocator
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <ios>
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/byte_string.hpp>
|
||||
#include <jsoncons/config/jsoncons_config.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons_ext/csv/csv_parser.hpp>
|
||||
#include <jsoncons/staj_cursor.hpp>
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons/source_adaptor.hpp>
|
||||
|
||||
namespace jsoncons { namespace csv {
|
||||
|
||||
template<class CharT,class Source=jsoncons::stream_source<CharT>,class Allocator=std::allocator<char>>
|
||||
class basic_csv_cursor : public basic_staj_cursor<CharT>, private virtual ser_context
|
||||
{
|
||||
public:
|
||||
using source_type = Source;
|
||||
using char_type = CharT;
|
||||
using allocator_type = Allocator;
|
||||
private:
|
||||
static constexpr size_t default_max_buffer_size = 16384;
|
||||
|
||||
typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<CharT> char_allocator_type;
|
||||
|
||||
text_source_adaptor<Source> source_;
|
||||
basic_csv_parser<CharT,Allocator> parser_;
|
||||
basic_staj_visitor<CharT> cursor_visitor_;
|
||||
|
||||
// Noncopyable and nonmoveable
|
||||
basic_csv_cursor(const basic_csv_cursor&) = delete;
|
||||
basic_csv_cursor& operator=(const basic_csv_cursor&) = delete;
|
||||
|
||||
public:
|
||||
using string_view_type = jsoncons::basic_string_view<CharT>;
|
||||
|
||||
// Constructors that throw parse exceptions
|
||||
|
||||
template <class Sourceable>
|
||||
basic_csv_cursor(Sourceable&& source,
|
||||
const basic_csv_decode_options<CharT>& options = basic_csv_decode_options<CharT>(),
|
||||
std::function<bool(csv_errc,const ser_context&)> err_handler = default_csv_parsing(),
|
||||
const Allocator& alloc = Allocator(),
|
||||
typename std::enable_if<!std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
parser_(options,err_handler,alloc),
|
||||
cursor_visitor_(accept_all)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_csv_cursor(Sourceable&& source,
|
||||
const basic_csv_decode_options<CharT>& options = basic_csv_decode_options<CharT>(),
|
||||
std::function<bool(csv_errc,const ser_context&)> err_handler = default_csv_parsing(),
|
||||
const Allocator& alloc = Allocator(),
|
||||
typename std::enable_if<std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(),
|
||||
parser_(options,err_handler,alloc),
|
||||
cursor_visitor_(accept_all)
|
||||
{
|
||||
jsoncons::basic_string_view<CharT> sv(std::forward<Sourceable>(source));
|
||||
initialize_with_string_view(sv);
|
||||
}
|
||||
|
||||
|
||||
// Constructors that set parse error codes
|
||||
template <class Sourceable>
|
||||
basic_csv_cursor(Sourceable&& source,
|
||||
std::error_code& ec)
|
||||
: basic_csv_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
basic_csv_decode_options<CharT>(),
|
||||
default_csv_parsing(),
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_csv_cursor(Sourceable&& source,
|
||||
const basic_csv_decode_options<CharT>& options,
|
||||
std::error_code& ec)
|
||||
: basic_csv_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
options,
|
||||
default_csv_parsing(),
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_csv_cursor(Sourceable&& source,
|
||||
const basic_csv_decode_options<CharT>& options,
|
||||
std::function<bool(csv_errc,const ser_context&)> err_handler,
|
||||
std::error_code& ec)
|
||||
: basic_csv_cursor(std::allocator_arg, Allocator(),
|
||||
std::forward<Sourceable>(source),
|
||||
options,
|
||||
err_handler,
|
||||
ec)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_csv_cursor(std::allocator_arg_t, const Allocator& alloc,
|
||||
Sourceable&& source,
|
||||
const basic_csv_decode_options<CharT>& options,
|
||||
std::function<bool(csv_errc,const ser_context&)> err_handler,
|
||||
std::error_code& ec,
|
||||
typename std::enable_if<!std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
parser_(options,err_handler,alloc),
|
||||
cursor_visitor_(accept_all)
|
||||
{
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_csv_cursor(std::allocator_arg_t, const Allocator& alloc,
|
||||
Sourceable&& source,
|
||||
const basic_csv_decode_options<CharT>& options,
|
||||
std::function<bool(csv_errc,const ser_context&)> err_handler,
|
||||
std::error_code& ec,
|
||||
typename std::enable_if<std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(),
|
||||
parser_(options,err_handler,alloc),
|
||||
cursor_visitor_(accept_all)
|
||||
{
|
||||
jsoncons::basic_string_view<CharT> sv(std::forward<Sourceable>(source));
|
||||
initialize_with_string_view(sv, ec);
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
typename std::enable_if<!std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type
|
||||
reset(Sourceable&& source)
|
||||
{
|
||||
source_ = std::forward<Sourceable>(source);
|
||||
parser_.reinitialize();
|
||||
cursor_visitor_.reset();
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
typename std::enable_if<std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type
|
||||
reset(Sourceable&& source)
|
||||
{
|
||||
source_ = {};
|
||||
parser_.reinitialize();
|
||||
cursor_visitor_.reset();
|
||||
initialize_with_string_view(std::forward<Sourceable>(source));
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
typename std::enable_if<!std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type
|
||||
reset(Sourceable&& source, std::error_code& ec)
|
||||
{
|
||||
source_ = std::forward<Sourceable>(source);
|
||||
parser_.reinitialize();
|
||||
cursor_visitor_.reset();
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
typename std::enable_if<std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type
|
||||
reset(Sourceable&& source, std::error_code& ec)
|
||||
{
|
||||
source_ = {};
|
||||
parser_.reinitialize();
|
||||
initialize_with_string_view(std::forward<Sourceable>(source), ec);
|
||||
}
|
||||
|
||||
bool done() const override
|
||||
{
|
||||
return parser_.done();
|
||||
}
|
||||
|
||||
const basic_staj_event<CharT>& current() const override
|
||||
{
|
||||
return cursor_visitor_.event();
|
||||
}
|
||||
|
||||
void read_to(basic_json_visitor<CharT>& visitor) override
|
||||
{
|
||||
std::error_code ec;
|
||||
read_to(visitor, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read_to(basic_json_visitor<CharT>& visitor,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
if (send_json_event(cursor_visitor_.event(), visitor, *this, ec))
|
||||
{
|
||||
read_next(visitor, ec);
|
||||
}
|
||||
}
|
||||
|
||||
void next() override
|
||||
{
|
||||
std::error_code ec;
|
||||
next(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void next(std::error_code& ec) override
|
||||
{
|
||||
read_next(ec);
|
||||
}
|
||||
|
||||
static bool accept_all(const basic_staj_event<CharT>&, const ser_context&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const ser_context& context() const override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return parser_.source_exhausted() && source_.eof();
|
||||
}
|
||||
|
||||
std::size_t line() const override
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const override
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
|
||||
friend
|
||||
basic_staj_filter_view<CharT> operator|(basic_csv_cursor& cursor,
|
||||
std::function<bool(const basic_staj_event<CharT>&, const ser_context&)> pred)
|
||||
{
|
||||
return basic_staj_filter_view<CharT>(cursor, pred);
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use read_to(basic_json_visitor<CharT>&)")
|
||||
void read(basic_json_visitor<CharT>& visitor)
|
||||
{
|
||||
read_to(visitor);
|
||||
}
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use read_to(basic_json_visitor<CharT>&, std::error_code&)")
|
||||
void read(basic_json_visitor<CharT>& visitor,
|
||||
std::error_code& ec)
|
||||
{
|
||||
read_to(visitor, ec);
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
|
||||
void initialize_with_string_view(string_view_type sv)
|
||||
{
|
||||
auto r = unicode_traits::detect_json_encoding(sv.data(), sv.size());
|
||||
if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected))
|
||||
{
|
||||
JSONCONS_THROW(ser_error(json_errc::illegal_unicode_character,parser_.line(),parser_.column()));
|
||||
}
|
||||
std::size_t offset = (r.ptr - sv.data());
|
||||
parser_.update(sv.data()+offset,sv.size()-offset);
|
||||
if (!done())
|
||||
{
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
void initialize_with_string_view(string_view_type sv, std::error_code& ec)
|
||||
{
|
||||
auto r = unicode_traits::detect_encoding_from_bom(sv.data(), sv.size());
|
||||
if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected))
|
||||
{
|
||||
ec = json_errc::illegal_unicode_character;
|
||||
return;
|
||||
}
|
||||
std::size_t offset = (r.ptr - sv.data());
|
||||
parser_.update(sv.data()+offset,sv.size()-offset);
|
||||
if (!done())
|
||||
{
|
||||
next(ec);
|
||||
}
|
||||
}
|
||||
|
||||
void read_next(std::error_code& ec)
|
||||
{
|
||||
read_next(cursor_visitor_, ec);
|
||||
}
|
||||
|
||||
void read_next(basic_json_visitor<CharT>& visitor, std::error_code& ec)
|
||||
{
|
||||
parser_.restart();
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
}
|
||||
}
|
||||
parser_.parse_some(visitor, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using csv_stream_cursor = basic_csv_cursor<char,jsoncons::stream_source<char>>;
|
||||
using csv_string_cursor = basic_csv_cursor<char,jsoncons::string_source<char>>;
|
||||
using wcsv_stream_cursor = basic_csv_cursor<wchar_t,jsoncons::stream_source<wchar_t>>;
|
||||
using wcsv_string_cursor = basic_csv_cursor<wchar_t,jsoncons::string_source<wchar_t>>;
|
||||
|
||||
using csv_cursor = basic_csv_cursor<char>;
|
||||
using wcsv_cursor = basic_csv_cursor<wchar_t>;
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
954
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp
Normal file
954
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp
Normal file
|
|
@ -0,0 +1,954 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CSV_CSV_ENCODER_HPP
|
||||
#define JSONCONS_CSV_CSV_ENCODER_HPP
|
||||
|
||||
#include <array> // std::array
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <utility> // std::move
|
||||
#include <unordered_map> // std::unordered_map
|
||||
#include <memory> // std::allocator
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons/detail/write_number.hpp>
|
||||
#include <jsoncons_ext/csv/csv_options.hpp>
|
||||
#include <jsoncons/sink.hpp>
|
||||
|
||||
namespace jsoncons { namespace csv {
|
||||
|
||||
template<class CharT,class Sink=jsoncons::stream_sink<CharT>,class Allocator=std::allocator<char>>
|
||||
class basic_csv_encoder final : public basic_json_visitor<CharT>
|
||||
{
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using typename basic_json_visitor<CharT>::string_view_type;
|
||||
using sink_type = Sink;
|
||||
|
||||
using allocator_type = Allocator;
|
||||
using char_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<CharT>;
|
||||
using string_type = std::basic_string<CharT, std::char_traits<CharT>, char_allocator_type>;
|
||||
using string_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<string_type>;
|
||||
using string_string_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<std::pair<const string_type,string_type>>;
|
||||
|
||||
private:
|
||||
static jsoncons::basic_string_view<CharT> null_constant()
|
||||
{
|
||||
static jsoncons::basic_string_view<CharT> k = JSONCONS_STRING_VIEW_CONSTANT(CharT,"null");
|
||||
return k;
|
||||
}
|
||||
static jsoncons::basic_string_view<CharT> true_constant()
|
||||
{
|
||||
static jsoncons::basic_string_view<CharT> k = JSONCONS_STRING_VIEW_CONSTANT(CharT,"true");
|
||||
return k;
|
||||
}
|
||||
static jsoncons::basic_string_view<CharT> false_constant()
|
||||
{
|
||||
static jsoncons::basic_string_view<CharT> k = JSONCONS_STRING_VIEW_CONSTANT(CharT,"false");
|
||||
return k;
|
||||
}
|
||||
|
||||
enum class stack_item_kind
|
||||
{
|
||||
row_mapping,
|
||||
column_mapping,
|
||||
object,
|
||||
row,
|
||||
column,
|
||||
object_multi_valued_field,
|
||||
row_multi_valued_field,
|
||||
column_multi_valued_field
|
||||
};
|
||||
|
||||
struct stack_item
|
||||
{
|
||||
stack_item_kind item_kind_;
|
||||
std::size_t count_;
|
||||
|
||||
stack_item(stack_item_kind item_kind) noexcept
|
||||
: item_kind_(item_kind), count_(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_object() const
|
||||
{
|
||||
return item_kind_ == stack_item_kind::object;
|
||||
}
|
||||
|
||||
stack_item_kind item_kind() const
|
||||
{
|
||||
return item_kind_;
|
||||
}
|
||||
};
|
||||
|
||||
Sink sink_;
|
||||
const basic_csv_encode_options<CharT> options_;
|
||||
allocator_type alloc_;
|
||||
|
||||
std::vector<stack_item> stack_;
|
||||
jsoncons::detail::write_double fp_;
|
||||
std::vector<string_type,string_allocator_type> strings_buffer_;
|
||||
|
||||
std::unordered_map<string_type,string_type, std::hash<string_type>,std::equal_to<string_type>,string_string_allocator_type> buffered_line_;
|
||||
string_type name_;
|
||||
std::size_t column_index_;
|
||||
std::vector<std::size_t> row_counts_;
|
||||
|
||||
// Noncopyable and nonmoveable
|
||||
basic_csv_encoder(const basic_csv_encoder&) = delete;
|
||||
basic_csv_encoder& operator=(const basic_csv_encoder&) = delete;
|
||||
public:
|
||||
basic_csv_encoder(Sink&& sink,
|
||||
const Allocator& alloc = Allocator())
|
||||
: basic_csv_encoder(std::forward<Sink>(sink), basic_csv_encode_options<CharT>(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
basic_csv_encoder(Sink&& sink,
|
||||
const basic_csv_encode_options<CharT>& options,
|
||||
const Allocator& alloc = Allocator())
|
||||
: sink_(std::forward<Sink>(sink)),
|
||||
options_(options),
|
||||
alloc_(alloc),
|
||||
stack_(),
|
||||
fp_(options.float_format(), options.precision()),
|
||||
column_index_(0)
|
||||
{
|
||||
jsoncons::csv::detail::parse_column_names(options.column_names(), strings_buffer_);
|
||||
}
|
||||
|
||||
~basic_csv_encoder() noexcept
|
||||
{
|
||||
JSONCONS_TRY
|
||||
{
|
||||
sink_.flush();
|
||||
}
|
||||
JSONCONS_CATCH(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
stack_.clear();
|
||||
strings_buffer_.clear();
|
||||
buffered_line_.clear();
|
||||
name_.clear();
|
||||
column_index_ = 0;
|
||||
row_counts_.clear();
|
||||
}
|
||||
|
||||
void reset(Sink&& sink)
|
||||
{
|
||||
sink_ = std::move(sink);
|
||||
reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<class AnyWriter>
|
||||
void escape_string(const CharT* s,
|
||||
std::size_t length,
|
||||
CharT quote_char, CharT quote_escape_char,
|
||||
AnyWriter& sink)
|
||||
{
|
||||
const CharT* begin = s;
|
||||
const CharT* end = s + length;
|
||||
for (const CharT* it = begin; it != end; ++it)
|
||||
{
|
||||
CharT c = *it;
|
||||
if (c == quote_char)
|
||||
{
|
||||
sink.push_back(quote_escape_char);
|
||||
sink.push_back(quote_char);
|
||||
}
|
||||
else
|
||||
{
|
||||
sink.push_back(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visit_flush() override
|
||||
{
|
||||
sink_.flush();
|
||||
}
|
||||
|
||||
bool visit_begin_object(semantic_tag, const ser_context&, std::error_code& ec) override
|
||||
{
|
||||
if (stack_.empty())
|
||||
{
|
||||
stack_.emplace_back(stack_item_kind::column_mapping);
|
||||
return true;
|
||||
}
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::row_mapping:
|
||||
stack_.emplace_back(stack_item_kind::object);
|
||||
return true;
|
||||
default: // error
|
||||
ec = csv_errc::source_error;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool visit_end_object(const ser_context&, std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::object:
|
||||
if (stack_[0].count_ == 0)
|
||||
{
|
||||
for (std::size_t i = 0; i < strings_buffer_.size(); ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
sink_.push_back(options_.field_delimiter());
|
||||
}
|
||||
sink_.append(strings_buffer_[i].data(),
|
||||
strings_buffer_[i].length());
|
||||
}
|
||||
sink_.append(options_.line_delimiter().data(),
|
||||
options_.line_delimiter().length());
|
||||
}
|
||||
for (std::size_t i = 0; i < strings_buffer_.size(); ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
sink_.push_back(options_.field_delimiter());
|
||||
}
|
||||
auto it = buffered_line_.find(strings_buffer_[i]);
|
||||
if (it != buffered_line_.end())
|
||||
{
|
||||
sink_.append(it->second.data(),it->second.length());
|
||||
it->second.clear();
|
||||
}
|
||||
}
|
||||
sink_.append(options_.line_delimiter().data(), options_.line_delimiter().length());
|
||||
break;
|
||||
case stack_item_kind::column_mapping:
|
||||
{
|
||||
for (const auto& item : strings_buffer_)
|
||||
{
|
||||
sink_.append(item.data(), item.size());
|
||||
sink_.append(options_.line_delimiter().data(), options_.line_delimiter().length());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
stack_.pop_back();
|
||||
if (!stack_.empty())
|
||||
{
|
||||
end_value();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_begin_array(semantic_tag, const ser_context&, std::error_code& ec) override
|
||||
{
|
||||
if (stack_.empty())
|
||||
{
|
||||
stack_.emplace_back(stack_item_kind::row_mapping);
|
||||
return true;
|
||||
}
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::row_mapping:
|
||||
stack_.emplace_back(stack_item_kind::row);
|
||||
if (stack_[0].count_ == 0)
|
||||
{
|
||||
for (std::size_t i = 0; i < strings_buffer_.size(); ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
sink_.push_back(options_.field_delimiter());
|
||||
}
|
||||
sink_.append(strings_buffer_[i].data(),strings_buffer_[i].length());
|
||||
}
|
||||
if (strings_buffer_.size() > 0)
|
||||
{
|
||||
sink_.append(options_.line_delimiter().data(),
|
||||
options_.line_delimiter().length());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case stack_item_kind::object:
|
||||
stack_.emplace_back(stack_item_kind::object_multi_valued_field);
|
||||
return true;
|
||||
case stack_item_kind::column_mapping:
|
||||
stack_.emplace_back(stack_item_kind::column);
|
||||
row_counts_.push_back(1);
|
||||
if (strings_buffer_.size() <= row_counts_.back())
|
||||
{
|
||||
strings_buffer_.emplace_back();
|
||||
}
|
||||
return true;
|
||||
case stack_item_kind::column:
|
||||
{
|
||||
if (strings_buffer_.size() <= row_counts_.back())
|
||||
{
|
||||
strings_buffer_.emplace_back();
|
||||
}
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
begin_value(bo);
|
||||
stack_.emplace_back(stack_item_kind::column_multi_valued_field);
|
||||
return true;
|
||||
}
|
||||
case stack_item_kind::row:
|
||||
begin_value(sink_);
|
||||
stack_.emplace_back(stack_item_kind::row_multi_valued_field);
|
||||
return true;
|
||||
default: // error
|
||||
ec = csv_errc::source_error;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool visit_end_array(const ser_context&, std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::row:
|
||||
sink_.append(options_.line_delimiter().data(),
|
||||
options_.line_delimiter().length());
|
||||
break;
|
||||
case stack_item_kind::column:
|
||||
++column_index_;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
stack_.pop_back();
|
||||
|
||||
if (!stack_.empty())
|
||||
{
|
||||
end_value();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_key(const string_view_type& name, const ser_context&, std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::object:
|
||||
{
|
||||
name_ = string_type(name);
|
||||
buffered_line_[string_type(name)] = std::basic_string<CharT>();
|
||||
if (stack_[0].count_ == 0 && options_.column_names().size() == 0)
|
||||
{
|
||||
strings_buffer_.emplace_back(name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::column_mapping:
|
||||
{
|
||||
if (strings_buffer_.empty())
|
||||
{
|
||||
strings_buffer_.emplace_back(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
strings_buffer_[0].push_back(options_.field_delimiter());
|
||||
strings_buffer_[0].append(string_type(name));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_null(semantic_tag, const ser_context&, std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::object:
|
||||
case stack_item_kind::object_multi_valued_field:
|
||||
{
|
||||
auto it = buffered_line_.find(name_);
|
||||
if (it != buffered_line_.end())
|
||||
{
|
||||
std::basic_string<CharT> s;
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
||||
write_null_value(bo);
|
||||
bo.flush();
|
||||
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
||||
{
|
||||
it->second.push_back(options_.subfield_delimiter());
|
||||
}
|
||||
it->second.append(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::row:
|
||||
case stack_item_kind::row_multi_valued_field:
|
||||
write_null_value(sink_);
|
||||
break;
|
||||
case stack_item_kind::column:
|
||||
{
|
||||
if (strings_buffer_.size() <= row_counts_.back())
|
||||
{
|
||||
strings_buffer_.emplace_back();
|
||||
}
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_null_value(bo);
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::column_multi_valued_field:
|
||||
{
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_null_value(bo);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_string(const string_view_type& sv, semantic_tag, const ser_context&, std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::object:
|
||||
case stack_item_kind::object_multi_valued_field:
|
||||
{
|
||||
auto it = buffered_line_.find(name_);
|
||||
if (it != buffered_line_.end())
|
||||
{
|
||||
std::basic_string<CharT> s;
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
||||
write_string_value(sv,bo);
|
||||
bo.flush();
|
||||
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
||||
{
|
||||
it->second.push_back(options_.subfield_delimiter());
|
||||
}
|
||||
it->second.append(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::row:
|
||||
case stack_item_kind::row_multi_valued_field:
|
||||
write_string_value(sv,sink_);
|
||||
break;
|
||||
case stack_item_kind::column:
|
||||
{
|
||||
if (strings_buffer_.size() <= row_counts_.back())
|
||||
{
|
||||
strings_buffer_.emplace_back();
|
||||
}
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_string_value(sv,bo);
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::column_multi_valued_field:
|
||||
{
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_string_value(sv,bo);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_byte_string(const byte_string_view& b,
|
||||
semantic_tag tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
byte_string_chars_format encoding_hint;
|
||||
switch (tag)
|
||||
{
|
||||
case semantic_tag::base16:
|
||||
encoding_hint = byte_string_chars_format::base16;
|
||||
break;
|
||||
case semantic_tag::base64:
|
||||
encoding_hint = byte_string_chars_format::base64;
|
||||
break;
|
||||
case semantic_tag::base64url:
|
||||
encoding_hint = byte_string_chars_format::base64url;
|
||||
break;
|
||||
default:
|
||||
encoding_hint = byte_string_chars_format::none;
|
||||
break;
|
||||
}
|
||||
byte_string_chars_format format = jsoncons::detail::resolve_byte_string_chars_format(encoding_hint,byte_string_chars_format::none,byte_string_chars_format::base64url);
|
||||
|
||||
std::basic_string<CharT> s;
|
||||
switch (format)
|
||||
{
|
||||
case byte_string_chars_format::base16:
|
||||
{
|
||||
encode_base16(b.begin(),b.end(),s);
|
||||
visit_string(s, semantic_tag::none, context, ec);
|
||||
break;
|
||||
}
|
||||
case byte_string_chars_format::base64:
|
||||
{
|
||||
encode_base64(b.begin(),b.end(),s);
|
||||
visit_string(s, semantic_tag::none, context, ec);
|
||||
break;
|
||||
}
|
||||
case byte_string_chars_format::base64url:
|
||||
{
|
||||
encode_base64url(b.begin(),b.end(),s);
|
||||
visit_string(s, semantic_tag::none, context, ec);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
JSONCONS_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_double(double val,
|
||||
semantic_tag,
|
||||
const ser_context& context,
|
||||
std::error_code& ec) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::object:
|
||||
case stack_item_kind::object_multi_valued_field:
|
||||
{
|
||||
auto it = buffered_line_.find(name_);
|
||||
if (it != buffered_line_.end())
|
||||
{
|
||||
std::basic_string<CharT> s;
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
||||
write_double_value(val, context, bo, ec);
|
||||
bo.flush();
|
||||
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
||||
{
|
||||
it->second.push_back(options_.subfield_delimiter());
|
||||
}
|
||||
it->second.append(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::row:
|
||||
case stack_item_kind::row_multi_valued_field:
|
||||
write_double_value(val, context, sink_, ec);
|
||||
break;
|
||||
case stack_item_kind::column:
|
||||
{
|
||||
if (strings_buffer_.size() <= row_counts_.back())
|
||||
{
|
||||
strings_buffer_.emplace_back();
|
||||
}
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_double_value(val, context, bo, ec);
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::column_multi_valued_field:
|
||||
{
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_double_value(val, context, bo, ec);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_int64(int64_t val,
|
||||
semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::object:
|
||||
case stack_item_kind::object_multi_valued_field:
|
||||
{
|
||||
auto it = buffered_line_.find(name_);
|
||||
if (it != buffered_line_.end())
|
||||
{
|
||||
std::basic_string<CharT> s;
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
||||
write_int64_value(val,bo);
|
||||
bo.flush();
|
||||
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
||||
{
|
||||
it->second.push_back(options_.subfield_delimiter());
|
||||
}
|
||||
it->second.append(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::row:
|
||||
case stack_item_kind::row_multi_valued_field:
|
||||
write_int64_value(val,sink_);
|
||||
break;
|
||||
case stack_item_kind::column:
|
||||
{
|
||||
if (strings_buffer_.size() <= row_counts_.back())
|
||||
{
|
||||
strings_buffer_.emplace_back();
|
||||
}
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_int64_value(val, bo);
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::column_multi_valued_field:
|
||||
{
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_int64_value(val, bo);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_uint64(uint64_t val,
|
||||
semantic_tag,
|
||||
const ser_context&,
|
||||
std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::object:
|
||||
case stack_item_kind::object_multi_valued_field:
|
||||
{
|
||||
auto it = buffered_line_.find(name_);
|
||||
if (it != buffered_line_.end())
|
||||
{
|
||||
std::basic_string<CharT> s;
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
||||
write_uint64_value(val, bo);
|
||||
bo.flush();
|
||||
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
||||
{
|
||||
it->second.push_back(options_.subfield_delimiter());
|
||||
}
|
||||
it->second.append(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::row:
|
||||
case stack_item_kind::row_multi_valued_field:
|
||||
write_uint64_value(val,sink_);
|
||||
break;
|
||||
case stack_item_kind::column:
|
||||
{
|
||||
if (strings_buffer_.size() <= row_counts_.back())
|
||||
{
|
||||
strings_buffer_.emplace_back();
|
||||
}
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_uint64_value(val, bo);
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::column_multi_valued_field:
|
||||
{
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_uint64_value(val, bo);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visit_bool(bool val, semantic_tag, const ser_context&, std::error_code&) override
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::object:
|
||||
case stack_item_kind::object_multi_valued_field:
|
||||
{
|
||||
auto it = buffered_line_.find(name_);
|
||||
if (it != buffered_line_.end())
|
||||
{
|
||||
std::basic_string<CharT> s;
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
||||
write_bool_value(val,bo);
|
||||
bo.flush();
|
||||
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
||||
{
|
||||
it->second.push_back(options_.subfield_delimiter());
|
||||
}
|
||||
it->second.append(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::row:
|
||||
case stack_item_kind::row_multi_valued_field:
|
||||
write_bool_value(val,sink_);
|
||||
break;
|
||||
case stack_item_kind::column:
|
||||
{
|
||||
if (strings_buffer_.size() <= row_counts_.back())
|
||||
{
|
||||
strings_buffer_.emplace_back();
|
||||
}
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_bool_value(val, bo);
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::column_multi_valued_field:
|
||||
{
|
||||
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
||||
write_bool_value(val, bo);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class AnyWriter>
|
||||
bool do_string_value(const CharT* s, std::size_t length, AnyWriter& sink)
|
||||
{
|
||||
bool quote = false;
|
||||
if (options_.quote_style() == quote_style_kind::all || options_.quote_style() == quote_style_kind::nonnumeric ||
|
||||
(options_.quote_style() == quote_style_kind::minimal &&
|
||||
(std::char_traits<CharT>::find(s, length, options_.field_delimiter()) != nullptr || std::char_traits<CharT>::find(s, length, options_.quote_char()) != nullptr)))
|
||||
{
|
||||
quote = true;
|
||||
sink.push_back(options_.quote_char());
|
||||
}
|
||||
escape_string(s, length, options_.quote_char(), options_.quote_escape_char(), sink);
|
||||
if (quote)
|
||||
{
|
||||
sink.push_back(options_.quote_char());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class AnyWriter>
|
||||
void write_string_value(const string_view_type& value, AnyWriter& sink)
|
||||
{
|
||||
begin_value(sink);
|
||||
do_string_value(value.data(),value.length(),sink);
|
||||
end_value();
|
||||
}
|
||||
|
||||
template <class AnyWriter>
|
||||
void write_double_value(double val, const ser_context& context, AnyWriter& sink, std::error_code& ec)
|
||||
{
|
||||
begin_value(sink);
|
||||
|
||||
if (!std::isfinite(val))
|
||||
{
|
||||
if ((std::isnan)(val))
|
||||
{
|
||||
if (options_.enable_nan_to_num())
|
||||
{
|
||||
sink.append(options_.nan_to_num().data(), options_.nan_to_num().length());
|
||||
}
|
||||
else if (options_.enable_nan_to_str())
|
||||
{
|
||||
visit_string(options_.nan_to_str(), semantic_tag::none, context, ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
sink.append(null_constant().data(), null_constant().size());
|
||||
}
|
||||
}
|
||||
else if (val == std::numeric_limits<double>::infinity())
|
||||
{
|
||||
if (options_.enable_inf_to_num())
|
||||
{
|
||||
sink.append(options_.inf_to_num().data(), options_.inf_to_num().length());
|
||||
}
|
||||
else if (options_.enable_inf_to_str())
|
||||
{
|
||||
visit_string(options_.inf_to_str(), semantic_tag::none, context, ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
sink.append(null_constant().data(), null_constant().size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (options_.enable_neginf_to_num())
|
||||
{
|
||||
sink.append(options_.neginf_to_num().data(), options_.neginf_to_num().length());
|
||||
}
|
||||
else if (options_.enable_neginf_to_str())
|
||||
{
|
||||
visit_string(options_.neginf_to_str(), semantic_tag::none, context, ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
sink.append(null_constant().data(), null_constant().size());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fp_(val, sink);
|
||||
}
|
||||
|
||||
end_value();
|
||||
|
||||
}
|
||||
|
||||
template <class AnyWriter>
|
||||
void write_int64_value(int64_t val, AnyWriter& sink)
|
||||
{
|
||||
begin_value(sink);
|
||||
|
||||
jsoncons::detail::from_integer(val,sink);
|
||||
|
||||
end_value();
|
||||
}
|
||||
|
||||
template <class AnyWriter>
|
||||
void write_uint64_value(uint64_t val, AnyWriter& sink)
|
||||
{
|
||||
begin_value(sink);
|
||||
|
||||
jsoncons::detail::from_integer(val,sink);
|
||||
|
||||
end_value();
|
||||
}
|
||||
|
||||
template <class AnyWriter>
|
||||
void write_bool_value(bool val, AnyWriter& sink)
|
||||
{
|
||||
begin_value(sink);
|
||||
|
||||
if (val)
|
||||
{
|
||||
sink.append(true_constant().data(), true_constant().size());
|
||||
}
|
||||
else
|
||||
{
|
||||
sink.append(false_constant().data(), false_constant().size());
|
||||
}
|
||||
|
||||
end_value();
|
||||
}
|
||||
|
||||
template <class AnyWriter>
|
||||
bool write_null_value(AnyWriter& sink)
|
||||
{
|
||||
begin_value(sink);
|
||||
sink.append(null_constant().data(), null_constant().size());
|
||||
end_value();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class AnyWriter>
|
||||
void begin_value(AnyWriter& sink)
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
switch (stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::row:
|
||||
if (stack_.back().count_ > 0)
|
||||
{
|
||||
sink.push_back(options_.field_delimiter());
|
||||
}
|
||||
break;
|
||||
case stack_item_kind::column:
|
||||
{
|
||||
if (row_counts_.size() >= 3)
|
||||
{
|
||||
for (std::size_t i = row_counts_.size()-2; i-- > 0;)
|
||||
{
|
||||
if (row_counts_[i] <= row_counts_.back())
|
||||
{
|
||||
sink.push_back(options_.field_delimiter());
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (column_index_ > 0)
|
||||
{
|
||||
sink.push_back(options_.field_delimiter());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::row_multi_valued_field:
|
||||
case stack_item_kind::column_multi_valued_field:
|
||||
if (stack_.back().count_ > 0 && options_.subfield_delimiter() != char_type())
|
||||
{
|
||||
sink.push_back(options_.subfield_delimiter());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void end_value()
|
||||
{
|
||||
JSONCONS_ASSERT(!stack_.empty());
|
||||
switch(stack_.back().item_kind_)
|
||||
{
|
||||
case stack_item_kind::row:
|
||||
{
|
||||
++stack_.back().count_;
|
||||
break;
|
||||
}
|
||||
case stack_item_kind::column:
|
||||
{
|
||||
++row_counts_.back();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
++stack_.back().count_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using csv_stream_encoder = basic_csv_encoder<char>;
|
||||
using csv_string_encoder = basic_csv_encoder<char,jsoncons::string_sink<std::string>>;
|
||||
using csv_wstream_encoder = basic_csv_encoder<wchar_t>;
|
||||
using wcsv_string_encoder = basic_csv_encoder<wchar_t,jsoncons::string_sink<std::wstring>>;
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
template<class CharT, class Sink = jsoncons::stream_sink<CharT>, class Allocator = std::allocator<CharT>>
|
||||
using basic_csv_serializer = basic_csv_encoder<CharT,Sink,Allocator>;
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use csv_stream_encoder") typedef csv_stream_encoder csv_serializer;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use csv_string_encoder") typedef csv_string_encoder csv_string_serializer;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use csv_stream_encoder") typedef csv_stream_encoder csv_serializer;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use csv_string_encoder") typedef csv_string_encoder csv_string_serializer;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use csv_stream_encoder") typedef csv_stream_encoder csv_encoder;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use wcsv_stream_encoder") typedef csv_stream_encoder wcsv_encoder;
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
85
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_error.hpp
Normal file
85
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_error.hpp
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CSV_CSV_ERROR_HPP
|
||||
#define JSONCONS_CSV_CSV_ERROR_HPP
|
||||
|
||||
#include <system_error>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
|
||||
namespace jsoncons { namespace csv {
|
||||
|
||||
enum class csv_errc : int
|
||||
{
|
||||
success = 0,
|
||||
unexpected_eof = 1,
|
||||
source_error,
|
||||
expected_quote,
|
||||
syntax_error,
|
||||
invalid_parse_state,
|
||||
invalid_escaped_char,
|
||||
unexpected_char_between_fields
|
||||
};
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use csv_errc") typedef csv_errc csv_parser_errc;
|
||||
#endif
|
||||
|
||||
class csv_error_category_impl
|
||||
: public std::error_category
|
||||
{
|
||||
public:
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "jsoncons/csv";
|
||||
}
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<csv_errc>(ev))
|
||||
{
|
||||
case csv_errc::unexpected_eof:
|
||||
return "Unexpected end of file";
|
||||
case csv_errc::source_error:
|
||||
return "Source error";
|
||||
case csv_errc::expected_quote:
|
||||
return "Expected quote character";
|
||||
case csv_errc::syntax_error:
|
||||
return "CSV syntax error";
|
||||
case csv_errc::invalid_parse_state:
|
||||
return "Invalid CSV parser state";
|
||||
case csv_errc::invalid_escaped_char:
|
||||
return "Invalid character following quote escape character";
|
||||
case csv_errc::unexpected_char_between_fields:
|
||||
return "Unexpected character between fields";
|
||||
default:
|
||||
return "Unknown CSV parser error";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
const std::error_category& csv_error_category()
|
||||
{
|
||||
static csv_error_category_impl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
inline
|
||||
std::error_code make_error_code(csv_errc result)
|
||||
{
|
||||
return std::error_code(static_cast<int>(result),csv_error_category());
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct is_error_code_enum<jsoncons::csv::csv_errc> : public true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
973
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_options.hpp
Normal file
973
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_options.hpp
Normal file
|
|
@ -0,0 +1,973 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CSV_CSV_OPTIONS_HPP
|
||||
#define JSONCONS_CSV_CSV_OPTIONS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility> // std::pair
|
||||
#include <unordered_map> // std::unordered_map
|
||||
#include <map>
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <cwchar>
|
||||
#include <jsoncons/json_options.hpp>
|
||||
|
||||
namespace jsoncons { namespace csv {
|
||||
|
||||
enum class csv_column_type : uint8_t
|
||||
{
|
||||
string_t,integer_t,float_t,boolean_t,repeat_t
|
||||
};
|
||||
|
||||
enum class quote_style_kind : uint8_t
|
||||
{
|
||||
minimal,all,nonnumeric,none
|
||||
};
|
||||
|
||||
enum class csv_mapping_kind : uint8_t
|
||||
{
|
||||
n_rows = 1,
|
||||
n_objects,
|
||||
m_columns
|
||||
};
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
using mapping_kind = csv_mapping_kind;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use quote_style_kind") typedef quote_style_kind quote_styles;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use quote_style_kind") typedef quote_style_kind quote_style_type;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use csv_mapping_kind") typedef csv_mapping_kind mapping_type;
|
||||
#endif
|
||||
|
||||
enum class column_state {sequence,label};
|
||||
|
||||
struct csv_type_info
|
||||
{
|
||||
csv_type_info() = default;
|
||||
csv_type_info(const csv_type_info&) = default;
|
||||
csv_type_info(csv_type_info&&) = default;
|
||||
|
||||
csv_type_info(csv_column_type ctype, std::size_t lev, std::size_t repcount = 0) noexcept
|
||||
{
|
||||
col_type = ctype;
|
||||
level = lev;
|
||||
rep_count = repcount;
|
||||
}
|
||||
|
||||
csv_column_type col_type;
|
||||
std::size_t level;
|
||||
std::size_t rep_count;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class CharT,class Container>
|
||||
void parse_column_names(const std::basic_string<CharT>& names,
|
||||
Container& cont)
|
||||
{
|
||||
column_state state = column_state::sequence;
|
||||
typename Container::value_type buffer(cont.get_allocator());
|
||||
|
||||
auto p = names.begin();
|
||||
while (p != names.end())
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case column_state::sequence:
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case ' ': case '\t':case '\r': case '\n':
|
||||
++p;
|
||||
break;
|
||||
default:
|
||||
buffer.clear();
|
||||
state = column_state::label;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case column_state::label:
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case ',':
|
||||
cont.push_back(buffer);
|
||||
buffer.clear();
|
||||
++p;
|
||||
state = column_state::sequence;
|
||||
break;
|
||||
default:
|
||||
buffer.push_back(*p);
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state == column_state::label)
|
||||
{
|
||||
cont.push_back(buffer);
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT,class Container>
|
||||
void parse_column_types(const std::basic_string<CharT>& types,
|
||||
Container& column_types)
|
||||
{
|
||||
const std::map<jsoncons::basic_string_view<CharT>,csv_column_type> type_dictionary =
|
||||
{
|
||||
|
||||
{JSONCONS_STRING_VIEW_CONSTANT(CharT,"string"),csv_column_type::string_t},
|
||||
{JSONCONS_STRING_VIEW_CONSTANT(CharT,"integer"),csv_column_type::integer_t},
|
||||
{JSONCONS_STRING_VIEW_CONSTANT(CharT,"float"),csv_column_type::float_t},
|
||||
{JSONCONS_STRING_VIEW_CONSTANT(CharT,"boolean"),csv_column_type::boolean_t}
|
||||
};
|
||||
|
||||
column_state state = column_state::sequence;
|
||||
int depth = 0;
|
||||
std::basic_string<CharT> buffer;
|
||||
|
||||
auto p = types.begin();
|
||||
while (p != types.end())
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case column_state::sequence:
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case ' ': case '\t':case '\r': case '\n':
|
||||
++p;
|
||||
break;
|
||||
case '[':
|
||||
++depth;
|
||||
++p;
|
||||
break;
|
||||
case ']':
|
||||
JSONCONS_ASSERT(depth > 0);
|
||||
--depth;
|
||||
++p;
|
||||
break;
|
||||
case '*':
|
||||
{
|
||||
JSONCONS_ASSERT(column_types.size() != 0);
|
||||
std::size_t offset = 0;
|
||||
std::size_t level = column_types.size() > 0 ? column_types.back().level: 0;
|
||||
if (level > 0)
|
||||
{
|
||||
for (auto it = column_types.rbegin();
|
||||
it != column_types.rend() && level == it->level;
|
||||
++it)
|
||||
{
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 1;
|
||||
}
|
||||
column_types.emplace_back(csv_column_type::repeat_t,depth,offset);
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
buffer.clear();
|
||||
state = column_state::label;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case column_state::label:
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case '*':
|
||||
{
|
||||
auto it = type_dictionary.find(buffer);
|
||||
if (it != type_dictionary.end())
|
||||
{
|
||||
column_types.emplace_back(it->second,depth);
|
||||
buffer.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONCONS_ASSERT(false);
|
||||
}
|
||||
state = column_state::sequence;
|
||||
break;
|
||||
}
|
||||
case ',':
|
||||
{
|
||||
auto it = type_dictionary.find(buffer);
|
||||
if (it != type_dictionary.end())
|
||||
{
|
||||
column_types.emplace_back(it->second,depth);
|
||||
buffer.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONCONS_ASSERT(false);
|
||||
}
|
||||
++p;
|
||||
state = column_state::sequence;
|
||||
break;
|
||||
}
|
||||
case ']':
|
||||
{
|
||||
JSONCONS_ASSERT(depth > 0);
|
||||
auto it = type_dictionary.find(buffer);
|
||||
if (it != type_dictionary.end())
|
||||
{
|
||||
column_types.emplace_back(it->second,depth);
|
||||
buffer.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONCONS_ASSERT(false);
|
||||
}
|
||||
--depth;
|
||||
++p;
|
||||
state = column_state::sequence;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
buffer.push_back(*p);
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state == column_state::label)
|
||||
{
|
||||
auto it = type_dictionary.find(buffer);
|
||||
if (it != type_dictionary.end())
|
||||
{
|
||||
column_types.emplace_back(it->second,depth);
|
||||
buffer.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONCONS_ASSERT(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
template <class CharT>
|
||||
class basic_csv_options;
|
||||
|
||||
template <class CharT>
|
||||
class basic_csv_options_common
|
||||
{
|
||||
friend class basic_csv_options<CharT>;
|
||||
public:
|
||||
using char_type = CharT;
|
||||
using string_type = std::basic_string<CharT>;
|
||||
private:
|
||||
char_type field_delimiter_;
|
||||
char_type quote_char_;
|
||||
char_type quote_escape_char_;
|
||||
char_type subfield_delimiter_;
|
||||
|
||||
bool enable_nan_to_num_:1;
|
||||
bool enable_inf_to_num_:1;
|
||||
bool enable_neginf_to_num_:1;
|
||||
bool enable_nan_to_str_:1;
|
||||
bool enable_inf_to_str_:1;
|
||||
bool enable_neginf_to_str_:1;
|
||||
bool enable_str_to_nan_:1;
|
||||
bool enable_str_to_inf_:1;
|
||||
bool enable_str_to_neginf_:1;
|
||||
|
||||
string_type nan_to_num_;
|
||||
string_type inf_to_num_;
|
||||
string_type neginf_to_num_;
|
||||
string_type nan_to_str_;
|
||||
string_type inf_to_str_;
|
||||
string_type neginf_to_str_;
|
||||
string_type column_names_;
|
||||
|
||||
protected:
|
||||
basic_csv_options_common()
|
||||
: field_delimiter_(','),
|
||||
quote_char_('\"'),
|
||||
quote_escape_char_('\"'),
|
||||
subfield_delimiter_(char_type()),
|
||||
enable_nan_to_num_(false),
|
||||
enable_inf_to_num_(false),
|
||||
enable_neginf_to_num_(false),
|
||||
enable_nan_to_str_(false),
|
||||
enable_inf_to_str_(false),
|
||||
enable_neginf_to_str_(false),
|
||||
enable_str_to_nan_(false),
|
||||
enable_str_to_inf_(false),
|
||||
enable_str_to_neginf_(false)
|
||||
{
|
||||
}
|
||||
|
||||
basic_csv_options_common(const basic_csv_options_common&) = default;
|
||||
basic_csv_options_common& operator=(const basic_csv_options_common&) = default;
|
||||
|
||||
virtual ~basic_csv_options_common() noexcept = default;
|
||||
public:
|
||||
|
||||
char_type field_delimiter() const
|
||||
{
|
||||
return field_delimiter_;
|
||||
}
|
||||
|
||||
const char_type subfield_delimiter() const
|
||||
{
|
||||
return subfield_delimiter_;
|
||||
}
|
||||
|
||||
char_type quote_char() const
|
||||
{
|
||||
return quote_char_;
|
||||
}
|
||||
|
||||
char_type quote_escape_char() const
|
||||
{
|
||||
return quote_escape_char_;
|
||||
}
|
||||
|
||||
string_type column_names() const
|
||||
{
|
||||
return column_names_;
|
||||
}
|
||||
|
||||
bool enable_nan_to_num() const
|
||||
{
|
||||
return enable_nan_to_num_;
|
||||
}
|
||||
|
||||
bool enable_inf_to_num() const
|
||||
{
|
||||
return enable_inf_to_num_;
|
||||
}
|
||||
|
||||
bool enable_neginf_to_num() const
|
||||
{
|
||||
return enable_neginf_to_num_ || enable_inf_to_num_;
|
||||
}
|
||||
|
||||
bool enable_nan_to_str() const
|
||||
{
|
||||
return enable_nan_to_str_;
|
||||
}
|
||||
|
||||
bool enable_str_to_nan() const
|
||||
{
|
||||
return enable_str_to_nan_;
|
||||
}
|
||||
|
||||
bool enable_inf_to_str() const
|
||||
{
|
||||
return enable_inf_to_str_;
|
||||
}
|
||||
|
||||
bool enable_str_to_inf() const
|
||||
{
|
||||
return enable_str_to_inf_;
|
||||
}
|
||||
|
||||
bool enable_neginf_to_str() const
|
||||
{
|
||||
return enable_neginf_to_str_ || enable_inf_to_str_;
|
||||
}
|
||||
|
||||
bool enable_str_to_neginf() const
|
||||
{
|
||||
return enable_str_to_neginf_ || enable_str_to_inf_;
|
||||
}
|
||||
|
||||
string_type nan_to_num() const
|
||||
{
|
||||
return nan_to_num_;
|
||||
}
|
||||
|
||||
string_type inf_to_num() const
|
||||
{
|
||||
return inf_to_num_;
|
||||
}
|
||||
|
||||
string_type neginf_to_num() const
|
||||
{
|
||||
if (enable_neginf_to_num_)
|
||||
{
|
||||
return neginf_to_num_;
|
||||
}
|
||||
else if (enable_inf_to_num_)
|
||||
{
|
||||
string_type s;
|
||||
s.push_back('-');
|
||||
s.append(inf_to_num_);
|
||||
return s;
|
||||
}
|
||||
else
|
||||
{
|
||||
return neginf_to_num_;
|
||||
}
|
||||
}
|
||||
|
||||
string_type nan_to_str() const
|
||||
{
|
||||
return nan_to_str_;
|
||||
}
|
||||
|
||||
string_type inf_to_str() const
|
||||
{
|
||||
return inf_to_str_;
|
||||
}
|
||||
|
||||
string_type neginf_to_str() const
|
||||
{
|
||||
if (enable_neginf_to_str_)
|
||||
{
|
||||
return neginf_to_str_;
|
||||
}
|
||||
else if (enable_inf_to_str_)
|
||||
{
|
||||
string_type s;
|
||||
s.push_back('-');
|
||||
s.append(inf_to_str_);
|
||||
return s;
|
||||
}
|
||||
else
|
||||
{
|
||||
return neginf_to_str_; // empty string
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
class basic_csv_decode_options : public virtual basic_csv_options_common<CharT>
|
||||
{
|
||||
friend class basic_csv_options<CharT>;
|
||||
using super_type = basic_csv_options_common<CharT>;
|
||||
public:
|
||||
using typename super_type::char_type;
|
||||
using typename super_type::string_type;
|
||||
|
||||
private:
|
||||
bool assume_header_:1;
|
||||
bool ignore_empty_values_:1;
|
||||
bool ignore_empty_lines_:1;
|
||||
bool trim_leading_:1;
|
||||
bool trim_trailing_:1;
|
||||
bool trim_leading_inside_quotes_:1;
|
||||
bool trim_trailing_inside_quotes_:1;
|
||||
bool unquoted_empty_value_is_null_:1;
|
||||
bool infer_types_:1;
|
||||
bool lossless_number_:1;
|
||||
char_type comment_starter_;
|
||||
csv_mapping_kind mapping_;
|
||||
std::size_t header_lines_;
|
||||
std::size_t max_lines_;
|
||||
string_type column_types_;
|
||||
string_type column_defaults_;
|
||||
public:
|
||||
basic_csv_decode_options()
|
||||
: assume_header_(false),
|
||||
ignore_empty_values_(false),
|
||||
ignore_empty_lines_(true),
|
||||
trim_leading_(false),
|
||||
trim_trailing_(false),
|
||||
trim_leading_inside_quotes_(false),
|
||||
trim_trailing_inside_quotes_(false),
|
||||
unquoted_empty_value_is_null_(false),
|
||||
infer_types_(true),
|
||||
lossless_number_(false),
|
||||
comment_starter_('\0'),
|
||||
mapping_(),
|
||||
header_lines_(0),
|
||||
max_lines_((std::numeric_limits<std::size_t>::max)())
|
||||
{}
|
||||
|
||||
basic_csv_decode_options(const basic_csv_decode_options& other) = default;
|
||||
|
||||
basic_csv_decode_options(basic_csv_decode_options&& other)
|
||||
: super_type(std::forward<basic_csv_decode_options>(other)),
|
||||
assume_header_(other.assume_header_),
|
||||
ignore_empty_values_(other.ignore_empty_values_),
|
||||
ignore_empty_lines_(other.ignore_empty_lines_),
|
||||
trim_leading_(other.trim_leading_),
|
||||
trim_trailing_(other.trim_trailing_),
|
||||
trim_leading_inside_quotes_(other.trim_leading_inside_quotes_),
|
||||
trim_trailing_inside_quotes_(other.trim_trailing_inside_quotes_),
|
||||
unquoted_empty_value_is_null_(other.unquoted_empty_value_is_null_),
|
||||
infer_types_(other.infer_types_),
|
||||
lossless_number_(other.lossless_number_),
|
||||
comment_starter_(other.comment_starter_),
|
||||
mapping_(other.mapping_),
|
||||
header_lines_(other.header_lines_),
|
||||
max_lines_(other.max_lines_),
|
||||
column_types_(std::move(other.column_types_)),
|
||||
column_defaults_(std::move(other.column_defaults_))
|
||||
{}
|
||||
|
||||
std::size_t header_lines() const
|
||||
{
|
||||
return (assume_header_ && header_lines_ <= 1) ? 1 : header_lines_;
|
||||
}
|
||||
|
||||
bool assume_header() const
|
||||
{
|
||||
return assume_header_;
|
||||
}
|
||||
|
||||
bool ignore_empty_values() const
|
||||
{
|
||||
return ignore_empty_values_;
|
||||
}
|
||||
|
||||
bool ignore_empty_lines() const
|
||||
{
|
||||
return ignore_empty_lines_;
|
||||
}
|
||||
|
||||
bool trim_leading() const
|
||||
{
|
||||
return trim_leading_;
|
||||
}
|
||||
|
||||
bool trim_trailing() const
|
||||
{
|
||||
return trim_trailing_;
|
||||
}
|
||||
|
||||
bool trim_leading_inside_quotes() const
|
||||
{
|
||||
return trim_leading_inside_quotes_;
|
||||
}
|
||||
|
||||
bool trim_trailing_inside_quotes() const
|
||||
{
|
||||
return trim_trailing_inside_quotes_;
|
||||
}
|
||||
|
||||
bool trim() const
|
||||
{
|
||||
return trim_leading_ && trim_trailing_;
|
||||
}
|
||||
|
||||
bool trim_inside_quotes() const
|
||||
{
|
||||
return trim_leading_inside_quotes_ && trim_trailing_inside_quotes_;
|
||||
}
|
||||
|
||||
bool unquoted_empty_value_is_null() const
|
||||
{
|
||||
return unquoted_empty_value_is_null_;
|
||||
}
|
||||
|
||||
bool infer_types() const
|
||||
{
|
||||
return infer_types_;
|
||||
}
|
||||
|
||||
bool lossless_number() const
|
||||
{
|
||||
return lossless_number_;
|
||||
}
|
||||
|
||||
char_type comment_starter() const
|
||||
{
|
||||
return comment_starter_;
|
||||
}
|
||||
|
||||
csv_mapping_kind mapping_kind() const
|
||||
{
|
||||
return mapping_ != csv_mapping_kind() ? mapping_ : (assume_header() || this->column_names().size() > 0 ? csv_mapping_kind::n_objects : csv_mapping_kind::n_rows);
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
csv_mapping_kind mapping() const
|
||||
{
|
||||
return mapping_kind();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::size_t max_lines() const
|
||||
{
|
||||
return max_lines_;
|
||||
}
|
||||
|
||||
string_type column_types() const
|
||||
{
|
||||
return column_types_;
|
||||
}
|
||||
|
||||
string_type column_defaults() const
|
||||
{
|
||||
return column_defaults_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
class basic_csv_encode_options : public virtual basic_csv_options_common<CharT>
|
||||
{
|
||||
friend class basic_csv_options<CharT>;
|
||||
using super_type = basic_csv_options_common<CharT>;
|
||||
public:
|
||||
using typename super_type::char_type;
|
||||
using typename super_type::string_type;
|
||||
private:
|
||||
quote_style_kind quote_style_;
|
||||
float_chars_format float_format_;
|
||||
int8_t precision_;
|
||||
string_type line_delimiter_;
|
||||
public:
|
||||
basic_csv_encode_options()
|
||||
: quote_style_(quote_style_kind::minimal),
|
||||
float_format_(float_chars_format::general),
|
||||
precision_(0)
|
||||
{
|
||||
line_delimiter_.push_back('\n');
|
||||
}
|
||||
|
||||
basic_csv_encode_options(const basic_csv_encode_options& other) = default;
|
||||
|
||||
basic_csv_encode_options(basic_csv_encode_options&& other)
|
||||
: super_type(std::forward<basic_csv_encode_options>(other)),
|
||||
quote_style_(other.quote_style_),
|
||||
float_format_(other.float_format_),
|
||||
precision_(other.precision_),
|
||||
line_delimiter_(std::move(other.line_delimiter_))
|
||||
{
|
||||
}
|
||||
|
||||
quote_style_kind quote_style() const
|
||||
{
|
||||
return quote_style_;
|
||||
}
|
||||
|
||||
float_chars_format float_format() const
|
||||
{
|
||||
return float_format_;
|
||||
}
|
||||
|
||||
int8_t precision() const
|
||||
{
|
||||
return precision_;
|
||||
}
|
||||
|
||||
string_type line_delimiter() const
|
||||
{
|
||||
return line_delimiter_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT>
|
||||
class basic_csv_options final : public basic_csv_decode_options<CharT>, public basic_csv_encode_options<CharT>
|
||||
{
|
||||
using char_type = CharT;
|
||||
using string_type = std::basic_string<CharT>;
|
||||
|
||||
public:
|
||||
using basic_csv_decode_options<CharT>::enable_str_to_nan;
|
||||
using basic_csv_decode_options<CharT>::enable_str_to_inf;
|
||||
using basic_csv_decode_options<CharT>::enable_str_to_neginf;
|
||||
using basic_csv_decode_options<CharT>::nan_to_str;
|
||||
using basic_csv_decode_options<CharT>::inf_to_str;
|
||||
using basic_csv_decode_options<CharT>::neginf_to_str;
|
||||
using basic_csv_decode_options<CharT>::nan_to_num;
|
||||
using basic_csv_decode_options<CharT>::inf_to_num;
|
||||
using basic_csv_decode_options<CharT>::neginf_to_num;
|
||||
using basic_csv_decode_options<CharT>::field_delimiter;
|
||||
using basic_csv_decode_options<CharT>::subfield_delimiter;
|
||||
using basic_csv_decode_options<CharT>::quote_char;
|
||||
using basic_csv_decode_options<CharT>::quote_escape_char;
|
||||
using basic_csv_decode_options<CharT>::column_names;
|
||||
using basic_csv_decode_options<CharT>::header_lines;
|
||||
using basic_csv_decode_options<CharT>::assume_header;
|
||||
using basic_csv_decode_options<CharT>::ignore_empty_values;
|
||||
using basic_csv_decode_options<CharT>::ignore_empty_lines;
|
||||
using basic_csv_decode_options<CharT>::trim_leading;
|
||||
using basic_csv_decode_options<CharT>::trim_trailing;
|
||||
using basic_csv_decode_options<CharT>::trim_leading_inside_quotes;
|
||||
using basic_csv_decode_options<CharT>::trim_trailing_inside_quotes;
|
||||
using basic_csv_decode_options<CharT>::trim;
|
||||
using basic_csv_decode_options<CharT>::trim_inside_quotes;
|
||||
using basic_csv_decode_options<CharT>::unquoted_empty_value_is_null;
|
||||
using basic_csv_decode_options<CharT>::infer_types;
|
||||
using basic_csv_decode_options<CharT>::lossless_number;
|
||||
using basic_csv_decode_options<CharT>::comment_starter;
|
||||
using basic_csv_decode_options<CharT>::mapping;
|
||||
using basic_csv_decode_options<CharT>::max_lines;
|
||||
using basic_csv_decode_options<CharT>::column_types;
|
||||
using basic_csv_decode_options<CharT>::column_defaults;
|
||||
using basic_csv_encode_options<CharT>::float_format;
|
||||
using basic_csv_encode_options<CharT>::precision;
|
||||
using basic_csv_encode_options<CharT>::line_delimiter;
|
||||
using basic_csv_encode_options<CharT>::quote_style;
|
||||
|
||||
static constexpr size_t default_indent = 4;
|
||||
|
||||
// Constructors
|
||||
|
||||
basic_csv_options() = default;
|
||||
basic_csv_options(const basic_csv_options&) = default;
|
||||
basic_csv_options(basic_csv_options&&) = default;
|
||||
basic_csv_options& operator=(const basic_csv_options&) = default;
|
||||
basic_csv_options& operator=(basic_csv_options&&) = default;
|
||||
|
||||
basic_csv_options& float_format(float_chars_format value)
|
||||
{
|
||||
this->float_format_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& precision(int8_t value)
|
||||
{
|
||||
this->precision_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& header_lines(std::size_t value)
|
||||
{
|
||||
this->header_lines_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& assume_header(bool value)
|
||||
{
|
||||
this->assume_header_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& ignore_empty_values(bool value)
|
||||
{
|
||||
this->ignore_empty_values_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& ignore_empty_lines(bool value)
|
||||
{
|
||||
this->ignore_empty_lines_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& trim_leading(bool value)
|
||||
{
|
||||
this->trim_leading_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& trim_trailing(bool value)
|
||||
{
|
||||
this->trim_trailing_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& trim_leading_inside_quotes(bool value)
|
||||
{
|
||||
this->trim_leading_inside_quotes_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& trim_trailing_inside_quotes(bool value)
|
||||
{
|
||||
this->trim_trailing_inside_quotes_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& trim(bool value)
|
||||
{
|
||||
this->trim_leading_ = value;
|
||||
this->trim_trailing_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& trim_inside_quotes(bool value)
|
||||
{
|
||||
this->trim_leading_inside_quotes_ = value;
|
||||
this->trim_trailing_inside_quotes_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& unquoted_empty_value_is_null(bool value)
|
||||
{
|
||||
this->unquoted_empty_value_is_null_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& column_names(const string_type& value)
|
||||
{
|
||||
this->column_names_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& column_types(const string_type& value)
|
||||
{
|
||||
this->column_types_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& column_defaults(const string_type& value)
|
||||
{
|
||||
this->column_defaults_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& field_delimiter(char_type value)
|
||||
{
|
||||
this->field_delimiter_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& subfield_delimiter(char_type value)
|
||||
{
|
||||
this->subfield_delimiter_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& line_delimiter(const string_type& value)
|
||||
{
|
||||
this->line_delimiter_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& quote_char(char_type value)
|
||||
{
|
||||
this->quote_char_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& infer_types(bool value)
|
||||
{
|
||||
this->infer_types_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& lossless_number(bool value)
|
||||
{
|
||||
this->lossless_number_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& quote_escape_char(char_type value)
|
||||
{
|
||||
this->quote_escape_char_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& comment_starter(char_type value)
|
||||
{
|
||||
this->comment_starter_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& quote_style(quote_style_kind value)
|
||||
{
|
||||
this->quote_style_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
basic_csv_options& mapping(csv_mapping_kind value)
|
||||
{
|
||||
this->mapping_ = value;
|
||||
return *this;
|
||||
}
|
||||
//#endif
|
||||
|
||||
basic_csv_options& mapping_kind(csv_mapping_kind value)
|
||||
{
|
||||
this->mapping_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& max_lines(std::size_t value)
|
||||
{
|
||||
this->max_lines_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& nan_to_num(const string_type& value)
|
||||
{
|
||||
this->enable_nan_to_num_ = true;
|
||||
this->nan_to_str_.clear();
|
||||
this->nan_to_num_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& inf_to_num(const string_type& value)
|
||||
{
|
||||
this->enable_inf_to_num_ = true;
|
||||
this->inf_to_str_.clear();
|
||||
this->inf_to_num_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& neginf_to_num(const string_type& value)
|
||||
{
|
||||
this->enable_neginf_to_num_ = true;
|
||||
this->neginf_to_str_.clear();
|
||||
this->neginf_to_num_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& nan_to_str(const string_type& value, bool enable_inverse = true)
|
||||
{
|
||||
this->enable_nan_to_str_ = true;
|
||||
this->enable_str_to_nan_ = enable_inverse;
|
||||
this->nan_to_num_.clear();
|
||||
this->nan_to_str_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& inf_to_str(const string_type& value, bool enable_inverse = true)
|
||||
{
|
||||
this->enable_inf_to_str_ = true;
|
||||
this->enable_inf_to_str_ = enable_inverse;
|
||||
this->inf_to_num_.clear();
|
||||
this->inf_to_str_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_csv_options& neginf_to_str(const string_type& value, bool enable_inverse = true)
|
||||
{
|
||||
this->enable_neginf_to_str_ = true;
|
||||
this->enable_neginf_to_str_ = enable_inverse;
|
||||
this->neginf_to_num_.clear();
|
||||
this->neginf_to_str_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use float_format(float_chars_format)")
|
||||
basic_csv_options& floating_point_format(float_chars_format value)
|
||||
{
|
||||
this->float_format_ = value;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
using csv_options = basic_csv_options<char>;
|
||||
using wcsv_options = basic_csv_options<wchar_t>;
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use csv_options") typedef csv_options csv_parameters;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use wcsv_options") typedef wcsv_options wcsv_parameters;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use csv_options") typedef csv_options csv_serializing_options;
|
||||
JSONCONS_DEPRECATED_MSG("Instead, use wcsv_options") typedef wcsv_options wcsv_serializing_options;
|
||||
#endif
|
||||
|
||||
|
||||
}}
|
||||
#endif
|
||||
2099
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp
Normal file
2099
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp
Normal file
File diff suppressed because it is too large
Load diff
348
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp
Normal file
348
scripts/exe/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CSV_CSV_READER_HPP
|
||||
#define JSONCONS_CSV_CSV_READER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <memory> // std::allocator
|
||||
#include <utility> // std::move
|
||||
#include <istream> // std::basic_istream
|
||||
#include <jsoncons/source.hpp>
|
||||
#include <jsoncons/json_exception.hpp>
|
||||
#include <jsoncons/json_visitor.hpp>
|
||||
#include <jsoncons_ext/csv/csv_error.hpp>
|
||||
#include <jsoncons_ext/csv/csv_parser.hpp>
|
||||
#include <jsoncons/json.hpp>
|
||||
#include <jsoncons/json_reader.hpp>
|
||||
#include <jsoncons/json_decoder.hpp>
|
||||
#include <jsoncons/source_adaptor.hpp>
|
||||
#include <jsoncons_ext/csv/csv_options.hpp>
|
||||
|
||||
namespace jsoncons { namespace csv {
|
||||
|
||||
template<class CharT,class Source=jsoncons::stream_source<CharT>,class Allocator=std::allocator<char>>
|
||||
class basic_csv_reader
|
||||
{
|
||||
struct stack_item
|
||||
{
|
||||
stack_item() noexcept
|
||||
: array_begun_(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool array_begun_;
|
||||
};
|
||||
using char_type = CharT;
|
||||
using temp_allocator_type = Allocator;
|
||||
typedef typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<CharT> char_allocator_type;
|
||||
|
||||
basic_csv_reader(const basic_csv_reader&) = delete;
|
||||
basic_csv_reader& operator = (const basic_csv_reader&) = delete;
|
||||
|
||||
basic_default_json_visitor<CharT> default_visitor_;
|
||||
text_source_adaptor<Source> source_;
|
||||
basic_json_visitor<CharT>& visitor_;
|
||||
basic_csv_parser<CharT,Allocator> parser_;
|
||||
|
||||
public:
|
||||
// Structural characters
|
||||
static constexpr size_t default_max_buffer_size = 16384;
|
||||
//! Parse an input stream of CSV text into a json object
|
||||
/*!
|
||||
\param is The input stream to read from
|
||||
*/
|
||||
|
||||
template <class Sourceable>
|
||||
basic_csv_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const Allocator& alloc = Allocator())
|
||||
|
||||
: basic_csv_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
basic_csv_decode_options<CharT>(),
|
||||
default_csv_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_csv_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const basic_csv_decode_options<CharT>& options,
|
||||
const Allocator& alloc = Allocator())
|
||||
|
||||
: basic_csv_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
options,
|
||||
default_csv_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_csv_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
std::function<bool(csv_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator())
|
||||
: basic_csv_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
basic_csv_decode_options<CharT>(),
|
||||
err_handler,
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
basic_csv_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const basic_csv_decode_options<CharT>& options,
|
||||
std::function<bool(csv_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator())
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
visitor_(visitor),
|
||||
parser_(options, err_handler, alloc)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
~basic_csv_reader() noexcept = default;
|
||||
|
||||
void read()
|
||||
{
|
||||
std::error_code ec;
|
||||
read(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read(std::error_code& ec)
|
||||
{
|
||||
read_internal(ec);
|
||||
}
|
||||
|
||||
std::size_t line() const
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return parser_.source_exhausted() && source_.eof();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void read_internal(std::error_code& ec)
|
||||
{
|
||||
if (source_.is_error())
|
||||
{
|
||||
ec = csv_errc::source_error;
|
||||
return;
|
||||
}
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
}
|
||||
}
|
||||
parser_.parse_some(visitor_, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class CharT,class Source=jsoncons::stream_source<CharT>,class Allocator=std::allocator<char>>
|
||||
class legacy_basic_csv_reader
|
||||
{
|
||||
struct stack_item
|
||||
{
|
||||
stack_item() noexcept
|
||||
: array_begun_(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool array_begun_;
|
||||
};
|
||||
using char_type = CharT;
|
||||
using temp_allocator_type = Allocator;
|
||||
typedef typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<CharT> char_allocator_type;
|
||||
|
||||
legacy_basic_csv_reader(const legacy_basic_csv_reader&) = delete;
|
||||
legacy_basic_csv_reader& operator = (const legacy_basic_csv_reader&) = delete;
|
||||
|
||||
basic_default_json_visitor<CharT> default_visitor_;
|
||||
text_source_adaptor<Source> source_;
|
||||
basic_json_visitor<CharT>& visitor_;
|
||||
basic_csv_parser<CharT,Allocator> parser_;
|
||||
|
||||
public:
|
||||
// Structural characters
|
||||
static constexpr size_t default_max_buffer_size = 16384;
|
||||
//! Parse an input stream of CSV text into a json object
|
||||
/*!
|
||||
\param is The input stream to read from
|
||||
*/
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_csv_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const Allocator& alloc = Allocator())
|
||||
|
||||
: legacy_basic_csv_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
basic_csv_decode_options<CharT>(),
|
||||
default_csv_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_csv_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const basic_csv_decode_options<CharT>& options,
|
||||
const Allocator& alloc = Allocator())
|
||||
|
||||
: legacy_basic_csv_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
options,
|
||||
default_csv_parsing(),
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_csv_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
std::function<bool(csv_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator())
|
||||
: legacy_basic_csv_reader(std::forward<Sourceable>(source),
|
||||
visitor,
|
||||
basic_csv_decode_options<CharT>(),
|
||||
err_handler,
|
||||
alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_csv_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const basic_csv_decode_options<CharT>& options,
|
||||
std::function<bool(csv_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator(),
|
||||
typename std::enable_if<!std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(std::forward<Sourceable>(source)),
|
||||
visitor_(visitor),
|
||||
parser_(options, err_handler, alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Sourceable>
|
||||
legacy_basic_csv_reader(Sourceable&& source,
|
||||
basic_json_visitor<CharT>& visitor,
|
||||
const basic_csv_decode_options<CharT>& options,
|
||||
std::function<bool(csv_errc,const ser_context&)> err_handler,
|
||||
const Allocator& alloc = Allocator(),
|
||||
typename std::enable_if<std::is_constructible<jsoncons::basic_string_view<CharT>,Sourceable>::value>::type* = 0)
|
||||
: source_(),
|
||||
visitor_(visitor),
|
||||
parser_(options, err_handler, alloc)
|
||||
{
|
||||
jsoncons::basic_string_view<CharT> sv(std::forward<Sourceable>(source));
|
||||
auto r = unicode_traits::detect_encoding_from_bom(sv.data(), sv.size());
|
||||
if (!(r.encoding == unicode_traits::encoding_kind::utf8 || r.encoding == unicode_traits::encoding_kind::undetected))
|
||||
{
|
||||
JSONCONS_THROW(ser_error(json_errc::illegal_unicode_character,parser_.line(),parser_.column()));
|
||||
}
|
||||
std::size_t offset = (r.ptr - sv.data());
|
||||
parser_.update(sv.data()+offset,sv.size()-offset);
|
||||
}
|
||||
|
||||
~legacy_basic_csv_reader() noexcept = default;
|
||||
|
||||
void read()
|
||||
{
|
||||
std::error_code ec;
|
||||
read(ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
|
||||
}
|
||||
}
|
||||
|
||||
void read(std::error_code& ec)
|
||||
{
|
||||
read_internal(ec);
|
||||
}
|
||||
|
||||
std::size_t line() const
|
||||
{
|
||||
return parser_.line();
|
||||
}
|
||||
|
||||
std::size_t column() const
|
||||
{
|
||||
return parser_.column();
|
||||
}
|
||||
|
||||
bool eof() const
|
||||
{
|
||||
return parser_.source_exhausted() && source_.eof();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void read_internal(std::error_code& ec)
|
||||
{
|
||||
if (source_.is_error())
|
||||
{
|
||||
ec = csv_errc::source_error;
|
||||
return;
|
||||
}
|
||||
while (!parser_.stopped())
|
||||
{
|
||||
if (parser_.source_exhausted())
|
||||
{
|
||||
auto s = source_.read_buffer(ec);
|
||||
if (ec) return;
|
||||
if (s.size() > 0)
|
||||
{
|
||||
parser_.update(s.data(),s.size());
|
||||
}
|
||||
}
|
||||
parser_.parse_some(visitor_, ec);
|
||||
if (ec) return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(JSONCONS_NO_DEPRECATED)
|
||||
using csv_reader = legacy_basic_csv_reader<char>;
|
||||
using wcsv_reader = legacy_basic_csv_reader<wchar_t>;
|
||||
#endif
|
||||
|
||||
using csv_string_reader = basic_csv_reader<char,string_source<char>>;
|
||||
using wcsv_string_reader = basic_csv_reader<wchar_t,string_source<wchar_t>>;
|
||||
using csv_stream_reader = basic_csv_reader<char,stream_source<char>>;
|
||||
using wcsv_stream_reader = basic_csv_reader<wchar_t,stream_source<wchar_t>>;
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CSV_CSV_SERIALIZER_HPP
|
||||
#define JSONCONS_CSV_CSV_SERIALIZER_HPP
|
||||
|
||||
#include <jsoncons_ext/csv/csv_encoder.hpp>
|
||||
|
||||
#endif
|
||||
208
scripts/exe/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp
Normal file
208
scripts/exe/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CSV_DECODE_CSV_HPP
|
||||
#define JSONCONS_CSV_DECODE_CSV_HPP
|
||||
|
||||
#include <jsoncons_ext/csv/csv_options.hpp>
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
#include <jsoncons_ext/csv/csv_encoder.hpp>
|
||||
#include <jsoncons_ext/csv/csv_cursor.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace csv {
|
||||
|
||||
template <class T,class Source>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_sequence_of<Source,typename T::char_type>::value,T>::type
|
||||
decode_csv(const Source& s, const basic_csv_decode_options<typename Source::value_type>& options = basic_csv_decode_options<typename Source::value_type>())
|
||||
{
|
||||
using char_type = typename Source::value_type;
|
||||
|
||||
json_decoder<T> decoder;
|
||||
|
||||
basic_csv_reader<char_type,jsoncons::string_source<char_type>> reader(s,decoder,options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template <class T,class Source>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_char_sequence<Source>::value,T>::type
|
||||
decode_csv(const Source& s, const basic_csv_decode_options<typename Source::value_type>& options = basic_csv_decode_options<typename Source::value_type>())
|
||||
{
|
||||
using char_type = typename Source::value_type;
|
||||
|
||||
basic_csv_cursor<char_type> cursor(s, options);
|
||||
jsoncons::json_decoder<basic_json<char_type>> decoder;
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char_type>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T,class CharT>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_csv(std::basic_istream<CharT>& is, const basic_csv_decode_options<CharT>& options = basic_csv_decode_options<CharT>())
|
||||
{
|
||||
using char_type = CharT;
|
||||
|
||||
json_decoder<T> decoder;
|
||||
|
||||
basic_csv_reader<char_type,jsoncons::stream_source<char_type>> reader(is,decoder,options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template <class T,class CharT>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_csv(std::basic_istream<CharT>& is, const basic_csv_decode_options<CharT>& options = basic_csv_decode_options<CharT>())
|
||||
{
|
||||
basic_csv_cursor<CharT> cursor(is, options);
|
||||
jsoncons::json_decoder<basic_json<CharT>> decoder;
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,CharT>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T, class InputIt>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_csv(InputIt first, InputIt last,
|
||||
const basic_csv_decode_options<typename std::iterator_traits<InputIt>::value_type>& options =
|
||||
basic_csv_decode_options<typename std::iterator_traits<InputIt>::value_type>())
|
||||
{
|
||||
using char_type = typename std::iterator_traits<InputIt>::value_type;
|
||||
|
||||
jsoncons::json_decoder<T> decoder;
|
||||
basic_csv_reader<char_type, iterator_source<InputIt>> reader(iterator_source<InputIt>(first,last), decoder, options);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template <class T, class InputIt>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_csv(InputIt first, InputIt last,
|
||||
const basic_csv_decode_options<typename std::iterator_traits<InputIt>::value_type>& options =
|
||||
basic_csv_decode_options<typename std::iterator_traits<InputIt>::value_type>())
|
||||
{
|
||||
using char_type = typename std::iterator_traits<InputIt>::value_type;
|
||||
|
||||
basic_csv_cursor<char_type,iterator_source<InputIt>> cursor(iterator_source<InputIt>(first, last), options);
|
||||
jsoncons::json_decoder<basic_json<char_type>> decoder;
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char_type>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// With leading allocator parameter
|
||||
|
||||
template <class T,class Source,class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_sequence_of<Source,typename T::char_type>::value,T>::type
|
||||
decode_csv(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const Source& s,
|
||||
const basic_csv_decode_options<typename Source::value_type>& options = basic_csv_decode_options<typename Source::value_type>())
|
||||
{
|
||||
using char_type = typename Source::value_type;
|
||||
|
||||
json_decoder<T,TempAllocator> decoder(temp_alloc);
|
||||
|
||||
basic_csv_reader<char_type,jsoncons::string_source<char_type>,TempAllocator> reader(s,decoder,options,temp_alloc);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template <class T,class Source,class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_char_sequence<Source>::value,T>::type
|
||||
decode_csv(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const Source& s,
|
||||
const basic_csv_decode_options<typename Source::value_type>& options = basic_csv_decode_options<typename Source::value_type>())
|
||||
{
|
||||
using char_type = typename Source::value_type;
|
||||
|
||||
basic_csv_cursor<char_type,stream_source<char_type>,TempAllocator> cursor(s, options, temp_alloc);
|
||||
json_decoder<basic_json<char_type,sorted_policy,TempAllocator>,TempAllocator> decoder(temp_alloc, temp_alloc);
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,char_type>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T,class CharT,class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_csv(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
std::basic_istream<CharT>& is,
|
||||
const basic_csv_decode_options<CharT>& options = basic_csv_decode_options<CharT>())
|
||||
{
|
||||
using char_type = CharT;
|
||||
|
||||
json_decoder<T,TempAllocator> decoder(temp_alloc);
|
||||
|
||||
basic_csv_reader<char_type,jsoncons::string_source<char_type>,TempAllocator> reader(is,decoder,options,temp_alloc);
|
||||
reader.read();
|
||||
if (!decoder.is_valid())
|
||||
{
|
||||
JSONCONS_THROW(ser_error(conv_errc::conversion_failed, reader.line(), reader.column()));
|
||||
}
|
||||
return decoder.get_result();
|
||||
}
|
||||
|
||||
template <class T,class CharT,class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,T>::type
|
||||
decode_csv(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
std::basic_istream<CharT>& is,
|
||||
const basic_csv_decode_options<CharT>& options = basic_csv_decode_options<CharT>())
|
||||
{
|
||||
basic_csv_cursor<CharT,stream_source<CharT>,TempAllocator> cursor(is, options, temp_alloc);
|
||||
json_decoder<basic_json<CharT,sorted_policy,TempAllocator>,TempAllocator> decoder(temp_alloc, temp_alloc);
|
||||
|
||||
std::error_code ec;
|
||||
T val = decode_traits<T,CharT>::decode(cursor, decoder, ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec, cursor.context().line(), cursor.context().column()));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
} // namespace csv
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
122
scripts/exe/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp
Normal file
122
scripts/exe/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/// Copyright 2013-2023 Daniel Parker
|
||||
// Distributed under the Boost license, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See https://github.com/danielaparker/jsoncons for latest version
|
||||
|
||||
#ifndef JSONCONS_CSV_ENCODE_CSV_HPP
|
||||
#define JSONCONS_CSV_ENCODE_CSV_HPP
|
||||
|
||||
#include <jsoncons_ext/csv/csv_options.hpp>
|
||||
#include <jsoncons_ext/csv/csv_reader.hpp>
|
||||
#include <jsoncons_ext/csv/csv_encoder.hpp>
|
||||
|
||||
namespace jsoncons {
|
||||
namespace csv {
|
||||
|
||||
template <class T,class Container>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_char_container<Container>::value>::type
|
||||
encode_csv(const T& j, Container& s, const basic_csv_encode_options<typename Container::value_type>& options = basic_csv_encode_options<typename Container::value_type>())
|
||||
{
|
||||
using char_type = typename Container::value_type;
|
||||
basic_csv_encoder<char_type,jsoncons::string_sink<std::basic_string<char_type>>> encoder(s,options);
|
||||
j.dump(encoder);
|
||||
}
|
||||
|
||||
template <class T,class Container>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_char_container<Container>::value>::type
|
||||
encode_csv(const T& val, Container& s, const basic_csv_encode_options<typename Container::value_type>& options = basic_csv_encode_options<typename Container::value_type>())
|
||||
{
|
||||
using char_type = typename Container::value_type;
|
||||
basic_csv_encoder<char_type,jsoncons::string_sink<std::basic_string<char_type>>> encoder(s,options);
|
||||
std::error_code ec;
|
||||
encode_traits<T,char_type>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class CharT>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_csv(const T& j, std::basic_ostream<CharT>& os, const basic_csv_encode_options<CharT>& options = basic_csv_encode_options<CharT>())
|
||||
{
|
||||
using char_type = CharT;
|
||||
basic_csv_encoder<char_type,jsoncons::stream_sink<char_type>> encoder(os,options);
|
||||
j.dump(encoder);
|
||||
}
|
||||
|
||||
template <class T, class CharT>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_csv(const T& val, std::basic_ostream<CharT>& os, const basic_csv_encode_options<CharT>& options = basic_csv_encode_options<CharT>())
|
||||
{
|
||||
using char_type = CharT;
|
||||
basic_csv_encoder<char_type,jsoncons::stream_sink<char_type>> encoder(os,options);
|
||||
std::error_code ec;
|
||||
encode_traits<T,CharT>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
// with temp_allocator_arg_t
|
||||
|
||||
template <class T, class Container, class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_char_container<Container>::value>::type
|
||||
encode_csv(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& j, Container& s, const basic_csv_encode_options<typename Container::value_type>& options = basic_csv_encode_options<typename Container::value_type>())
|
||||
{
|
||||
using char_type = typename Container::value_type;
|
||||
basic_csv_encoder<char_type,jsoncons::string_sink<std::basic_string<char_type>>,TempAllocator> encoder(s, options, temp_alloc);
|
||||
j.dump(encoder);
|
||||
}
|
||||
|
||||
template <class T, class Container, class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value &&
|
||||
extension_traits::is_back_insertable_char_container<Container>::value>::type
|
||||
encode_csv(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val, Container& s, const basic_csv_encode_options<typename Container::value_type>& options = basic_csv_encode_options<typename Container::value_type>())
|
||||
{
|
||||
using char_type = typename Container::value_type;
|
||||
basic_csv_encoder<char_type,jsoncons::string_sink<std::basic_string<char_type>>,TempAllocator> encoder(s, options, temp_alloc);
|
||||
std::error_code ec;
|
||||
encode_traits<T,char_type>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class CharT, class TempAllocator>
|
||||
typename std::enable_if<extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_csv(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& j, std::basic_ostream<CharT>& os, const basic_csv_encode_options<CharT>& options = basic_csv_encode_options<CharT>())
|
||||
{
|
||||
using char_type = CharT;
|
||||
basic_csv_encoder<char_type,jsoncons::stream_sink<char_type>,TempAllocator> encoder(os, options, temp_alloc);
|
||||
j.dump(encoder);
|
||||
}
|
||||
|
||||
template <class T, class CharT, class TempAllocator>
|
||||
typename std::enable_if<!extension_traits::is_basic_json<T>::value,void>::type
|
||||
encode_csv(temp_allocator_arg_t, const TempAllocator& temp_alloc,
|
||||
const T& val, std::basic_ostream<CharT>& os, const basic_csv_encode_options<CharT>& options = basic_csv_encode_options<CharT>())
|
||||
{
|
||||
using char_type = CharT;
|
||||
basic_csv_encoder<char_type,jsoncons::stream_sink<char_type>,TempAllocator> encoder(os, options, temp_alloc);
|
||||
std::error_code ec;
|
||||
encode_traits<T,CharT>::encode(val, encoder, json(), ec);
|
||||
if (ec)
|
||||
{
|
||||
JSONCONS_THROW(ser_error(ec));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace csv
|
||||
} // namespace jsoncons
|
||||
|
||||
#endif
|
||||
5215
scripts/exe/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp
Normal file
5215
scripts/exe/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue