code_twain/sln/sdk/include/utility/known_file.h

310 lines
32 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.


// json.h : simple json parser/maker
//
// Author: Gongbing
//
// Date: 2016-07-12, rewrite on 2019-10-27
#pragma once
#include <string>
#include <vector>
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
namespace known_file_util
{
struct IJson;
struct IJsonW;
enum _json_type
{
JV_UNKNOWN = 0,
JV_BOOL,
JV_INT,
JV_FLOAT,
// JV_ARRAY,
JV_STRING,
JV_OBJECT,
JV_UINT64,
};
typedef union _json_member
{
_json_type type;
void *nothing; // JV_UNKNOWN = 0,
bool bool_val; // JV_BOOL,
int int_val; // JV_INT,
double double_val; // JV_FLOAT,
const char *str_val; // JV_STRING,
IJson *child; // JV_OBJECT, IJson or IJsonW value
unsigned long long uint64_val; // JV_UINT64,
}JSONMEM, *LPJSONMEM;
typedef union _json_member_w
{
_json_type type;
void *nothing; // JV_UNKNOWN = 0,
bool bool_val; // JV_BOOL,
int int_val; // JV_INT,
double double_val; // JV_FLOAT,
const wchar_t *str_val; // JV_STRING,
IJsonW *child; // JV_OBJECT, IJson or IJsonW value
unsigned long long uint64_val; // JV_UINT64,
}JSONMEMW, *LPJSONMEMW;
// NOTE: following interfaces, do NOTHING on transfer chars(no converting from '\n' to 0x0d, ...), user should transfer them yourself !!!
__declspec(novtable) struct IJson : public ref_util::IRef
{
// function: parse a json string
// json_str: string that in json format
// start: [in] - the start position of json_str, start from 0 if it was NULL; [out] - the ending position when returned
// return: true - success
COM_API_DECLARE(bool, attach(const char* json_str, int* start = NULL));
COM_API_DECLARE(long, members(void));
// function: convert IJson object to plain text
// callback - data: (const char*)
// len: bytes of data
// total: unused, always be ZERO
// flag: always be inter_module_data::DATA_FLAG_FINAL
// param: the same as you passed into the API as 'param'
COM_API_DECLARE(void, to_string(inter_module_data::set_data result, void* param));
COM_API_DECLARE(const char*, key(void)); // 'val' to receive the key value, use it immediately and need not free
// 'key' for get_xxx apis can include path, e.g. get_value("data\\school\\score", score)
COM_API_DECLARE(bool, get_value(const char* key, bool& val));
COM_API_DECLARE(bool, get_value(const char* key, int& val));
COM_API_DECLARE(bool, get_value(const char* key, double& val));
COM_API_DECLARE(bool, get_value(const char* key, unsigned long long& val));
COM_API_DECLARE(bool, get_value(const char* key, IJson** val)); // you should call val->release() to free the returned object
COM_API_DECLARE(bool, get_value(const char* key, const char** val)); // you should use the 'val' immediately, and need not free it!
COM_API_DECLARE(void, clear(void));
COM_API_DECLARE(void, set_key(const char* key_str));
COM_API_DECLARE(bool, set_value(const char* key, bool val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, set_value(const char* key, int val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, set_value(const char* key, double val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, set_value(const char* key, unsigned long long val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, set_value(const char* key, const char* val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, set_value(const char* key, IJson* val, bool insert_if_not_exist = true)); // you can call val->release
COM_API_DECLARE(bool, set_value(int index, bool val, bool insert = false)); // for array operation
COM_API_DECLARE(bool, set_value(int index, int val, bool insert = false)); // for array operation
COM_API_DECLARE(bool, set_value(int index, double val, bool insert = false)); // for array operation
COM_API_DECLARE(bool, set_value(int index, unsigned long long val, bool insert = false)); // for array operation
COM_API_DECLARE(bool, set_value(int index, const char* val, bool insert = false)); // for array operation
COM_API_DECLARE(bool, set_value(int index, IJson* val, bool insert = false)); // you can call val->release
COM_API_DECLARE(bool, remove_value(const char* key));
COM_API_DECLARE(bool, remove_value(int index));
COM_API_DECLARE(IJson*, first_child(void)); // call 'release()' on returned object after use
COM_API_DECLARE(IJson*, next_child(void)); // call 'release()' on returned object after use
// enum member, 'JV_UNKNOWN' will enum all members, all values but 'object' need not free
// enumerating should stopped if returned JV_UNKNOWN !!!
COM_API_DECLARE(JSONMEM, first_member(_json_type type = JV_UNKNOWN)); // call 'release()' on returned object after use
COM_API_DECLARE(JSONMEM, next_member(void)); // call 'release()' on returned object after use
COM_API_DECLARE(JSONMEM, operator[](int index)); // call 'release()' on returned object after use
COM_API_DECLARE(bool, is_array(void)); // whether this object is an array
// following apis only effect array
COM_API_DECLARE(IJson*&, operator+=(bool val)); // *(IJson*) += true;
COM_API_DECLARE(IJson*&, operator+=(int val)); // *(IJson*) += 100;
COM_API_DECLARE(IJson*&, operator+=(double val)); // *(IJson*) += 100.0;
COM_API_DECLARE(IJson*&, operator+=(unsigned long long val)); // *(IJson*) += (unsigned long long)100;
COM_API_DECLARE(IJson*&, operator+=(const char* val)); // *(IJson*) += "array sub string";
COM_API_DECLARE(IJson*&, operator+=(known_file_util::IJson* val)); // *(IJson*) += (IJson*)child;
COM_API_DECLARE(IJson*&, operator-=(int index)); // *(IJson*) -= 0;
};
// unicode version of IJson, and transfer chars(convert from '\n' to 0x0d, ...) automately
__declspec(novtable) struct IJsonW : public ref_util::IRef
{
// function: parse a json string
// json_str: string that in json format
// start: [in] - the start position of json_str, start from 0 if it was NULL; [out] - the ending position when returned
// return: true - success
COM_API_DECLARE(bool, attach(const wchar_t* json_str, int* start = NULL));
COM_API_DECLARE(long, members(void));
// function: convert IJson object to plain text
// callback - data: (const wchar_t*)
// len: bytes of data
// total: unused, always be ZERO
// flag: always be inter_module_data::DATA_FLAG_FINAL
// param: the same as you passed into the API as 'param'
//
// tab - set this parameter to get formated text, or else get a compact text (not support now)
COM_API_DECLARE(void, to_string(inter_module_data::set_data result, void* param, const wchar_t* tab = NULL));
COM_API_DECLARE(const wchar_t*, key(void)); // 'val' to receive the key value, use it immediately and need not free
// 'key' for get_xxx apis can include path, e.g. get_value("data\\school\\score", score)
COM_API_DECLARE(bool, get_value(const wchar_t* key, bool& val));
COM_API_DECLARE(bool, get_value(const wchar_t* key, int& val));
COM_API_DECLARE(bool, get_value(const wchar_t* key, double& val));
COM_API_DECLARE(bool, get_value(const wchar_t* key, unsigned long long& val));
COM_API_DECLARE(bool, get_value(const wchar_t* key, IJsonW** val)); // you should call val->release() to free the returned object
COM_API_DECLARE(bool, get_value(const wchar_t* key, const wchar_t** val)); // you should use the 'val' immediately, and need not free it!
COM_API_DECLARE(void, clear(void));
COM_API_DECLARE(bool, set_as_array(bool arr)); // set as JV_ARRAY, only effect when empty
COM_API_DECLARE(void, set_key(const wchar_t* key_str));
COM_API_DECLARE(bool, set_value(const wchar_t* key, bool val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, set_value(const wchar_t* key, int val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, set_value(const wchar_t* key, double val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, set_value(const wchar_t* key, unsigned long long val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, set_value(const wchar_t* key, const wchar_t* val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, set_value(const wchar_t* key, IJsonW* val, bool insert_if_not_exist = true)); // you can call val->release
COM_API_DECLARE(bool, set_value(int index, bool val, bool insert = false)); // for array operation
COM_API_DECLARE(bool, set_value(int index, int val, bool insert = false)); // for array operation
COM_API_DECLARE(bool, set_value(int index, double val, bool insert = false)); // for array operation
COM_API_DECLARE(bool, set_value(int index, unsigned long long val, bool insert = false)); // for array operation
COM_API_DECLARE(bool, set_value(int index, const wchar_t* val, bool insert = false)); // for array operation
COM_API_DECLARE(bool, set_value(int index, IJsonW* val, bool insert = false)); // you can call val->release
COM_API_DECLARE(bool, remove_value(const wchar_t* key));
COM_API_DECLARE(bool, remove_value(int index));
COM_API_DECLARE(IJsonW*, first_child(void)); // call 'release()' on returned object after use
COM_API_DECLARE(IJsonW*, next_child(void)); // call 'release()' on returned object after use
// enum member, 'JV_UNKNOWN' will enum all members, all values but 'object' need not free
// enumerating should stopped if returned JV_UNKNOWN !!!
COM_API_DECLARE(JSONMEMW, first_member(_json_type type = JV_UNKNOWN)); // call 'release()' on returned object after use
COM_API_DECLARE(JSONMEMW, next_member(void)); // call 'release()' on returned object after use
COM_API_DECLARE(JSONMEMW, operator[](int index)); // call 'release()' on returned object after use
COM_API_DECLARE(bool, is_array(void)); // whether this object is an array
// following apis only effect array
COM_API_DECLARE(IJsonW*&, operator+=(bool val)); // *(IJsonW*) += true;
COM_API_DECLARE(IJsonW*&, operator+=(int val)); // *(IJsonW*) += 100;
COM_API_DECLARE(IJsonW*&, operator+=(double val)); // *(IJsonW*) += 100.0;
COM_API_DECLARE(IJsonW*&, operator+=(unsigned long long val)); // *(IJsonW*) += (unsigned long long)100;
COM_API_DECLARE(IJsonW*&, operator+=(const wchar_t* val)); // *(IJsonW*) += "array sub string";
COM_API_DECLARE(IJsonW*&, operator+=(known_file_util::IJsonW* val)); // *(IJsonW*) += (IJsonW*)child;
COM_API_DECLARE(IJsonW*&, operator-=(int index)); // *(IJsonW*) -= 0;
};
// xml parser
enum _xml_clear_mask
{
XML_CLEAR_XML_CHILD = 0x01,
XML_CLEAR_TEXT = 0x02,
XML_CLEAR_ATTRIBUTES = 0x04,
XML_CLEAR_TAG_NAME = 0x08,
XML_CLEAR_ALL = -1,
};
__declspec(novtable) struct IXmlW : public ref_util::IRef
{
// function: parse a XML string
// xml_str: string that in XML format
// start: [in] - the start position of xml_str, start from 0 if it was NULL; [out] - the ending position when returned
// return: true - success
COM_API_DECLARE(bool, attach(const wchar_t* xml_str, int* start = NULL));
COM_API_DECLARE(void, clear(int clear_mask = XML_CLEAR_ALL));
COM_API_DECLARE(void, set_tag_name(const wchar_t* name));
// for multiple elements with the same 'tag name' can be coexists, all path in following methods
// only walk through the first matched element !!!
//
// e.g. <html>
// <meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" />
// <meta http-equiv = "content-type" content = "text/html;charset=utf-8">
// <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
// </meta>
// </html>
//
// then call set_attribute(L"html\\meta\\link\\rel", L"icon", false)
// or get_child(L"html\\meta\\link") would be failed
//
COM_API_DECLARE(bool, set_attribute(const wchar_t* attr_path, const wchar_t* attr_val, bool insert_if_not_exist = true));
COM_API_DECLARE(bool, remove_attribute(const wchar_t* attr_path)); // remove the first attribute named path matches 'attr_path'
COM_API_DECLARE(bool, add_child(IXmlW* xml, int index = -1));
// function: to replace or add a text <tag>text</tag>
//
// parameter: text - the text to be set, clear if it was NULL
//
// replace - true to replace or clear the text with index 'index'; false to insert a new text at 'index'
//
// index - the index of the text element, -1 for all text elements when 'replace' was true, or the last element when 'replace' was false
//
// return: whether done
//
// NOTE: the index is in only in text children sequence when 'replace' was true,
// and in all children sequence when 'replace' was false
COM_API_DECLARE(bool, set_text(const wchar_t* text, bool replace = true, int index = -1));
// function: to add a child xml element
//
// parameter: name - tag name of the element
//
// attrs - attributes name list, ending with double '\0'
//
// attr_vals - attributes value list, ending with double '\0', must ONE-to-ONE to attrs
//
// simple_text - plain text of the element
//
// index - the inserting position of the element
//
// return: the new element, you should call 'release' whenever use it
//
// NOTE: this create a simple xml element: <name attrs0=attr_vals0, ..., >simple_text</name>
COM_API_DECLARE(IXmlW*, create_child(const wchar_t* name, const wchar_t* attrs = NULL, const wchar_t* attr_vals = NULL, const wchar_t* simple_text = NULL, int index = -1));
COM_API_DECLARE(bool, remove_child(IXmlW* xml));
COM_API_DECLARE(bool, remove_child(int index));
COM_API_DECLARE(void, set_single_line(bool single_line)); // set single line if has no children when call 'to_string'
// whether this object is comment or plain text such as scripts ...
COM_API_DECLARE(bool, is_plain_text(void));
COM_API_DECLARE(bool, is_single_line(void)); // whether output single line if has no children when call 'to_string'
COM_API_DECLARE(int, child_index(IXmlW* child));
// access ...
// function: convert IJson object to plain text
// callback - data: (const char*)a BOM string (with BOM head)
// len: bytes of data
// total: unused, always be ZERO
// flag: always be inter_module_data::DATA_FLAG_FINAL
// param: the same as you passed into the API as 'param'
// with_xml_tag - whether add "<?xml version="1.0" encoding="utf-8"?>" at beginning
// tab - to specify the indentation of every child
COM_API_DECLARE(void, to_string(inter_module_data::set_data result, void* param, bool with_xml_tag = true, const wchar_t* tab = L" "));
COM_API_DECLARE(const wchar_t*, get_tag_name(void));
COM_API_DECLARE(bool, get_attribute(const wchar_t* attr_path, const wchar_t** val));
COM_API_DECLARE(bool, get_text(const wchar_t** val, int index = 0)); // return 'text' in this formal: <tag>text</tag>
// attributes ...
COM_API_DECLARE(long, attributes(void));
COM_API_DECLARE(bool, has_attribute(const wchar_t* name));
COM_API_DECLARE(bool, first_attribute(const wchar_t** name, const wchar_t** val));
COM_API_DECLARE(bool, next_attribute(const wchar_t** name, const wchar_t** val));
// children ...
COM_API_DECLARE(long, children(void));
COM_API_DECLARE(IXmlW*, get_child(const wchar_t* child_path)); // call 'release' to free the return value
COM_API_DECLARE(IXmlW*, get_child(int index)); // call 'release' to free the return value
// function: enumerating children, not finding recursive
//
// parameter: tag - tag name of the child
//
// attr - attribute names of the child, ending with double '\0'
//
// attr_val - attribute values of the child, ONE-to-ONE to 'attr', ending with double '\0'
//
// return: the child pointer, call 'release' to free it after use
//
// NOTE: return the first matches the conditions child
COM_API_DECLARE(IXmlW*, first_child(const wchar_t* tag = NULL, const wchar_t* attr = NULL, const wchar_t* attr_val = NULL));
COM_API_DECLARE(IXmlW*, next_child(const wchar_t* tag = NULL, const wchar_t* attr = NULL, const wchar_t* attr_val = NULL));
};
// the parameter 'start' can receive the error point if the 'data' was invalid
PORT_API(IJson*) create_json(const char* data = NULL, int* start = NULL);
PORT_API(IJsonW*) create_jsonW(const wchar_t* data = NULL, int* start = NULL);
PORT_API(IXmlW*) create_xmlW(const wchar_t* data = NULL, int* start = NULL);
}