Giter VIP home page Giter VIP logo

sonic-cpp's Introduction

Sonic-Cpp


A fast JSON serializing & deserializing library, accelerated by SIMD.

clang-format Check Test codecov

Requirement

  • c++11 or above
  • x86 platform with AVX2 instruction
  • GCC or LLVM compiler (not support MSVC compiler now)
  • Linux OS

Features

  • Complete APIs for JSON value manipulation
  • Fast on JSON serializing and parsing
  • Support parse ondemand

Benchmarks

  • use CMake
cmake -S . -B build -DBUILD_BENCH=ON
cmake --build build --target bench -j
./build/benchmark/bench
  • use bazel
bazel run :benchmark --compilation_mode=opt

Performance by sonic benchmark

  • Run
# build by bazel
python3 ./scripts/tools/draw-decode-encode.py
  • Result

Parsing Performance image

Serializing performance image

Performance by third-party benchmark

Below data is test by https://github.com/miloyip/nativejson-benchmark:

Parsing Performance image

Serializing Performance image

API Document

Make sure Doxygen 1.8.13 or higher version has been installed. Then following:

mdkir api-doc && cd api-doc
doxygen ../Doxyfile

Design

Sonic-cpp parses JSON into a compact document tree. The document structure is as follows:

image

There are many optimizations in parsing as follows:

  • using SIMD to accelerate skipping white space.
  • using SIMD to find escaped chars when parsing strings.
  • using the STOA float pointing algorithm.

Sonic-cpp serializes a document to JSON. When serializing JSON strings, we should check the escaped characters first. So, we use SIMD instructions(AVX2/SSE) to find the escaped char for a long JSON string.

Sonic-cpp also supports ParseOnDemand if the user knows the target key at compile time. ParseOndemand also used SIMD and bit manipulation to skip the unwanted values fastly.

Usage

Include

Sonic-Cpp is a header-only library, you only need to include the directory of Sonic-Cpp header files, such as adding -I/path/to/sonic/include/ to your compiler.

Parsing and Serializing

#include "sonic/sonic.h"

#include <string>
#include <iostream>

int main()
{
  std::string json = R"(
    {
      "a": 1,
      "b": 2
    }
  )";

  sonic_json::Document doc;
  doc.Parse(json);

  sonic_json::WriteBuffer wb;
  doc.Serialize(wb);
  std::cout << wb.ToString() << std::endl;
}
// g++ -I./include/ -march=haswell --std=c++11 -O3 example/parse_and_serialize.cpp -o example/parse_and_serialize

Checking parse result

#include "sonic/sonic.h"

#include <string>
#include <iostream>

int main()
{
  std::string json = R"(
    {
      "a": 1,
      "b": 2
    }
  )";

  sonic_json::Document doc;
  doc.Parse(json);
  if (doc.HasParseError()) {
    std::cout << "Parse failed!\n";
  } else {
    std::cout << "Parse successful!\n";
  }
  return 0;
}
// g++ -I./include/ -march=haswell --std=c++11 -O3 example/check_parse_result.cpp -o example/check_parse_result

Getting and Setting

#include "sonic/sonic.h"

#include <string>
#include <iostream>

using member_itr_type = typename sonic_json::Document::MemberIterator;

void print_member(member_itr_type m) {
  const sonic_json::Node& key = m->name;
  sonic_json::Node& value = m->value;
  if (key.IsString()) {
    std::cout << "Key is: "
              << key.GetString()
              << std::endl;
  } else {
    std::cout << "Incorrect key type!\n";
    return;
  }
  if (value.IsInt64()) {
    std::cout << "Value is " << value.GetInt64() << std::endl;
  }

  return;
}

void set_new_value(member_itr_type m) {
  sonic_json::Node& value = m->value;
  value.SetInt64(2);
  return;
}

