tools/jsonschematoc11/jsonschematoc11.py
import sys
import os
import argparse
from configparser import SafeConfigParser
import logging
import json
from c11types import BuildC11Type
from c11types.c11typestruct import C11TypeStruct
logging.basicConfig(level=logging.DEBUG, format=u'%(asctime)s [%(name)s][%(levelname)s](%(filename)s:%(lineno)d) %(message)s')
logger = logging.getLogger(name=u'JSONSchemaToC11')
class C11TypeLibrary(object):
def __init__(self):
"""Construct and declare some vars."""
self.c11Types = dict()
def setVersion(self, major=0, minor=0, patch=0):
self.major = major
self.minor = minor
self.patch = patch
def addC11Type(self, schemaName, c11Type):
if schemaName in self.c11Types:
return (1, u'already have %s in c11 type library' % schemaName)
self.c11Types[schemaName] = c11Type
return (0, u'')
def addSchema(self, rootPath, schemaFileName, config=None):
schema_file_path = os.path.join(rootPath, schemaFileName)
with open(schema_file_path, u'r') as schema_file:
schema = json.load(schema_file)
if schema is None:
return (1, u'Can\'t parse the schema file %s' % schema_file_path)
code_headers = None
if config is not None and config.has_option(u'code.headers', schemaFileName):
code_file_path = config.get(u'code.headers', schemaFileName)
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_headers = code_file.readlines()
code_sources_variable = None
if config is not None and config.has_option(u'code.sources.variable', schemaFileName):
code_file_path = config.get(u'code.sources.variable', schemaFileName)
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_sources_variable = code_file.readlines()
code_sources_function = None
if config is not None and config.has_option(u'code.sources.function', schemaFileName):
code_file_path = config.get(u'code.sources.function', schemaFileName)
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_sources_function = code_file.readlines()
code_parsers_from = None
if config is not None and config.has_option(u'code.parsers.from', schemaFileName):
code_file_path = config.get(u'code.parsers.from', schemaFileName)
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_parsers_from = code_file.readlines()
code_parsers_to = None
if config is not None and config.has_option(u'code.parsers.to', schemaFileName):
code_file_path = config.get(u'code.parsers.to', schemaFileName)
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_parsers_to = code_file.readlines()
(c11_type, error_code, error_message) = BuildC11Type(schemaFileName, schema, isSchema=True, manualCodeHeaders=code_headers, manualCodeSourcesVariable=code_sources_variable, manualCodeSourcesFunction=code_sources_function , manualCodeParsersFrom=code_parsers_from, manualCodeParsersTo=code_parsers_to)
if error_code != 0:
return (error_code, u'Has error when build - %s' % error_message)
(error_code, error_message) = self.addC11Type(schemaFileName, c11_type)
if error_code != 0:
return (error_code, u'Has error when add - %s' % error_message)
return (0, u'')
def addSchemaDirectory(self, schemaDirectory, config=None):
schema_directory = os.path.normpath(schemaDirectory)
if not os.path.isdir(schema_directory):
return (1, u'The schema directory (%s) is not a valid directory' % schema_directory)
for root_path, _, file_names in os.walk(schema_directory, topdown=False):
for file_name in file_names:
if not file_name.endswith(u'schema.json'):
continue
(error_code, error_message) = self.addSchema(root_path, file_name, config)
if error_code != 0:
return (error_code, error_message)
return (0, u'')
def codeVersion(self):
code_lines = []
code_lines.append(u'#define LIBGLTF_MAJOR_VERSION %s' % self.major)
code_lines.append(u'#define LIBGLTF_MINOR_VERSION %s' % self.minor)
code_lines.append(u'#define LIBGLTF_PATCH_VERSION %s' % self.patch)
return code_lines
def codeDefines(self):
code_lines = []
code_lines.append(u'#cmakedefine LIBGLTF_WITH_MSVC_MT')
code_lines.append(u'#cmakedefine LIBGLTF_WITH_GOOGLE_DRACO')
return code_lines
def codeHeaderParser(self):
code_lines = []
code_lines.append(u'struct SGlTF;')
code_lines.append(u'bool operator<<(SGlTF& _gltf, const std::string& _sContent);')
code_lines.append(u'bool operator>>(const SGlTF& _gltf, std::string& _sContent);')
code_lines.append(u'')
code_lines.append(u'/*!')
code_lines.append(u' * struct: SObject')
code_lines.append(u' */')
code_lines.append(u'struct SObject')
code_lines.append(u'{')
code_lines.append(u' SObject();')
code_lines.append(u' std::string schemaType;')
code_lines.append(u'};')
return code_lines
def codeSourceParser(self):
code_lines = []
code_lines.append(u'SObject::SObject()')
code_lines.append(u' : schemaType("")')
code_lines.append(u'{')
code_lines.append(u' //')
code_lines.append(u'}')
return code_lines
def preprocess(self):
for key in self.c11Types:
(error_code, error_message) = self.c11Types[key].revise(self.c11Types)
if error_code != 0:
return (error_code, error_message)
return (0, u'')
def generate(self, codeFileName, outputHeaderPath=None, outputSourcePath=None, nameSpace=None, config=None):
header_file_path = u'%s.h.cmakein' % codeFileName
source_file_path = u'%s.cpp' % codeFileName
if outputHeaderPath is not None:
header_file_path = os.path.join(outputHeaderPath, header_file_path)
if outputSourcePath is not None:
source_file_path = os.path.join(outputSourcePath, source_file_path)
with open(header_file_path, u'w') as header_file:
if config is not None and config.has_option(u'code', u'license'):
code_file_path = config.get(u'code', u'license')
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
header_file.write(u'/*\n')
code_file_lines = code_file.readlines()
for code_file_line in code_file_lines:
header_file.write(u' * ' + code_file_line)
header_file.write(u' */\n')
header_file.write(u'\n')
if config is not None and config.has_option(u'code.headers', u'header.begin'):
code_file_path = config.get(u'code.headers', u'header.begin')
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_header_extra_lines = code_file.readlines()
for code_header_extra_line in code_header_extra_lines:
header_file.write(code_header_extra_line)
header_file.write(u'\n')
if config is not None and config.has_option(u'code.headers', u'header.include'):
code_file_path = config.get(u'code.headers', u'header.include')
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_header_extra_lines = code_file.readlines()
for code_header_extra_line in code_header_extra_lines:
header_file.write(code_header_extra_line)
header_file.write(u'\n')
begin_space = u''
code_version_parser_lines = self.codeVersion()
for code_version_parser_line in code_version_parser_lines:
code_version_parser_line = u'%s%s\n' % (begin_space, code_version_parser_line)
header_file.write(code_version_parser_line)
if code_version_parser_line:
header_file.write(u'\n')
code_defines_parser_lines = self.codeDefines();
for code_defines_parser_line in code_defines_parser_lines:
code_defines_parser_line = u'%s%s\n' % (begin_space, code_defines_parser_line)
header_file.write(code_defines_parser_line)
if code_defines_parser_line:
header_file.write(u'\n')
if nameSpace is not None:
header_file.write(u'namespace %s\n' % nameSpace)
header_file.write(u'{\n')
begin_space = u' '
if config is not None and config.has_option(u'code.headers', u'header.namespace.begin'):
code_file_path = config.get(u'code.headers', u'header.namespace.begin')
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_header_extra_lines = code_file.readlines()
for code_header_extra_line in code_header_extra_lines:
header_file.write(code_header_extra_line)
header_file.write(u'\n')
code_header_parser_lines = self.codeHeaderParser()
for code_header_parser_line in code_header_parser_lines:
code_header_parser_line = u'%s%s\n' % (begin_space, code_header_parser_line)
header_file.write(code_header_parser_line)
if code_header_parser_lines:
header_file.write(u'\n')
code_header_declare_line = u'%s// declare all types\n' % (begin_space)
header_file.write(code_header_declare_line)
for key in self.c11Types:
c11_type = self.c11Types[key]
code_header_declare_line = u'%sstruct %s;\n' % (begin_space, c11_type.codeTypeName())
header_file.write(code_header_declare_line)
header_file.write(u'\n')
parent_type_names = []
for key in self.c11Types:
c11_type = self.c11Types[key]
if c11_type.codeTypeName() in parent_type_names:
continue
c11_type_code_lines = c11_type.codeHeader(parent_type_names)
for c11_type_code_line in c11_type_code_lines:
if c11_type_code_line:
c11_type_code_line = u'%s%s' % (begin_space, c11_type_code_line)
header_file.write(u'%s\n' % c11_type_code_line)
header_file.write(u'\n')
parent_type_names.append(c11_type.codeTypeName())
if isinstance(c11_type, C11TypeStruct):
for c11_type_parent_type_name in c11_type.getParentTypeNames():
parent_type_names.append(c11_type_parent_type_name)
if config is not None and config.has_option(u'code.headers', u'header.namespace.end'):
code_file_path = config.get(u'code.headers', u'header.namespace.end')
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_header_extra_lines = code_file.readlines()
for code_header_extra_line in code_header_extra_lines:
header_file.write(code_header_extra_line)
header_file.write(u'\n')
if nameSpace != None:
header_file.write(u'}\n')
if config is not None and config.has_option(u'code.headers', u'header.end'):
code_file_path = config.get(u'code.headers', u'header.end')
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_header_extra_lines = code_file.readlines()
for code_header_extra_line in code_header_extra_lines:
header_file.write(code_header_extra_line)
header_file.write(u'\n')
with open(source_file_path, u'w') as source_file:
if config is not None and config.has_option(u'code', u'license'):
code_file_path = config.get(u'code', u'license')
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_file_lines = code_file.readlines()
source_file.write(u'/*\n')
for code_file_line in code_file_lines:
source_file.write(u' * ' + code_file_line)
source_file.write(u' */')
source_file.write(u'\n')
source_file.write(u'#include "%s/%s.h"\n' % (codeFileName, codeFileName))
source_file.write(u'\n')
begin_space = u''
if nameSpace != None:
source_file.write(u'namespace %s\n' % nameSpace)
source_file.write(u'{\n')
begin_space = u' '
code_source_parser_lines = self.codeSourceParser()
for code_source_parser_line in code_source_parser_lines:
code_source_parser_line = u'%s%s\n' % (begin_space, code_source_parser_line)
source_file.write(code_source_parser_line)
if code_source_parser_lines:
source_file.write(u'\n')
parent_type_names = []
for key in self.c11Types:
c11_type = self.c11Types[key]
if c11_type.codeTypeName() in parent_type_names:
continue
c11_type_code_lines = c11_type.codeSource(parent_type_names)
for c11_type_code_line in c11_type_code_lines:
if c11_type_code_line:
c11_type_code_line = u'%s%s' % (begin_space, c11_type_code_line)
source_file.write(u'%s\n' % c11_type_code_line)
source_file.write(u'\n')
parent_type_names.append(c11_type.codeTypeName())
if isinstance(c11_type, C11TypeStruct):
for c11_type_parent_type_name in c11_type.getParentTypeNames():
parent_type_names.append(c11_type_parent_type_name)
if nameSpace != None:
source_file.write(u'}\n')
# generate parser
header_file_path = u'%sparser.h' % codeFileName
source_file_path = u'%sparser.cpp' % codeFileName
if outputSourcePath != None:
header_file_path = os.path.join(outputSourcePath, header_file_path)
source_file_path = os.path.join(outputSourcePath, source_file_path)
with open(header_file_path, u'w') as header_file:
if config is not None and config.has_option(u'code', u'license'):
code_file_path = config.get(u'code', u'license')
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_file_lines = code_file.readlines()
header_file.write(u'/*\n')
for code_file_line in code_file_lines:
header_file.write(u' * ' + code_file_line)
header_file.write(u' */\n')
header_file.write(u'\n')
header_file.write(u'#pragma once\n')
header_file.write(u'\n')
if config is not None and config.has_option(u'code.parser', u'header'):
code_file_path = config.get(u'code.parser', u'header')
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
code_header_extra_lines = code_file.readlines()
for code_header_extra_line in code_header_extra_lines:
header_file.write(code_header_extra_line)
header_file.write(u'\n')
begin_space = u''
if nameSpace != None:
header_file.write(u'namespace %s\n' % nameSpace)
header_file.write(u'{\n')
begin_space = u' '
header_file.write(u'%s%s\n' % (begin_space, u'template<typename TData>'))
header_file.write(u'%s%s\n' % (begin_space, u'class TDataDoc'))
header_file.write(u'%s%s\n' % (begin_space, u'{'))
header_file.write(u'%s%s\n' % (begin_space, u'public:'))
header_file.write(u'%s%s\n' % (begin_space, u' explicit TDataDoc(const TData& _rData, JSONCharDocument* _pDoc)'))
header_file.write(u'%s%s\n' % (begin_space, u' : data(_rData)'))
header_file.write(u'%s%s\n' % (begin_space, u' , doc(_pDoc)'))
header_file.write(u'%s%s\n' % (begin_space, u' {'))
header_file.write(u'%s%s\n' % (begin_space, u' //'))
header_file.write(u'%s%s\n' % (begin_space, u' }'))
header_file.write(u'%s%s\n' % (begin_space, u' const TData& data;'))
header_file.write(u'%s%s\n' % (begin_space, u' JSONCharDocument* doc;'))
header_file.write(u'%s%s\n' % (begin_space, u'};'))
header_file.write(u'\n')
for key in self.c11Types:
c11_type = self.c11Types[key]
if not isinstance(c11_type, C11TypeStruct):
continue
code_lines = c11_type.codeParserHeader()
for code_line in code_lines:
if not code_line:
header_file.write(u'\n')
else:
header_file.write(u'%s%s\n' % (begin_space, code_line))
header_file.write(u'\n')
if nameSpace != None:
header_file.write(u'}\n')
with open(source_file_path, u'w') as source_file:
if config is not None and config.has_option(u'code', u'license'):
code_file_path = config.get(u'code', u'license')
if os.path.isfile(code_file_path):
with open(code_file_path, u'r') as code_file:
source_file.write(u'/*\n')
code_file_lines = code_file.readlines()
for code_file_line in code_file_lines:
source_file.write(u' * ' + code_file_line)
source_file.write(u' */\n')
source_file.write(u'\n')
source_file.write(u'#include "%sparser.h"\n' % codeFileName)
source_file.write(u'\n')
begin_space = u''
if nameSpace != None:
source_file.write(u'namespace %s\n' % nameSpace)
source_file.write(u'{\n')
begin_space = u' '
source_file.write(u'%sbool operator<<(SGlTF& _gltf, const std::string& _sContent)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s JSONCharDocument json_doc;\n' % begin_space)
source_file.write(u'%s json_doc.Parse(_sContent.c_str());\n' % begin_space)
source_file.write(u'%s if (!json_doc.IsObject()) return false;\n' % begin_space)
source_file.write(u'%s return (_gltf << json_doc.GetObject());\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%sbool operator>>(const SGlTF& _gltf, std::string& _sContent)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s JSONCharDocument json_doc;\n' % begin_space)
source_file.write(u'%s if (!(TDataDoc<SGlTF>(_gltf, &json_doc) >> json_doc)) return false;\n' % begin_space)
source_file.write(u'%s JSONStringBuffer json_string_buffer;\n' % begin_space)
source_file.write(u'%s JSONWriter json_writer(json_string_buffer);\n' % begin_space)
source_file.write(u'%s if (!json_doc.Accept(json_writer)) return false;\n' % begin_space)
source_file.write(u'%s _sContent = json_string_buffer.GetString();\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%sbool operator<<(bool& _rData, const JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s if (!_JsonValue.IsBool()) return false;\n' % begin_space)
source_file.write(u'%s _rData = _JsonValue.GetBool();\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%sbool operator>>(const TDataDoc<bool>& _rData, JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s _JsonValue.SetBool(_rData.data);\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%sbool operator<<(int32_t& _rData, const JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s if (!_JsonValue.IsInt()) return false;\n' % begin_space)
source_file.write(u'%s _rData = _JsonValue.GetInt();\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%sbool operator>>(const TDataDoc<int32_t>& _rData, JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s _JsonValue.SetInt(_rData.data);\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%sbool operator<<(float& _rData, const JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s if (_JsonValue.IsNumber())\n' % begin_space)
source_file.write(u'%s {\n' % begin_space)
source_file.write(u'%s _rData = _JsonValue.GetFloat();\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s }\n' % begin_space)
source_file.write(u'%s if (_JsonValue.IsInt())\n' % begin_space)
source_file.write(u'%s {\n' % begin_space)
source_file.write(u'%s _rData = static_cast<float>(_JsonValue.GetInt());\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s }\n' % begin_space)
source_file.write(u'%s return false;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%sbool operator>>(const TDataDoc<float>& _rData, JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s _JsonValue.SetFloat(_rData.data);\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%sbool operator<<(std::string& _rData, const JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s if (!_JsonValue.IsString()) return false;\n' % begin_space)
source_file.write(u'%s _rData = _JsonValue.GetString();\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%sbool operator>>(const TDataDoc<std::string>& _rData, JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s if (!_rData.doc) return false;\n' % begin_space)
source_file.write(u'%s _JsonValue.SetString(_rData.data.c_str(), _rData.doc->GetAllocator());\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%stemplate<typename TData>\n' % begin_space)
source_file.write(u'%sbool operator<<(std::vector<TData>& _vDatas, const JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s if (!_JsonValue.IsArray()) return false;\n' % begin_space)
source_file.write(u'%s std::vector<TData> datas;\n' % begin_space)
source_file.write(u'%s const JSONCharConstArray& json_array = _JsonValue.GetArray();\n' % begin_space)
source_file.write(u'%s size_t len = json_array.Size();\n' % begin_space)
source_file.write(u'%s if (len == 0) return true;\n' % begin_space)
source_file.write(u'%s datas.resize(len);\n' % begin_space)
source_file.write(u'%s for (size_t i = 0; i < len; ++i)\n' % begin_space)
source_file.write(u'%s {\n' % begin_space)
source_file.write(u'%s if (datas[i] << json_array[static_cast<rapidjson::SizeType>(i)]) continue;\n' % begin_space)
source_file.write(u'%s return false;\n' % begin_space)
source_file.write(u'%s }\n' % begin_space)
source_file.write(u'%s _vDatas = datas;\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%stemplate<typename TData>\n' % begin_space)
source_file.write(u'%sbool operator>>(const TDataDoc<std::vector<TData>>& _rData, JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s if (_rData.data.empty() || !_rData.doc) return false;\n' % begin_space)
source_file.write(u'%s JSONCharValue& json_array = _JsonValue.SetArray();\n' % begin_space)
source_file.write(u'%s for (const TData& data : _rData.data)\n' % begin_space)
source_file.write(u'%s {\n' % begin_space)
source_file.write(u'%s JSONCharValue json_value;\n' % begin_space)
source_file.write(u'%s if (!(TDataDoc<TData>(data, _rData.doc) >> json_value)) return false;\n' % begin_space)
source_file.write(u'%s json_array.PushBack(json_value, _rData.doc->GetAllocator());\n' % begin_space)
source_file.write(u'%s }\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%stemplate<typename TData>\n' % begin_space)
source_file.write(u'%sbool operator<<(std::map<std::string, TData>& _mDatas, const JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s if (!_JsonValue.IsObject()) return false;\n' % begin_space)
source_file.write(u'%s std::map<std::string, TData> datas;\n' % begin_space)
source_file.write(u'%s const JSONCharConstObject& json_object = _JsonValue.GetObject();\n' % begin_space)
source_file.write(u'%s for (JSONCharConstObject::ConstMemberIterator cit = json_object.MemberBegin(); cit != json_object.MemberEnd(); ++cit)\n' % begin_space)
source_file.write(u'%s {\n' % begin_space)
source_file.write(u'%s TData data;\n' % begin_space)
source_file.write(u'%s if (!(data << cit->value)) return false;\n' % begin_space)
source_file.write(u'%s datas.insert(std::make_pair(cit->name.GetString(), data));\n' % begin_space)
source_file.write(u'%s }\n' % begin_space)
source_file.write(u'%s _mDatas = datas;\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
source_file.write(u'%stemplate<typename TData>\n' % begin_space)
source_file.write(u'%sbool operator>>(const TDataDoc<std::map<std::string, TData>>& _rData, JSONCharValue& _JsonValue)\n' % begin_space)
source_file.write(u'%s{\n' % begin_space)
source_file.write(u'%s if (_rData.data.empty() || !_rData.doc) return false;\n' % begin_space)
source_file.write(u'%s _JsonValue.SetObject();\n' % begin_space)
source_file.write(u'%s for (const std::pair<std::string, TData>& data : _rData.data)\n' % begin_space)
source_file.write(u'%s {\n' % begin_space)
source_file.write(u'%s JSONCharValue json_value;\n' % begin_space)
source_file.write(u'%s if (!(TDataDoc<TData>(data.second, _rData.doc) >> json_value)) return false;\n' % begin_space)
source_file.write(u'%s JSONCharValue json_key(data.first.c_str(), _rData.doc->GetAllocator());\n' % begin_space)
source_file.write(u'%s _JsonValue.AddMember(json_key, json_value, _rData.doc->GetAllocator());\n' % begin_space)
source_file.write(u'%s }\n' % begin_space)
source_file.write(u'%s return true;\n' % begin_space)
source_file.write(u'%s}\n' % begin_space)
source_file.write(u'\n')
for key in self.c11Types:
c11_type = self.c11Types[key]
if not isinstance(c11_type, C11TypeStruct):
continue
code_lines = c11_type.codeParserSource()
for code_line in code_lines:
if not code_line:
source_file.write(u'\n')
else:
source_file.write(u'%s%s\n' % (begin_space, code_line))
source_file.write(u'\n')
if nameSpace != None:
source_file.write(u'}\n')
return (0, u'')
def JSONSchemaToC11(argv):
parser = argparse.ArgumentParser(description=u'Generate c11 code by json schema.')
parser.add_argument(u'configFile', metavar=u'config_file', type=open, help=u'The configuration file')
args = parser.parse_args(argv)
if not args.configFile:
return (1, u'Can\'t find the configuration file')
os.environ['CD'] = os.path.dirname(os.path.abspath(args.configFile.name))
config = SafeConfigParser(os.environ)
config.readfp(args.configFile)
schema_directory = config.get(u'glTF', u'schema_directory')
code_file_name = config.get(u'glTF', u'code_file_name')
extensions_schema_directories = []
for extensions_schema_directory in config.get(u'glTF', u'extensions_schema_directories').split(u','):
extensions_schema_directories.append(extensions_schema_directory.replace(u'\n', u''))
major_version = config.get(u'glTF', u'major_version')
minor_version = config.get(u'glTF', u'minor_version')
patch_version = config.get(u'glTF', u'patch_version')
output_header_path = config.get(u'output', u'output_header_path')
output_source_path = config.get(u'output', u'output_source_path')
namespace = config.get(u'output', u'namespace')
if output_header_path != None and not os.path.exists(output_header_path):
return (1, u'Invalid output header path')
if output_source_path != None and not os.path.exists(output_source_path):
return (1, u'Invalid output source path')
if output_header_path is None:
output_header_path = u'./'
if output_source_path is None:
output_source_path = u'./'
c11_type_library = C11TypeLibrary()
c11_type_library.setVersion(major_version, minor_version, patch_version)
(error_code, error_message) = c11_type_library.addSchemaDirectory(schema_directory, config)
if error_code != 0:
return (error_code, error_message)
for extensions_schema_directory in extensions_schema_directories:
(error_code, error_message) = c11_type_library.addSchemaDirectory(extensions_schema_directory, config)
if error_code != 0:
print(error_code, error_message)
return (error_code, error_message)
(error_code, error_message) = c11_type_library.preprocess()
if error_code != 0:
return (error_code, error_message)
(error_code, error_message) = c11_type_library.generate(code_file_name, outputHeaderPath=output_header_path, outputSourcePath=output_source_path, nameSpace=namespace, config=config)
if error_code != 0:
return (error_code, error_message)
return (0, u'')
if __name__ == u'__main__':
(error_code, error_message) = JSONSchemaToC11(sys.argv[1:])
if error_code != 0:
logger.error(error_message)
sys.exit(error_code)
else:
logger.info(u'Success')
sys.exit(error_code)