Repository: TeskaLabs/cysimdjson (language: python)

Issue:
Create `export` to string or bytes function and expose it via C API



Discussion / hints:

Fix patch:
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<simdjson::dom::element *>(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


Test patch:
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)