int main()
{
  std::string json = R"(
    {
      "a": 1,
      "b": 2
    }
  )";

  sonic_json::Document doc;
  doc.Parse(json);

  if (doc.HasParseError()) {
    std::cout << "Parse failed!\n";
    return -1;
  }

  // Find member by key
  if (!doc.IsObject()) { // Check JSON value type.
    std::cout << "Incorrect doc type!\n";
    return -1;
  }
  auto m = doc.FindMember("a");
  if (m != doc.MemberEnd()) {
    std::cout << "Before Setting new value:\n";
    print_member(m);
    std::cout << "After Setting value:\n";
    set_new_value(m);
    print_member(m);
  } else {
    std::cout << "Find key doesn't exist!\n";
  }
  return 0;
}
// g++ -I./include/ -march=haswell --std=c++11 -O3 example/get_and_set.cpp -o example/get_and_set

The following Is*, Get* and Set* methods are supported:

  • IsNull(), SetNull()
  • IsBool(), GetBool(), SetBool(bool)
  • IsString(), GetString(), GetStringView(), SetString(const char*, size_t)
  • IsNumber()
  • IsArray(), SetArray()
  • IsObject(), SetObject()
  • IsTrue(), IsFalse()
  • IsDouble(), GetDouble(), SetDouble(double)
  • IsInt64(), GetInt64(), SetInt64(int64_t)
  • IsUint64(), GetUint64(), SetUint64_t(uint64_t)

More usage.

RoadMap

  • Support RawNumber for JSON parsing.
  • Support JSON Path.
  • Support JSON Merge Patch.
  • Support JSON Pointer.
  • Support more platforms, e.g. ARM.
  • Support struct bind.
  • Support validating UTF-8.

Contributing

Please read CONTRIBUTING.md for information on contributing to sonic-cpp.

sonic-cpp's People

Contributors

dup4 avatar ishuah avatar liuq19 avatar moyin1004 avatar qshanz373 avatar xiegx94 avatar zhuna8616 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sonic-cpp's Issues

Proposal: more abstracted SAX handler for lots of JSON manipulates

SAX handler is necessary because it consumes less memory and has fast performance. especially based on SIMD skip. Now, sonic-cpp's handler is designed to parse the whole json, and lazysax is limited to only parsing the top level of json. There are many limits:

  1. not support load or skip according to the user-defined handler.
  2. can not check json type in sax.

We can add SkipOne(raw json), CheckOne(type) and other handler functions, to support lots of JSON manipulates, such as, merge json, cut json, and so on.

support jsonpointer format as rfc6901

Hi,
Does sonic-cpp support merge-patch easily?
For example : { op: replace, patch : "Object/0/New_object", value : "123" }

If use json_pointer:
sonic_json::Node* node2 = doc.AtPointer(PointerType({"Object", 0, "New_object"}));
This doesn't format well. transfer patch : "Object/0/New_object" to {"Object", 0, "New_object"}

Error occurred when compiling the sample with ubuntu1804: json_pointer.h:46:18: error: ‘std::enable_if_t’ has not been declared

Error occurred when compiling the sample with ubuntu1804:
./include/sonic/dom/json_pointer.h:46:18: error: ‘std::enable_if_t’ has not been declared
std::enable_if_t<std::is_integral::value, bool> = true>

Thanks for such an excellent open source project repository of ByteDance , and looking forward to better development, Expect to support more platforms, such as msvc

Proposal: Support parsing JSON number as RawNumber type

In order to parse JSON numbers with full precision and improve parsing performance, we propose adding a new RawNumber type for representing parsed JSON number values.

The design of this feature includes the following steps:

  1. Add a new kRawNumber enum to represent JSON number values, and add a RawNumberclass to distinguish it from stringview type.
  2. Provide support for construct, modifying, copying, and comparing RawNumber values. Especially, validate the number in construct and set API, because the number is from the user and maybe invalid numbers
  3. Use IsRawNumber to check for the presence of a RawNumber, while IsNumber continues to check for numeric types.

Implementation branch: #60
Status: To be reviewed.

支持mingw平台吗?尝试编译会报错

