diff --git a/cysimdjson/cysimdjsonc.cpp b/cysimdjson/cysimdjsonc.cpp index 7621ffa..04abffd 100644 --- a/cysimdjson/cysimdjsonc.cpp +++ b/cysimdjson/cysimdjsonc.cpp @@ -186,3 +186,16 @@ int cysimdjson_parser_test() { return 0; } + + +size_t cysimdjson_minify(void * e, char * buffer, size_t buffer_size) { + simdjson::dom::element * element = static_cast(e); + std::string json_string = simdjson::minify(*element); + + if (json_string.size() < buffer_size) { + std::strcpy(buffer, json_string.c_str()); + return json_string.size(); + } else { + return 0; // The output JSON doesn't fit + } +} diff --git a/cysimdjson/cysimdjsonc.h b/cysimdjson/cysimdjsonc.h index 1597c57..689e320 100644 --- a/cysimdjson/cysimdjsonc.h +++ b/cysimdjson/cysimdjsonc.h @@ -27,4 +27,8 @@ bool cysimdjson_element_get(const char * attrname, size_t attrlen, void * elemen int cysimdjson_parser_test(void); +// Export element `e` as JSON into the "buffer" and returns the exported JSON size. +// If the "buffer_size" is too small, returns 0; +size_t cysimdjson_minify(void * element, char * buffer, size_t buffer_size); + #endif diff --git a/test/test_capi/__init__.py b/test/test_capi/__init__.py index b1ceca7..275cded 100644 --- a/test/test_capi/__init__.py +++ b/test/test_capi/__init__.py @@ -26,6 +26,9 @@ def setUp(self): self.cysimdjsonapi.cysimdjson_element_get.restype = ctypes.c_bool self.cysimdjsonapi.cysimdjson_element_get.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p, ctypes.c_void_p] + self.cysimdjsonapi.cysimdjson_minify.restype = ctypes.c_size_t + self.cysimdjsonapi.cysimdjson_minify.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t] + def test_capi_01(self): parser = self.cysimdjsonapi.cysimdjson_parser_new() @@ -153,3 +156,57 @@ def test_capi_06(self): cython_element = cysimdjson.addr_to_element(element_addr) val = cython_element.at_pointer("/document/key4") self.assertEqual(val, 40) + + + def test_capi_07(self): + ''' + Export parsed JSON into a string + ''' + + parser = cysimdjson.JSONParser() + + with open(os.path.join(THIS_DIR, 'test.json'), 'r') as fo: + json_parsed = parser.parse_string(fo.read()) + + # Transition into C API + element_addr = json_parsed.get_addr() + self.assertNotEqual(element_addr, 0) + + buf_max_size = 16*1024 + buf = ctypes.create_string_buffer(buf_max_size) + + size = self.cysimdjsonapi.cysimdjson_minify( + element_addr, + buf, + buf_max_size + ) + self.assertNotEqual(size, 0) + + json_string = buf[:size].decode('utf-8') + self.assertEqual(json_string, r'''{"document":{"key1":1,"key2":"2","key3":"3","key4":40,"key5":"50"}}''') + + + + def test_capi_08(self): + ''' + Try to export parsed JSON into a string but the output buffer is too small + ''' + + parser = cysimdjson.JSONParser() + + with open(os.path.join(THIS_DIR, 'test.json'), 'r') as fo: + json_parsed = parser.parse_string(fo.read()) + + # Transition into C API + element_addr = json_parsed.get_addr() + self.assertNotEqual(element_addr, 0) + + buf_max_size = 3 + buf = ctypes.create_string_buffer(buf_max_size) + + size = self.cysimdjsonapi.cysimdjson_minify( + element_addr, + buf, + buf_max_size + ) + self.assertEqual(size, 0)