package("sonic-cpp")
    set_kind("library", {headeronly = true})
    set_homepage("https://github.com/bytedance/sonic-cpp")
    set_description("A fast JSON serializing & deserializing library, accelerated by SIMD.")
    set_license("Apache-2.0")

    add_urls("https://github.com/bytedance/sonic-cpp/archive/refs/tags/v$(version).zip")
    add_versions("1.0.0", "409441bfc8b8b9fea8641dc0a0cdfaeed784246066a5c49fc7d6e74c39999f7b")

    add_cxxflags("-march=haswell")

    on_install("linux", "mingw", function (package)
        os.cp("include", package:installdir())
    end)

    on_test(function (package)
        assert(package:check_cxxsnippets({test = [[
            #include "sonic/sonic.h"

            #include <string>
            #include <iostream>

            void test()
            {
                std::string json = R"(
                    {
                    "a": 1,
                    "b": 2
                    }
                )";

                sonic_json::Document doc;
                doc.Parse(json);

                sonic_json::WriteBuffer wb;
                doc.Serialize(wb);
                std::cout << wb.ToString() << std::endl;
            }
        ]]}, {configs = {languages = "c++11"}}))
    end)

写了个xmake包,测试时,编译执行的命令如下

> C:\msys64\ucrt64\bin\x86_64-w64-mingw32-g++ -c -m64 -march=haswell -std=c++11 -isystem C:\Users\Administrator\AppData\Local\.xmake\packages\s\sonic-cpp\1.0.0\458df893a7ff477d92a940696c86a316\include -o C:\Users\ADMINI~1\AppData\Local\Temp\.xmake\230619\_EF9250378A744340846C152D91AA04B0.o C:\Users\ADMINI~1\AppData\Local\Temp\.xmake\230619\_4F3AD1D1A3F8411D9A0D827D5BABD56C.cpp
checking for flags (-fdiagnostics-color=always) ... ok
> x86_64-w64-mingw32-g++ "-fdiagnostics-color=always" "-m64"
> checking for c++ snippet(test)
checkinfo: ...amdir\core\sandbox\modules\import\core\tool\compiler.lua:84: @programdir\modules\core\tools\gcc.lua:721: In file included from C:\Users\Administrator\AppData\Local\.xmake\packages\s\sonic-cpp\1.0.0\458df893a7ff477d92a940696c86a316\include/sonic/dom/dynamicnode.h:24,
                 from C:\Users\Administrator\AppData\Local\.xmake\packages\s\sonic-cpp\1.0.0\458df893a7ff477d92a940696c86a316\include/sonic/sonic.h:19,
                 from C:\Users\ADMINI~1\AppData\Local\Temp\.xmake\230619\_4F3AD1D1A3F8411D9A0D827D5BABD56C.cpp:4:
C:\Users\Administrator\AppData\Local\.xmake\packages\s\sonic-cpp\1.0.0\458df893a7ff477d92a940696c86a316\include/sonic/dom/genericnode.h: In member function 'uint64_t sonic_json::GenericNode<NodeType>::getUintMax() const':
C:\Users\Administrator\AppData\Local\.xmake\packages\s\sonic-cpp\1.0.0\458df893a7ff477d92a940696c86a316\include/sonic/dom/genericnode.h:1069:32: error: 'uint' was not declared in this scope; did you mean 'int'?
 1069 |     return std::numeric_limits<uint>::max();
      |                                ^~~~
      |                                int
C:\Users\Administrator\AppData\Local\.xmake\packages\s\sonic-cpp\1.0.0\458df893a7ff477d92a940696c86a316\include/sonic/dom/genericnode.h:1069:36: error: template argument 1 is invalid
 1069 |     return std::numeric_limits<uint>::max();
      |                                    ^

Ask about struct bind

image

  • Is the struct bind capability in roadmap a convenient way to serialize and deserialize a struct?
  • The plan is which bi-monthly will support this?

find member from object by map seems slower than list

What happened

UpdateNodeLazy updates object by CreateMap may be slower than list.

template <typename NodeType, typename Allocator>
static inline SonicError UpdateNodeLazy(NodeType &target, NodeType &source,
                                        Allocator &alloc) {
  ParseResult ret;
  SonicError err = kErrorNone;
  // check the raw type
  if (target.IsRaw() && *target.GetRaw().data() == '{') {
    ret = ParseLazy(target, target.GetRaw(), alloc);
  }
  if (source.IsRaw() && *source.GetRaw().data() == '{') {
    ret = ParseLazy(source, source.GetRaw(), alloc);
  }
  if (ret.Error()) {
    return ret.Error();
  }
  // update the object type
  if (!target.IsObject() || !source.IsObject() || target.Empty()) {
    target = std::move(source);
    return kErrorNone;
  }
  target.CreateMap(alloc);
  auto source_begin = source.MemberBegin(), source_end = source.MemberEnd();
  for (auto iter = source_begin; iter != source_end; iter++) {
    StringView key = iter->name.GetStringView();
    auto match = target.FindMember(key);
    if (match == target.MemberEnd()) {
      target.AddMember(key, iter->value, alloc);
    } else {
      err = UpdateNodeLazy(match->value, iter->value, alloc);
      if (err) return err;
    }
  }
  return err;
}

and

sonic-cpp/docs/usage.md

Lines 48 to 81 in fc7545b

### Find member in object
There are two ways to find members: `operator[]` or `FindMember`. We recommand
using `FindMember`.
```c++
#include "sonic/sonic.h"
// ...
using AllocatorType = typename sonic_json::Allocator;
sonic_json::Node node;
AllocatorType alloc;
// Add members for node
// find member by key
if (node.IsObject()) { // Note: CHECK NODE TYPE IS VERY IMPORTANT.
const char* key = "key";
auto m = node.FindMember(key, std::strlen(key)); // recommand
if (m != node.MemberEnd()) {
// do something
}
auto m = node.FindMember(key, std::strlen(key), alloc); // create a map to record k-v.
if (m != node.MemberEnd()) {
// do something
}
{
sonic_json::Node& value = node[key];
// do something
}
}
```
A multimap will be created to acclerate find operation if `FindMember` has allocator
as argument. This map is maintained by object, user cannot access it directly.

Benchmark

Run on (8 X 24.1208 MHz CPU s)
CPU Caches:
  L1 Data 64 KiB
  L1 Instruction 128 KiB
  L2 Unified 4096 KiB (x8)
Load Average: 1.45, 1.42, 1.46
-------------------------------------------------------------------
Benchmark                         Time             CPU   Iterations
-------------------------------------------------------------------
BM_GetObjectByIterate/2        13.8 ns         13.8 ns     42653797
BM_GetObjectByIterate/10        130 ns          130 ns      5593199
BM_GetObjectByIterate/18        416 ns          416 ns      1648711
BM_GetObjectByIterate/26        949 ns          949 ns       733822
BM_GetObjectByIterate/32       1515 ns         1515 ns       463346
BM_GetObjectByIterate/48       3643 ns         3643 ns       189418
BM_GetObjectByIterate/64       6877 ns         6877 ns       100505
BM_GetObjectByIterate/80      11081 ns        11081 ns        62114
BM_GetObjectByIterate/96      16769 ns        16769 ns        41888
BM_GetObjectByMap/2            86.6 ns         86.6 ns      8092766
BM_GetObjectByMap/10            566 ns          566 ns      1207292
BM_GetObjectByMap/18           1067 ns         1067 ns       637047
BM_GetObjectByMap/26           1651 ns         1651 ns       410442
BM_GetObjectByMap/32           2151 ns         2151 ns       320698
BM_GetObjectByMap/48           3475 ns         3475 ns       196641
BM_GetObjectByMap/64           5065 ns         5065 ns       138496
BM_GetObjectByMap/80           6386 ns         6386 ns       103811
BM_GetObjectByMap/96           8313 ns         8313 ns        84515

General object will not have too many data members, it seems slower if the count of members less than 32.

image

#include <benchmark/benchmark.h>

#include <algorithm>
#include <forward_list>
#include <iostream>
#include <list>
#include <random>
#include <string>
#include <vector>

using Object = std::forward_list<std::string>;
using NameList = std::vector<std::string>;

std::string GenerateString() {
  std::seed_seq seq{time(0)};
  static std::default_random_engine gen{seq};
  std::uniform_int_distribution<size_t> distN(4, 15);
  std::uniform_int_distribution<unsigned char> distCh('a', 'z');
  std::string s(distN(gen), '\0');
  for (auto& ch : s) {
    ch = distCh(gen);
  }
  return s;
}

Object GenerateObject(size_t n) {
  Object obj;
  for (auto i = 0; i != 2 * n; ++i) {
    obj.emplace_front(GenerateString());
  }
  return obj;
}

NameList GetObjectNames(Object const& obj) {
  NameList names;
  for (auto it = obj.cbegin(); it != obj.cend(); ++it) {
    names.emplace_back(*it);
    if (++it == obj.cend()) {
      break;
    }
  }
  std::seed_seq seq{time(0)};
  static std::default_random_engine gen{seq};
  std::shuffle(names.begin(), names.end(), gen);
  return names;
}

void BM_GetObjectByIterate(benchmark::State& state) {
  auto object = GenerateObject(state.range(0));
  auto names = GetObjectNames(object);
  for (auto _ : state) {
    for (auto const& name : names) {
      std::string value;
      for (auto it = object.cbegin(), cend = object.cend(); it != cend; ++it) {
        if (name == *it) {
          if (++it != cend) {
            benchmark::DoNotOptimize(value = *it);
          }
        } else if (++it == cend) {
          break;
        }
      }  // for object
    }    // for name
  }      // for state
}

BENCHMARK(BM_GetObjectByIterate)
  ->DenseRange(1 << 1, 1 << 5, 1 << 3)
  ->DenseRange(1 << 5, 100, 1 << 4);

void BM_GetObjectByMap(benchmark::State& state) {
  auto object = GenerateObject(state.range(0));
  auto names = GetObjectNames(object);
  for (auto _ : state) {
    std::map<std::string_view, decltype(object.cend())> m;
    for (auto it = object.cbegin(), cend = object.cend(); it != cend; ++it) {
      auto name = it++;
      if (it == cend) {
        break;
      }
      m[name->c_str()] = it;
    }  // for object

    for (auto const& name : names) {
      std::string value;
      auto it = m.find(name);
      if (it != m.cend()) {
        benchmark::DoNotOptimize(value = *(it->second));
      }
    }  // for name
  }    // for state
}

BENCHMARK(BM_GetObjectByMap)
  ->DenseRange(1 << 1, 1 << 5, 1 << 3)
  ->DenseRange(1 << 5, 100, 1 << 4);

link

AVX2 instruction set required. Missing option -mavx2

os:ubuntu 20
gcc:9
cmake:3.25

cat /proc/cpuinfo | grep avx2
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap intel_pt xsaveopt dtherm ida arat pln pts md_clear flush_l1d

error:error "AVX2 instruction set required. Missing option -mavx2 ?"

Error when trying to build Fuzz -DBUILD_FUZZ=ON

I'm trying to build the fuzz code:

cmake -S . -B build -DBUILD_FUZZ=ON

The command fails with the following output:

-- The CXX compiler identification is Clang 18.1.8
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++-18 - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at /usr/share/cmake-3.22/Modules/ExternalProject.cmake:2806 (message):
  At least one entry of URL is a path (invalid in a list)
Call Stack (most recent call first):
  /usr/share/cmake-3.22/Modules/ExternalProject.cmake:3716 (_ep_add_download_command)
  CMakeLists.txt:15 (ExternalProject_Add)


-- Configuring incomplete, errors occurred!
See also "/home/ishuah/workshop/fuzzing-experiment/sonic-cpp/build/_deps/googletest-subbuild/CMakeFiles/CMakeOutput.log".

CMake Error at /usr/share/cmake-3.22/Modules/FetchContent.cmake:1075 (message):
  CMake step for googletest failed: 1
Call Stack (most recent call first):
  /usr/share/cmake-3.22/Modules/FetchContent.cmake:1216:EVAL:2 (__FetchContent_directPopulate)
  /usr/share/cmake-3.22/Modules/FetchContent.cmake:1216 (cmake_language)
  /usr/share/cmake-3.22/Modules/FetchContent.cmake:1259 (FetchContent_Populate)
  tests/CMakeLists.txt:22 (FetchContent_MakeAvailable)


-- Configuring incomplete, errors occurred!
See also "/home/ishuah/workshop/fuzzing-experiment/sonic-cpp/build/CMakeFiles/CMakeOutput.log".

Core dumped without AVX2 instructiom (VM instance)

Yes, I know that sonic-cpp relies on the AVX2 instruction, for most VM instance, especially the cloud VMs, there's no AVX2 supported yet. But why the simdjson works normally? Can you fall back to sse/sse2 if no AVX2?

❯ ./build/benchmark/bench
[1]    2624172 illegal hardware instruction (core dumped)  ./build/benchmark/bench

CPU flags

❯ cat  /proc/cpuinfo | grep flags | uniq

flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pse36 clflush mmx fxsr sse sse2 ht syscall nx lm rep_good nopl xtopology cpuid tsc_known_freq pni cx16 x2apic hypervisor lahf_lm pti

vs2022不能编译过

F:\work\github\sonic-cpp\include\sonic/allocator.h(92,9): error C3861: 'builtin_ia32_pause': identifier not found
1>assert_test.cpp
1>document_test.cpp
1>F:\work\github\sonic-cpp\tests\document_test.cpp(17,10): fatal error C1083: Cannot open include file: 'dirent.h': No such file or directory
1>error_test.cpp
1>F:\work\github\sonic-cpp\include\sonic/error.h(95,3): error C2059: syntax error: '('
1>F:\work\github\sonic-cpp\include\sonic/error.h(95,3): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/error.h(95,3): error C2059: syntax error: ')'
1>F:\work\github\sonic-cpp\include\sonic/error.h(96,3): error C2059: syntax error: '('
1>F:\work\github\sonic-cpp\include\sonic/error.h(96,3): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/error.h(96,3): error C2535: 'int sonic_json::ParseResult::attribute(void)': member function already defined or declared
1>F:\work\github\sonic-cpp\include\sonic/error.h(95,3): message : see declaration of 'sonic_json::ParseResult::attribute'
1>F:\work\github\sonic-cpp\include\sonic/error.h(96,3): error C2059: syntax error: ')'
1>F:\work\github\sonic-cpp\include\sonic/allocator.h(92,9): error C3861: 'builtin_ia32_pause': identifier not found
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(49,3): error C2059: syntax error: '('
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(49,3): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(49,3): error C2059: syntax error: ')'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(55,3): error C2059: syntax error: '('
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(55,3): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(55,3): error C2535: 'int sonic_json::WriteBuffer::attribute(void)': member function already defined or declared
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(49,3): message : see declaration of 'sonic_json::WriteBuffer::attribute'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(55,3): error C2059: syntax error: ')'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(56,3): error C2059: syntax error: '('
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(56,3): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(56,3): error C2535: 'int sonic_json::WriteBuffer::attribute(void)': member function already defined or declared
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(49,3): message : see declaration of 'sonic_json::WriteBuffer::attribute'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(56,3): error C2059: syntax error: ')'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(57,3): error C2059: syntax error: '('
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(57,3): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(57,3): error C2535: 'int sonic_json::WriteBuffer::attribute(void)': member function already defined or declared
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(49,3): message : see declaration of 'sonic_json::WriteBuffer::attribute'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(57,3): error C2059: syntax error: ')'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(63,3): error C2059: syntax error: '('
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(63,3): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(63,3): error C2535: 'int sonic_json::WriteBuffer::attribute(void)': member function already defined or declared
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(49,3): message : see declaration of 'sonic_json::WriteBuffer::attribute'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(63,3): error C2059: syntax error: ')'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(78,3): error C2059: syntax error: '('
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(78,3): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(78,3): error C2535: 'int sonic_json::WriteBuffer::attribute(void)': member function already defined or declared
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(49,3): message : see declaration of 'sonic_json::WriteBuffer::attribute'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(78,3): error C2059: syntax error: ')'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(85,3): error C2988: unrecognizable template declaration/definition
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(85,3): error C2059: syntax error: '('
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(85,3): error C2059: syntax error: ')'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(85,37): error C2334: unexpected token(s) preceding '{'; skipping apparent function body
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(96,3): error C2988: unrecognizable template declaration/definition
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(96,3): error C2059: syntax error: '('
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(96,3): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(96,3): error C2059: syntax error: ')'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(97,10): error C2061: syntax error: identifier 'n'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(97,16): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(98,17): error C2061: syntax error: identifier 'top
'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(98,10): error C2838: 'memcpy': illegal qualified name in member declaration
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(99,10): error C2988: unrecognizable template declaration/definition
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(99,10): error C2143: syntax error: missing ';' before '+='
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(99,10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(99,14): error C2238: unexpected token(s) preceding ';'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(101,3): error C2065: 'always_inline': undeclared identifier
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(101,3): error C7525: inline variables require at least '/std:c++17'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(101,22): error C2144: syntax error: 'void' should be preceded by ';'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(102,17): error C2065: 'top
': undeclared identifier
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(103,5): error C2065: 'top
': undeclared identifier
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(28,48): error C2614: 'sonic_json::WriteBuffer': illegal member initialization: 'cap
' is not a base or member
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(31,18): error C2039: 'buf_': is not a member of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(26,7): message : see declaration of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(31,34): error C2039: 'top_': is not a member of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(26,7): message : see declaration of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(31,50): error C2039: 'cap_': is not a member of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(26,7): message : see declaration of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(31,9): error C2614: 'sonic_json::WriteBuffer': illegal member initialization: 'buf_' is not a base or member
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(31,25): error C2614: 'sonic_json::WriteBuffer': illegal member initialization: 'top_' is not a base or member
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(31,41): error C2614: 'sonic_json::WriteBuffer': illegal member initialization: 'cap_' is not a base or member
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(32,9): error C2039: 'setZero': is not a member of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(26,7): message : see declaration of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(34,30): error C2065: 'buf_': undeclared identifier
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(38,5): error C2065: 'buf_': undeclared identifier
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(38,16): error C2039: 'buf_': is not a member of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(26,7): message : see declaration of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(39,5): error C2065: 'top_': undeclared identifier
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(39,16): error C2039: 'top_': is not a member of 'sonic_json::WriteBuffer'
1>F:\work\github\sonic-cpp\include\sonic/writebuffer.h(26,7): message : see declaration of 'sonic_json::WriteBuffer'

Add more examples for Document API

We need to add more examples for Document API into example directory

The example should be like follows:

#include <iostream>
#include <string>

#include "sonic/sonic.h"

int main() {
  using NodeType = sonic_json::Node;
  using Allocator = typename NodeType::AllocatorType;
  sonic_json::Node node;
  Allocator alloc;

  node.SetObject();
  node.AddMember("Key", NodeType("Value", alloc), alloc);
  std::cout << "Add member successfully!\n";
  return 0;
}
// g++ -I../include/ -march=haswell --std=c++11 get_and_set.cpp -o get_and_set

some optimizations or enhancement?

Record possible optimizations and enhancements for sonic-cpp

Optimize:

  • use smallvec in parseimpl
  • port rust itoa

Enhancements

  • add JSON iterator API

doc.HasParseError()默认值赋值为true

doc.HasParseError()的默认值建议赋值为true,doc.Parse(json)成功的时候赋值为false。因为有些情况,json为空就不存在pasre操作,doc引用返回给外部的时候,doc.HasParseError()为fasle(目前的默认值), 外界认为是doc初始化成功,后边doc.HasMember("xxx")就会core了

operator[]/AtPoiter返回的引用(指针)有bug?

void fun3()
{
SONIC_DEFAULT_ALLOCATOR alloc;
sonic_json::Node node, node1Inner, node2Inner;

node1Inner.SetObject();
node1Inner.AddMember("innerKey1", sonic_json::Node("innerValue1", alloc), alloc);

node2Inner.SetObject();
node2Inner.AddMember("innerKey2", sonic_json::Node("innerValue2", alloc), alloc);

node.SetObject();
node.AddMember("key1", std::move(node1Inner), alloc);
node.AddMember("key2", std::move(node2Inner), alloc);

printf("js:%s\n", node.Dump().c_str());

auto & nRef = node["key2"];
node.RemoveMember("key1");

//这行代码不能执行,抛异常显示nRef不是一个Object?
nRef.AddMember("newKey", sonic_json::Node("newValue", alloc), alloc);

}

我看了代码RemoveMember底下会修改DNode的位置,导致nRef引用的DNode已经不是当前有效的地址了?类似的操作std::map是支持的吧?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.