├── .gitattributes ├── .gitignore ├── 1-word ├── README.md ├── answer.txt ├── check.cpp ├── function.h ├── input.txt ├── jsoncpp ├── json-forwards.h ├── json.h └── jsoncpp.cpp ├── main.cpp ├── makefile ├── merge.cpp ├── output.txt ├── pinyin ├── release ├── README.md ├── bin │ ├── 1-gram │ ├── 1-word │ ├── 2-gram │ ├── 2-word.zip │ ├── diff.exe │ ├── pinyin.exe │ └── pinyin_2.exe └── src │ ├── character │ ├── function.h │ └── main.cpp │ ├── diff.cpp │ └── word │ ├── function.h │ └── main.cpp ├── result.txt ├── result ├── 1-word.txt ├── 2-gram-v2.2.txt ├── 2-gram_v1.txt ├── 2-gram_v2.0.1.txt ├── 2-gram_v2.1.1.txt ├── 2-gram_v2.1.txt ├── 2-gram_v2.txt └── 2-word.txt ├── test ├── HSK.txt ├── answer.txt ├── input.txt └── make.py ├── tmp.txt ├── training.cpp └── trans.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | *.txt filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | sina_news_gbk/ 3 | log 4 | data/ 5 | 6 | 1-gram-tmp 7 | 2-gram-tmp 8 | 3-gram-tmp 9 | 4-gram-tmp 10 | 1-word-tmp 11 | 2-word 12 | -------------------------------------------------------------------------------- /1-word: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/1-word -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 拼音输入法编程作业实验报告 2 | 3 | ## 概况 4 | 5 | - 本文是一篇实验报告,主要介绍了这几天以来我对拼音输入法的设计和思考。 6 | - 算法实现基于字的二元模型,使用基于 sina news 的汉语语料库进行模型训练。 7 | - 对于拼音到汉字的转换,目前算法可以轻松实现 80% 以上的准确率。 8 | - Git 仓库地址:https://github.com/Konano/homework_input_method/tree/master/release 9 | 10 | ## 算法初步实现 11 | 12 | ### 一、对训练数据的处理 13 | 14 | 原语料库文件为 JSON 格式,一条 JSON 信息包含一条新闻。但每条新闻并不是单纯地由汉字构成,其内混杂了各种标点符号、数字、字母等非汉字字符,很难被直接利用,所以在训练前需要对原始语料进一步处理。 15 | 16 | 我将 JSON 的新闻内容提取出来后,将数字、字母和各种字符删去。其中的难点在于如何区别中文标点符号和汉字,在 ANSI 编码下中文标点符号和汉字都为双字节,最后在多次查验后确定了中文标点符号的编码范围,从而将其去除。 17 | 18 | 经过处理,便得到了可直接使用的句子片段。 19 | 20 | ### 二、训练 21 | 22 | 调用 `training.exe` 程序进行训练,主要是统计训练数据中单字出现频率和相邻二字所组成的二元组频率,分别保存到 `1-gram` 和 `2-gram` 文件内。拼音方面则是直接使用了提供的拼音汉字表。 23 | 24 | ### 三、实现解码算法 25 | 26 | 解法算法使用了 Viterbi 算法,该算法基于动态规划思想;并使用最大似然估计作为其概率。为了解决样本数量较少的问题,我还引入了 Laplace 平滑,缓解数据稀疏所带来的问题。 27 | 28 | ## 进一步改进 29 | 30 | ### 一、多音字处理 31 | 32 | 在对第一版程序(v1)进行测试后发现,转换结果中多音字的错误尤其多。这可能是由于训练的时候未对语料进行正确注音导致。 33 | 34 | 于是我调用了 python 下的 `pypinyin` 对语料进行注音。同时为了提升多音字注音正确性,我先调用了 python 下的「结巴分词」对语料进行分词再注音。训练的时候不再以单字作为基本单位,而是以单字单音作为基本单位,这样便将多音字分成多个单体,从而避免多音字内生僻读音的概率受常用读音的影响。 35 | 36 | ### 二、句首句尾概率 37 | 38 | 训练的时候进一步统计了每个字在句首和句尾的频数。假如给句首和句尾多定义一个特殊字符的话,出现在句首和句尾的情况也可以看成是一种二元关系。解码的时候充分利用此信息,能使得转换后的句子开头和结尾不会太突兀。 39 | 40 | ### 三、增加训练集 41 | 42 | 由于训练集多为新闻,在转换非新闻的句子(例如日常用语)的时候准确率就十分一般。所以我搜集了另外一些日常用语作为训练集的补充。 43 | 44 | ### 四、基于字的三元模型 45 | 46 | 尝试更高阶的 HMM 模型。训练的时候增加对相邻三字所构成的三元组的频数统计。难点在于不同三元组的数量过多,很难在程序内全部存下。我采取的解决方案是,先统计单个子训练集内出现的三元组信息,并有序输出到外部文件内;再对多个外部文件进行合并,取频数前 5,000,000 的三元组并储存。解码的时候以相邻二字为状态,并使用 Viterbi 算法解码。 47 | 48 | ### 五、基于词的一、二元模型 49 | 50 | 基于处理语料时的分词,我初步实现了基于词的一、二元模型的算法。由于词与词的二元关系实在过于庞大,在训练时采用了和处理字的三元关系一样「先单个再合并」的做法。解码方面则依旧使用 Viterbi 算法。 51 | 52 | ### 六、平滑算法 53 | 54 | 在处理字三元组和词二元组的时候,数据稀疏性的问题越发突出,于是尝试使用 Good-Turing 估计和 Katz 回退法取代最大似然估计来计算其出现概率。 55 | 56 | ## 实验效果 57 | 58 | 由于作业附件并没有提供测试数据,于是我手动从最近的新闻中摘录了一些新闻片段组成了测试集,单字个数 4880,句子总数 122。各版本测试结果如下: 59 | 60 | | | 准确率 | 61 | | --------------------------- | -------- | 62 | | 1.字二元模型 | 82.541% | 63 | | 2.字二元模型 + 一 | 84.8566% | 64 | | 3.字二元模型 + 一 + 二 | 84.9795% | 65 | | 4.字二元模型 + 一 + 三 | 84.7336% | 66 | | 5.字二元模型 + 一 + 二 + 三 | 84.6721% | 67 | | 6.字三元模型 + 一 + 二 | 74.629% | 68 | | 7.词一元模型 + 一 + 二 | 61.6598% | 69 | | 8.词二元模型 + 一 + 二 | 86.168% | 70 | | 9.词二元模型 + 一 + 二 + 六 | 72.9158% | 71 | 72 | 从测试结果能够得到的信息有: 73 | 74 | - 对于多音字的处理可以看出是有效果的,准确率有所提高。 75 | - 第 2 个和第 4 个的比较中可以看出新增和测试集(多为新闻)交集较小的训练集(多为日常用语)会降低准确率。当然实验结果两个版本准确率只相差了 0.1%,也不排除是数据正常误差导致。 76 | - 字三元模型的准确率反而比最基本的字二元模型准确率要低。个人认为有三点原因:一是数据稀疏性;二是数据量过大无法全部储存;三是可能程序内三元 Viterbi 算法实现有误。 77 | - 尝试给字二元和词二元模型更换平滑算法,换成 Katz 回退法,但是准确率反而下降了近 10%。尚不清楚是什么原因导致的。 78 | 79 | ## 总结 & ToDo 80 | 81 | - 训练语料对于算法的影响十分明显。若训练语料和测试集是不同情景下的句子,则算法准确率便会大打折扣。今后可考虑用与测试集同类的训练语料进行训练。 82 | - 对于训练语料的处理同样重要。原算法对语料库的处理方法实现起来简单粗暴。但一个完整的句子在这种分割下也变得破碎不堪,并没有很好利用标点符号两端字符连接的信息等。 83 | - 若考虑最简单的储存方式,字二元模型的数据库大小在未压缩的情况下已经有 33MB 左右,所以可在数据库压缩方面做进一步的改进。对于字多元模型和词多元模型可采取舍弃频数较少的多元关系信息来缩小数据库。 84 | - 今后可以尝试用各种平滑算法解决数据稀疏问题。 85 | - 可以尝试完善基于字的三元模型的算法,和实现基于字的四元模型或基于词的三元模型的算法。 86 | - 解码算法方面还有许多问题需要思考,比如音节切分歧义、大规模解码算法的剪枝、更高阶的 N 元模型的解码算法等。 87 | -------------------------------------------------------------------------------- /answer.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eefdd7bebd57fe980f390285ccab5333362ca4911c26ab361fff2003676a57ed 3 | size 229778 4 | -------------------------------------------------------------------------------- /check.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/check.cpp -------------------------------------------------------------------------------- /function.h: -------------------------------------------------------------------------------- 1 | //#pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define MAXPINYIN 500 13 | #define MAXWORD 1500000 14 | 15 | #define Long(i, j) 1LL*i*MAXWORD+j 16 | 17 | using namespace std; 18 | 19 | int PinyinTotal = 0, WordTotal = 0; 20 | 21 | string Pinyin[MAXPINYIN]; 22 | map Pinyin_map; 23 | 24 | string Word[MAXWORD]; 25 | vector Word_pinyin[MAXWORD]; 26 | map,int> Word_map; 27 | 28 | inline int Pinyin_ID(string py) 29 | { 30 | if (py=="n") py="en"; 31 | if (py=="lve") py="lue"; 32 | if (py=="nve") py="nue"; 33 | 34 | if (Pinyin_map[py] == 0) 35 | return Pinyin[Pinyin_map[py] = ++PinyinTotal] = py, PinyinTotal; 36 | return Pinyin_map[py]; 37 | } 38 | 39 | inline int PinyinHash(int id) 40 | { 41 | int tmp = (int)Word_pinyin[id].size(), num = 0; 42 | for(int i = 0; i < tmp; i++) 43 | num = (2333LL * num + Word_pinyin[id][i]) % 1000000007; 44 | return num; 45 | } 46 | 47 | inline int PinyinHash(string py) 48 | { 49 | int L = py.length(); 50 | int num = 0; 51 | int S = 0, E = py.find('-', S); 52 | 53 | while (E != -1) 54 | { 55 | num = (2333LL * num + Pinyin_ID(py.substr(S, E-S))) % 1000000007; 56 | S = E + 1; 57 | E = py.find('-', S); 58 | } 59 | num = (2333LL * num + Pinyin_ID(py.substr(S, L-S))) % 1000000007; 60 | return num; 61 | } 62 | 63 | inline string JoinPinyin(int id) 64 | { 65 | string tmp = Pinyin[Word_pinyin[id][0]]; 66 | int tot = (int)Word_pinyin[id].size(); 67 | for(int i = 1; i < tot; i++) 68 | tmp += '-' + Pinyin[Word_pinyin[id][i]]; 69 | return tmp; 70 | } 71 | 72 | inline void SplitPinyin(int id, string py) 73 | { 74 | int L = py.length(); 75 | int S = 0, E = py.find('-', S); 76 | 77 | while (E != -1) 78 | { 79 | Word_pinyin[id].push_back(Pinyin_ID(py.substr(S, E-S))); 80 | S = E + 1; 81 | E = py.find('-', S); 82 | } 83 | 84 | Word_pinyin[id].push_back(Pinyin_ID(py.substr(S, L-S))); 85 | } 86 | 87 | inline int Word_ID(string wd, string py) 88 | { 89 | int H = PinyinHash(py); 90 | if (Word_map.count(make_pair(wd, H))) 91 | return Word_map[make_pair(wd, H)]; 92 | 93 | WordTotal ++; 94 | Word[WordTotal] = wd; 95 | Word_map[make_pair(wd, H)] = WordTotal; 96 | SplitPinyin(WordTotal, py); 97 | 98 | return WordTotal; 99 | } 100 | 101 | map Times_2; 102 | int Times_1[MAXWORD]; 103 | 104 | int N[1000000]; 105 | 106 | inline void ReadData() 107 | { 108 | // ============================================ 1-word 109 | 110 | ifstream fin1("1-word"); 111 | 112 | char str[500], py[500]; 113 | 114 | while (fin1 >> str >> py) 115 | fin1 >> Times_1[Word_ID(str, py)]; 116 | 117 | // ============================================ 2-word 118 | 119 | ifstream fin2("2-word"); 120 | 121 | long long tmp; 122 | 123 | while (fin2 >> tmp) 124 | fin2 >> Times_2[tmp]; 125 | 126 | N[Times_2[tmp]]++; 127 | } 128 | 129 | /*inline int ChineseWord(const char ch, const char ch2) 130 | { 131 | if ((0xffffffa1 <= (int)ch && (int)ch <= 0xffffffa8) || ((int)ch == 0xffffffa9 && (int)ch2 != 0xffffff96)) 132 | return -1; 133 | if (ch & 0x80) 134 | return 1; 135 | return 0; 136 | } 137 | 138 | #include 139 | string Int_to_String(int n) 140 | { 141 | ostringstream stream; 142 | stream << n; 143 | return stream.str(); 144 | } 145 | 146 | inline string OutputWord(const int id) 147 | { 148 | //cout << "Word " << id << ": " << Word[id].first << Word[id].second << " " << Pinyin[Word_pinyin[id]] << endl; 149 | 150 | if (id == 0) return "??0"; 151 | 152 | string tmp = ""; int i = 0; 153 | while (Word_vec[Word[id]][i] != Word_pinyin[id]) i++; 154 | return tmp + Word[id].first + Word[id].second + Int_to_String(i); 155 | } 156 | 157 | inline void OutputWord2(const int id) 158 | { 159 | cout << "Word " << id << ": " << Word[id].first << Word[id].second << " " << Pinyin[Word_pinyin[id]] << endl; 160 | }*/ 161 | -------------------------------------------------------------------------------- /input.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:14013324b620ad69af4ee3044b14ddce94de86c292bda69b154fc7d3fe225cf6 3 | size 426186 4 | -------------------------------------------------------------------------------- /jsoncpp/json-forwards.h: -------------------------------------------------------------------------------- 1 | /// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). 2 | /// It is intented to be used with #include 3 | /// This header provides forward declaration for all JsonCpp types. 4 | 5 | // ////////////////////////////////////////////////////////////////////// 6 | // Beginning of content of file: LICENSE 7 | // ////////////////////////////////////////////////////////////////////// 8 | 9 | /* 10 | The JsonCpp library's source code, including accompanying documentation, 11 | tests and demonstration applications, are licensed under the following 12 | conditions... 13 | 14 | The author (Baptiste Lepilleur) explicitly disclaims copyright in all 15 | jurisdictions which recognize such a disclaimer. In such jurisdictions, 16 | this software is released into the Public Domain. 17 | 18 | In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 19 | 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is 20 | released under the terms of the MIT License (see below). 21 | 22 | In jurisdictions which recognize Public Domain property, the user of this 23 | software may choose to accept it either as 1) Public Domain, 2) under the 24 | conditions of the MIT License (see below), or 3) under the terms of dual 25 | Public Domain/MIT License conditions described here, as they choose. 26 | 27 | The MIT License is about as close to Public Domain as a license can get, and is 28 | described in clear, concise terms at: 29 | 30 | http://en.wikipedia.org/wiki/MIT_License 31 | 32 | The full text of the MIT License follows: 33 | 34 | ======================================================================== 35 | Copyright (c) 2007-2010 Baptiste Lepilleur 36 | 37 | Permission is hereby granted, free of charge, to any person 38 | obtaining a copy of this software and associated documentation 39 | files (the "Software"), to deal in the Software without 40 | restriction, including without limitation the rights to use, copy, 41 | modify, merge, publish, distribute, sublicense, and/or sell copies 42 | of the Software, and to permit persons to whom the Software is 43 | furnished to do so, subject to the following conditions: 44 | 45 | The above copyright notice and this permission notice shall be 46 | included in all copies or substantial portions of the Software. 47 | 48 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 49 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 50 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 51 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 52 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 53 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 54 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 55 | SOFTWARE. 56 | ======================================================================== 57 | (END LICENSE TEXT) 58 | 59 | The MIT license is compatible with both the GPL and commercial 60 | software, affording one all of the rights of Public Domain with the 61 | minor nuisance of being required to keep the above copyright notice 62 | and license text in the source code. Note also that by accepting the 63 | Public Domain "license" you can re-license your copy using whatever 64 | license you like. 65 | 66 | */ 67 | 68 | // ////////////////////////////////////////////////////////////////////// 69 | // End of content of file: LICENSE 70 | // ////////////////////////////////////////////////////////////////////// 71 | 72 | 73 | 74 | 75 | 76 | #ifndef JSON_FORWARD_AMALGATED_H_INCLUDED 77 | # define JSON_FORWARD_AMALGATED_H_INCLUDED 78 | /// If defined, indicates that the source file is amalgated 79 | /// to prevent private header inclusion. 80 | #define JSON_IS_AMALGAMATION 81 | 82 | // ////////////////////////////////////////////////////////////////////// 83 | // Beginning of content of file: include/json/config.h 84 | // ////////////////////////////////////////////////////////////////////// 85 | 86 | // Copyright 2007-2010 Baptiste Lepilleur 87 | // Distributed under MIT license, or public domain if desired and 88 | // recognized in your jurisdiction. 89 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 90 | 91 | #ifndef JSON_CONFIG_H_INCLUDED 92 | #define JSON_CONFIG_H_INCLUDED 93 | 94 | /// If defined, indicates that json library is embedded in CppTL library. 95 | //# define JSON_IN_CPPTL 1 96 | 97 | /// If defined, indicates that json may leverage CppTL library 98 | //# define JSON_USE_CPPTL 1 99 | /// If defined, indicates that cpptl vector based map should be used instead of 100 | /// std::map 101 | /// as Value container. 102 | //# define JSON_USE_CPPTL_SMALLMAP 1 103 | /// If defined, indicates that Json specific container should be used 104 | /// (hash table & simple deque container with customizable allocator). 105 | /// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 106 | //# define JSON_VALUE_USE_INTERNAL_MAP 1 107 | /// Force usage of standard new/malloc based allocator instead of memory pool 108 | /// based allocator. 109 | /// The memory pools allocator used optimization (initializing Value and 110 | /// ValueInternalLink 111 | /// as if it was a POD) that may cause some validation tool to report errors. 112 | /// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. 113 | //# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 114 | 115 | // If non-zero, the library uses exceptions to report bad input instead of C 116 | // assertion macros. The default is to use exceptions. 117 | #ifndef JSON_USE_EXCEPTION 118 | #define JSON_USE_EXCEPTION 1 119 | #endif 120 | 121 | /// If defined, indicates that the source file is amalgated 122 | /// to prevent private header inclusion. 123 | /// Remarks: it is automatically defined in the generated amalgated header. 124 | // #define JSON_IS_AMALGAMATION 125 | 126 | #ifdef JSON_IN_CPPTL 127 | #include 128 | #ifndef JSON_USE_CPPTL 129 | #define JSON_USE_CPPTL 1 130 | #endif 131 | #endif 132 | 133 | #ifdef JSON_IN_CPPTL 134 | #define JSON_API CPPTL_API 135 | #elif defined(JSON_DLL_BUILD) 136 | #if defined(_MSC_VER) 137 | #define JSON_API __declspec(dllexport) 138 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 139 | #endif // if defined(_MSC_VER) 140 | #elif defined(JSON_DLL) 141 | #if defined(_MSC_VER) 142 | #define JSON_API __declspec(dllimport) 143 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 144 | #endif // if defined(_MSC_VER) 145 | #endif // ifdef JSON_IN_CPPTL 146 | #if !defined(JSON_API) 147 | #define JSON_API 148 | #endif 149 | 150 | // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for 151 | // integer 152 | // Storages, and 64 bits integer support is disabled. 153 | // #define JSON_NO_INT64 1 154 | 155 | #if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 156 | // Microsoft Visual Studio 6 only support conversion from __int64 to double 157 | // (no conversion from unsigned __int64). 158 | #define JSON_USE_INT64_DOUBLE_CONVERSION 1 159 | // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' 160 | // characters in the debug information) 161 | // All projects I've ever seen with VS6 were using this globally (not bothering 162 | // with pragma push/pop). 163 | #pragma warning(disable : 4786) 164 | #endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 165 | 166 | #if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 167 | /// Indicates that the following function is deprecated. 168 | #define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) 169 | #endif 170 | 171 | #if !defined(JSONCPP_DEPRECATED) 172 | #define JSONCPP_DEPRECATED(message) 173 | #endif // if !defined(JSONCPP_DEPRECATED) 174 | 175 | namespace Json { 176 | typedef int Int; 177 | typedef unsigned int UInt; 178 | #if defined(JSON_NO_INT64) 179 | typedef int LargestInt; 180 | typedef unsigned int LargestUInt; 181 | #undef JSON_HAS_INT64 182 | #else // if defined(JSON_NO_INT64) 183 | // For Microsoft Visual use specific types as long long is not supported 184 | #if defined(_MSC_VER) // Microsoft Visual Studio 185 | typedef __int64 Int64; 186 | typedef unsigned __int64 UInt64; 187 | #else // if defined(_MSC_VER) // Other platforms, use long long 188 | typedef long long int Int64; 189 | typedef unsigned long long int UInt64; 190 | #endif // if defined(_MSC_VER) 191 | typedef Int64 LargestInt; 192 | typedef UInt64 LargestUInt; 193 | #define JSON_HAS_INT64 194 | #endif // if defined(JSON_NO_INT64) 195 | } // end namespace Json 196 | 197 | #endif // JSON_CONFIG_H_INCLUDED 198 | 199 | // ////////////////////////////////////////////////////////////////////// 200 | // End of content of file: include/json/config.h 201 | // ////////////////////////////////////////////////////////////////////// 202 | 203 | 204 | 205 | 206 | 207 | 208 | // ////////////////////////////////////////////////////////////////////// 209 | // Beginning of content of file: include/json/forwards.h 210 | // ////////////////////////////////////////////////////////////////////// 211 | 212 | // Copyright 2007-2010 Baptiste Lepilleur 213 | // Distributed under MIT license, or public domain if desired and 214 | // recognized in your jurisdiction. 215 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 216 | 217 | #ifndef JSON_FORWARDS_H_INCLUDED 218 | #define JSON_FORWARDS_H_INCLUDED 219 | 220 | #if !defined(JSON_IS_AMALGAMATION) 221 | #include "config.h" 222 | #endif // if !defined(JSON_IS_AMALGAMATION) 223 | 224 | namespace Json { 225 | 226 | // writer.h 227 | class FastWriter; 228 | class StyledWriter; 229 | 230 | // reader.h 231 | class Reader; 232 | 233 | // features.h 234 | class Features; 235 | 236 | // value.h 237 | typedef unsigned int ArrayIndex; 238 | class StaticString; 239 | class Path; 240 | class PathArgument; 241 | class Value; 242 | class ValueIteratorBase; 243 | class ValueIterator; 244 | class ValueConstIterator; 245 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 246 | class ValueMapAllocator; 247 | class ValueInternalLink; 248 | class ValueInternalArray; 249 | class ValueInternalMap; 250 | #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP 251 | 252 | } // namespace Json 253 | 254 | #endif // JSON_FORWARDS_H_INCLUDED 255 | 256 | // ////////////////////////////////////////////////////////////////////// 257 | // End of content of file: include/json/forwards.h 258 | // ////////////////////////////////////////////////////////////////////// 259 | 260 | 261 | 262 | 263 | 264 | #endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED 265 | -------------------------------------------------------------------------------- /jsoncpp/json.h: -------------------------------------------------------------------------------- 1 | /// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). 2 | /// It is intented to be used with #include 3 | 4 | // ////////////////////////////////////////////////////////////////////// 5 | // Beginning of content of file: LICENSE 6 | // ////////////////////////////////////////////////////////////////////// 7 | 8 | /* 9 | The JsonCpp library's source code, including accompanying documentation, 10 | tests and demonstration applications, are licensed under the following 11 | conditions... 12 | 13 | The author (Baptiste Lepilleur) explicitly disclaims copyright in all 14 | jurisdictions which recognize such a disclaimer. In such jurisdictions, 15 | this software is released into the Public Domain. 16 | 17 | In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 18 | 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is 19 | released under the terms of the MIT License (see below). 20 | 21 | In jurisdictions which recognize Public Domain property, the user of this 22 | software may choose to accept it either as 1) Public Domain, 2) under the 23 | conditions of the MIT License (see below), or 3) under the terms of dual 24 | Public Domain/MIT License conditions described here, as they choose. 25 | 26 | The MIT License is about as close to Public Domain as a license can get, and is 27 | described in clear, concise terms at: 28 | 29 | http://en.wikipedia.org/wiki/MIT_License 30 | 31 | The full text of the MIT License follows: 32 | 33 | ======================================================================== 34 | Copyright (c) 2007-2010 Baptiste Lepilleur 35 | 36 | Permission is hereby granted, free of charge, to any person 37 | obtaining a copy of this software and associated documentation 38 | files (the "Software"), to deal in the Software without 39 | restriction, including without limitation the rights to use, copy, 40 | modify, merge, publish, distribute, sublicense, and/or sell copies 41 | of the Software, and to permit persons to whom the Software is 42 | furnished to do so, subject to the following conditions: 43 | 44 | The above copyright notice and this permission notice shall be 45 | included in all copies or substantial portions of the Software. 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 48 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 50 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 51 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 52 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 53 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 54 | SOFTWARE. 55 | ======================================================================== 56 | (END LICENSE TEXT) 57 | 58 | The MIT license is compatible with both the GPL and commercial 59 | software, affording one all of the rights of Public Domain with the 60 | minor nuisance of being required to keep the above copyright notice 61 | and license text in the source code. Note also that by accepting the 62 | Public Domain "license" you can re-license your copy using whatever 63 | license you like. 64 | 65 | */ 66 | 67 | // ////////////////////////////////////////////////////////////////////// 68 | // End of content of file: LICENSE 69 | // ////////////////////////////////////////////////////////////////////// 70 | 71 | 72 | 73 | 74 | 75 | #ifndef JSON_AMALGATED_H_INCLUDED 76 | # define JSON_AMALGATED_H_INCLUDED 77 | /// If defined, indicates that the source file is amalgated 78 | /// to prevent private header inclusion. 79 | #define JSON_IS_AMALGAMATION 80 | 81 | // ////////////////////////////////////////////////////////////////////// 82 | // Beginning of content of file: include/json/version.h 83 | // ////////////////////////////////////////////////////////////////////// 84 | 85 | // DO NOT EDIT. This file is generated by CMake from "version" 86 | // and "version.h.in" files. 87 | // Run CMake configure step to update it. 88 | #ifndef JSON_VERSION_H_INCLUDED 89 | # define JSON_VERSION_H_INCLUDED 90 | 91 | # define JSONCPP_VERSION_STRING "0.7.0" 92 | # define JSONCPP_VERSION_MAJOR 0 93 | # define JSONCPP_VERSION_MINOR 7 94 | # define JSONCPP_VERSION_PATCH 0 95 | # define JSONCPP_VERSION_QUALIFIER 96 | # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) 97 | 98 | #endif // JSON_VERSION_H_INCLUDED 99 | 100 | // ////////////////////////////////////////////////////////////////////// 101 | // End of content of file: include/json/version.h 102 | // ////////////////////////////////////////////////////////////////////// 103 | 104 | 105 | 106 | 107 | 108 | 109 | // ////////////////////////////////////////////////////////////////////// 110 | // Beginning of content of file: include/json/config.h 111 | // ////////////////////////////////////////////////////////////////////// 112 | 113 | // Copyright 2007-2010 Baptiste Lepilleur 114 | // Distributed under MIT license, or public domain if desired and 115 | // recognized in your jurisdiction. 116 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 117 | 118 | #ifndef JSON_CONFIG_H_INCLUDED 119 | #define JSON_CONFIG_H_INCLUDED 120 | 121 | /// If defined, indicates that json library is embedded in CppTL library. 122 | //# define JSON_IN_CPPTL 1 123 | 124 | /// If defined, indicates that json may leverage CppTL library 125 | //# define JSON_USE_CPPTL 1 126 | /// If defined, indicates that cpptl vector based map should be used instead of 127 | /// std::map 128 | /// as Value container. 129 | //# define JSON_USE_CPPTL_SMALLMAP 1 130 | /// If defined, indicates that Json specific container should be used 131 | /// (hash table & simple deque container with customizable allocator). 132 | /// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 133 | //# define JSON_VALUE_USE_INTERNAL_MAP 1 134 | /// Force usage of standard new/malloc based allocator instead of memory pool 135 | /// based allocator. 136 | /// The memory pools allocator used optimization (initializing Value and 137 | /// ValueInternalLink 138 | /// as if it was a POD) that may cause some validation tool to report errors. 139 | /// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. 140 | //# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 141 | 142 | // If non-zero, the library uses exceptions to report bad input instead of C 143 | // assertion macros. The default is to use exceptions. 144 | #ifndef JSON_USE_EXCEPTION 145 | #define JSON_USE_EXCEPTION 1 146 | #endif 147 | 148 | /// If defined, indicates that the source file is amalgated 149 | /// to prevent private header inclusion. 150 | /// Remarks: it is automatically defined in the generated amalgated header. 151 | // #define JSON_IS_AMALGAMATION 152 | 153 | #ifdef JSON_IN_CPPTL 154 | #include 155 | #ifndef JSON_USE_CPPTL 156 | #define JSON_USE_CPPTL 1 157 | #endif 158 | #endif 159 | 160 | #ifdef JSON_IN_CPPTL 161 | #define JSON_API CPPTL_API 162 | #elif defined(JSON_DLL_BUILD) 163 | #if defined(_MSC_VER) 164 | #define JSON_API __declspec(dllexport) 165 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 166 | #endif // if defined(_MSC_VER) 167 | #elif defined(JSON_DLL) 168 | #if defined(_MSC_VER) 169 | #define JSON_API __declspec(dllimport) 170 | #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING 171 | #endif // if defined(_MSC_VER) 172 | #endif // ifdef JSON_IN_CPPTL 173 | #if !defined(JSON_API) 174 | #define JSON_API 175 | #endif 176 | 177 | // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for 178 | // integer 179 | // Storages, and 64 bits integer support is disabled. 180 | // #define JSON_NO_INT64 1 181 | 182 | #if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 183 | // Microsoft Visual Studio 6 only support conversion from __int64 to double 184 | // (no conversion from unsigned __int64). 185 | #define JSON_USE_INT64_DOUBLE_CONVERSION 1 186 | // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' 187 | // characters in the debug information) 188 | // All projects I've ever seen with VS6 were using this globally (not bothering 189 | // with pragma push/pop). 190 | #pragma warning(disable : 4786) 191 | #endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 192 | 193 | #if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 194 | /// Indicates that the following function is deprecated. 195 | #define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) 196 | #endif 197 | 198 | #if !defined(JSONCPP_DEPRECATED) 199 | #define JSONCPP_DEPRECATED(message) 200 | #endif // if !defined(JSONCPP_DEPRECATED) 201 | 202 | namespace Json { 203 | typedef int Int; 204 | typedef unsigned int UInt; 205 | #if defined(JSON_NO_INT64) 206 | typedef int LargestInt; 207 | typedef unsigned int LargestUInt; 208 | #undef JSON_HAS_INT64 209 | #else // if defined(JSON_NO_INT64) 210 | // For Microsoft Visual use specific types as long long is not supported 211 | #if defined(_MSC_VER) // Microsoft Visual Studio 212 | typedef __int64 Int64; 213 | typedef unsigned __int64 UInt64; 214 | #else // if defined(_MSC_VER) // Other platforms, use long long 215 | typedef long long int Int64; 216 | typedef unsigned long long int UInt64; 217 | #endif // if defined(_MSC_VER) 218 | typedef Int64 LargestInt; 219 | typedef UInt64 LargestUInt; 220 | #define JSON_HAS_INT64 221 | #endif // if defined(JSON_NO_INT64) 222 | } // end namespace Json 223 | 224 | #endif // JSON_CONFIG_H_INCLUDED 225 | 226 | // ////////////////////////////////////////////////////////////////////// 227 | // End of content of file: include/json/config.h 228 | // ////////////////////////////////////////////////////////////////////// 229 | 230 | 231 | 232 | 233 | 234 | 235 | // ////////////////////////////////////////////////////////////////////// 236 | // Beginning of content of file: include/json/forwards.h 237 | // ////////////////////////////////////////////////////////////////////// 238 | 239 | // Copyright 2007-2010 Baptiste Lepilleur 240 | // Distributed under MIT license, or public domain if desired and 241 | // recognized in your jurisdiction. 242 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 243 | 244 | #ifndef JSON_FORWARDS_H_INCLUDED 245 | #define JSON_FORWARDS_H_INCLUDED 246 | 247 | #if !defined(JSON_IS_AMALGAMATION) 248 | #include "config.h" 249 | #endif // if !defined(JSON_IS_AMALGAMATION) 250 | 251 | namespace Json { 252 | 253 | // writer.h 254 | class FastWriter; 255 | class StyledWriter; 256 | 257 | // reader.h 258 | class Reader; 259 | 260 | // features.h 261 | class Features; 262 | 263 | // value.h 264 | typedef unsigned int ArrayIndex; 265 | class StaticString; 266 | class Path; 267 | class PathArgument; 268 | class Value; 269 | class ValueIteratorBase; 270 | class ValueIterator; 271 | class ValueConstIterator; 272 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 273 | class ValueMapAllocator; 274 | class ValueInternalLink; 275 | class ValueInternalArray; 276 | class ValueInternalMap; 277 | #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP 278 | 279 | } // namespace Json 280 | 281 | #endif // JSON_FORWARDS_H_INCLUDED 282 | 283 | // ////////////////////////////////////////////////////////////////////// 284 | // End of content of file: include/json/forwards.h 285 | // ////////////////////////////////////////////////////////////////////// 286 | 287 | 288 | 289 | 290 | 291 | 292 | // ////////////////////////////////////////////////////////////////////// 293 | // Beginning of content of file: include/json/features.h 294 | // ////////////////////////////////////////////////////////////////////// 295 | 296 | // Copyright 2007-2010 Baptiste Lepilleur 297 | // Distributed under MIT license, or public domain if desired and 298 | // recognized in your jurisdiction. 299 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 300 | 301 | #ifndef CPPTL_JSON_FEATURES_H_INCLUDED 302 | #define CPPTL_JSON_FEATURES_H_INCLUDED 303 | 304 | #if !defined(JSON_IS_AMALGAMATION) 305 | #include "forwards.h" 306 | #endif // if !defined(JSON_IS_AMALGAMATION) 307 | 308 | namespace Json { 309 | 310 | /** \brief Configuration passed to reader and writer. 311 | * This configuration object can be used to force the Reader or Writer 312 | * to behave in a standard conforming way. 313 | */ 314 | class JSON_API Features { 315 | public: 316 | /** \brief A configuration that allows all features and assumes all strings 317 | * are UTF-8. 318 | * - C & C++ comments are allowed 319 | * - Root object can be any JSON value 320 | * - Assumes Value strings are encoded in UTF-8 321 | */ 322 | static Features all(); 323 | 324 | /** \brief A configuration that is strictly compatible with the JSON 325 | * specification. 326 | * - Comments are forbidden. 327 | * - Root object must be either an array or an object value. 328 | * - Assumes Value strings are encoded in UTF-8 329 | */ 330 | static Features strictMode(); 331 | 332 | /** \brief Initialize the configuration like JsonConfig::allFeatures; 333 | */ 334 | Features(); 335 | 336 | /// \c true if comments are allowed. Default: \c true. 337 | bool allowComments_; 338 | 339 | /// \c true if root must be either an array or an object value. Default: \c 340 | /// false. 341 | bool strictRoot_; 342 | 343 | /// \c true if dropped null placeholders are allowed. Default: \c false. 344 | bool allowDroppedNullPlaceholders_; 345 | 346 | /// \c true if numeric object key are allowed. Default: \c false. 347 | bool allowNumericKeys_; 348 | }; 349 | 350 | } // namespace Json 351 | 352 | #endif // CPPTL_JSON_FEATURES_H_INCLUDED 353 | 354 | // ////////////////////////////////////////////////////////////////////// 355 | // End of content of file: include/json/features.h 356 | // ////////////////////////////////////////////////////////////////////// 357 | 358 | 359 | 360 | 361 | 362 | 363 | // ////////////////////////////////////////////////////////////////////// 364 | // Beginning of content of file: include/json/value.h 365 | // ////////////////////////////////////////////////////////////////////// 366 | 367 | // Copyright 2007-2010 Baptiste Lepilleur 368 | // Distributed under MIT license, or public domain if desired and 369 | // recognized in your jurisdiction. 370 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 371 | 372 | #ifndef CPPTL_JSON_H_INCLUDED 373 | #define CPPTL_JSON_H_INCLUDED 374 | 375 | #if !defined(JSON_IS_AMALGAMATION) 376 | #include "forwards.h" 377 | #endif // if !defined(JSON_IS_AMALGAMATION) 378 | #include 379 | #include 380 | 381 | #ifndef JSON_USE_CPPTL_SMALLMAP 382 | #include 383 | #else 384 | #include 385 | #endif 386 | #ifdef JSON_USE_CPPTL 387 | #include 388 | #endif 389 | 390 | // Disable warning C4251: : needs to have dll-interface to 391 | // be used by... 392 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 393 | #pragma warning(push) 394 | #pragma warning(disable : 4251) 395 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 396 | 397 | /** \brief JSON (JavaScript Object Notation). 398 | */ 399 | namespace Json { 400 | 401 | /** \brief Type of the value held by a Value object. 402 | */ 403 | enum ValueType { 404 | nullValue = 0, ///< 'null' value 405 | intValue, ///< signed integer value 406 | uintValue, ///< unsigned integer value 407 | realValue, ///< double value 408 | stringValue, ///< UTF-8 string value 409 | booleanValue, ///< bool value 410 | arrayValue, ///< array value (ordered list) 411 | objectValue ///< object value (collection of name/value pairs). 412 | }; 413 | 414 | enum CommentPlacement { 415 | commentBefore = 0, ///< a comment placed on the line before a value 416 | commentAfterOnSameLine, ///< a comment just after a value on the same line 417 | commentAfter, ///< a comment on the line after a value (only make sense for 418 | /// root value) 419 | numberOfCommentPlacement 420 | }; 421 | 422 | //# ifdef JSON_USE_CPPTL 423 | // typedef CppTL::AnyEnumerator EnumMemberNames; 424 | // typedef CppTL::AnyEnumerator EnumValues; 425 | //# endif 426 | 427 | /** \brief Lightweight wrapper to tag static string. 428 | * 429 | * Value constructor and objectValue member assignement takes advantage of the 430 | * StaticString and avoid the cost of string duplication when storing the 431 | * string or the member name. 432 | * 433 | * Example of usage: 434 | * \code 435 | * Json::Value aValue( StaticString("some text") ); 436 | * Json::Value object; 437 | * static const StaticString code("code"); 438 | * object[code] = 1234; 439 | * \endcode 440 | */ 441 | class JSON_API StaticString { 442 | public: 443 | explicit StaticString(const char* czstring) : str_(czstring) {} 444 | 445 | operator const char*() const { return str_; } 446 | 447 | const char* c_str() const { return str_; } 448 | 449 | private: 450 | const char* str_; 451 | }; 452 | 453 | /** \brief Represents a JSON value. 454 | * 455 | * This class is a discriminated union wrapper that can represents a: 456 | * - signed integer [range: Value::minInt - Value::maxInt] 457 | * - unsigned integer (range: 0 - Value::maxUInt) 458 | * - double 459 | * - UTF-8 string 460 | * - boolean 461 | * - 'null' 462 | * - an ordered list of Value 463 | * - collection of name/value pairs (javascript object) 464 | * 465 | * The type of the held value is represented by a #ValueType and 466 | * can be obtained using type(). 467 | * 468 | * values of an #objectValue or #arrayValue can be accessed using operator[]() 469 | *methods. 470 | * Non const methods will automatically create the a #nullValue element 471 | * if it does not exist. 472 | * The sequence of an #arrayValue will be automatically resize and initialized 473 | * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. 474 | * 475 | * The get() methods can be used to obtanis default value in the case the 476 | *required element 477 | * does not exist. 478 | * 479 | * It is possible to iterate over the list of a #objectValue values using 480 | * the getMemberNames() method. 481 | */ 482 | class JSON_API Value { 483 | friend class ValueIteratorBase; 484 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 485 | friend class ValueInternalLink; 486 | friend class ValueInternalMap; 487 | #endif 488 | public: 489 | typedef std::vector Members; 490 | typedef ValueIterator iterator; 491 | typedef ValueConstIterator const_iterator; 492 | typedef Json::UInt UInt; 493 | typedef Json::Int Int; 494 | #if defined(JSON_HAS_INT64) 495 | typedef Json::UInt64 UInt64; 496 | typedef Json::Int64 Int64; 497 | #endif // defined(JSON_HAS_INT64) 498 | typedef Json::LargestInt LargestInt; 499 | typedef Json::LargestUInt LargestUInt; 500 | typedef Json::ArrayIndex ArrayIndex; 501 | 502 | static const Value& null; 503 | /// Minimum signed integer value that can be stored in a Json::Value. 504 | static const LargestInt minLargestInt; 505 | /// Maximum signed integer value that can be stored in a Json::Value. 506 | static const LargestInt maxLargestInt; 507 | /// Maximum unsigned integer value that can be stored in a Json::Value. 508 | static const LargestUInt maxLargestUInt; 509 | 510 | /// Minimum signed int value that can be stored in a Json::Value. 511 | static const Int minInt; 512 | /// Maximum signed int value that can be stored in a Json::Value. 513 | static const Int maxInt; 514 | /// Maximum unsigned int value that can be stored in a Json::Value. 515 | static const UInt maxUInt; 516 | 517 | #if defined(JSON_HAS_INT64) 518 | /// Minimum signed 64 bits int value that can be stored in a Json::Value. 519 | static const Int64 minInt64; 520 | /// Maximum signed 64 bits int value that can be stored in a Json::Value. 521 | static const Int64 maxInt64; 522 | /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. 523 | static const UInt64 maxUInt64; 524 | #endif // defined(JSON_HAS_INT64) 525 | 526 | private: 527 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 528 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 529 | class CZString { 530 | public: 531 | enum DuplicationPolicy { 532 | noDuplication = 0, 533 | duplicate, 534 | duplicateOnCopy 535 | }; 536 | CZString(ArrayIndex index); 537 | CZString(const char* cstr, DuplicationPolicy allocate); 538 | CZString(const CZString& other); 539 | ~CZString(); 540 | CZString& operator=(CZString other); 541 | bool operator<(const CZString& other) const; 542 | bool operator==(const CZString& other) const; 543 | ArrayIndex index() const; 544 | const char* c_str() const; 545 | bool isStaticString() const; 546 | 547 | private: 548 | void swap(CZString& other); 549 | const char* cstr_; 550 | ArrayIndex index_; 551 | }; 552 | 553 | public: 554 | #ifndef JSON_USE_CPPTL_SMALLMAP 555 | typedef std::map ObjectValues; 556 | #else 557 | typedef CppTL::SmallMap ObjectValues; 558 | #endif // ifndef JSON_USE_CPPTL_SMALLMAP 559 | #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP 560 | #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 561 | 562 | public: 563 | /** \brief Create a default Value of the given type. 564 | 565 | This is a very useful constructor. 566 | To create an empty array, pass arrayValue. 567 | To create an empty object, pass objectValue. 568 | Another Value can then be set to this one by assignment. 569 | This is useful since clear() and resize() will not alter types. 570 | 571 | Examples: 572 | \code 573 | Json::Value null_value; // null 574 | Json::Value arr_value(Json::arrayValue); // [] 575 | Json::Value obj_value(Json::objectValue); // {} 576 | \endcode 577 | */ 578 | Value(ValueType type = nullValue); 579 | Value(Int value); 580 | Value(UInt value); 581 | #if defined(JSON_HAS_INT64) 582 | Value(Int64 value); 583 | Value(UInt64 value); 584 | #endif // if defined(JSON_HAS_INT64) 585 | Value(double value); 586 | Value(const char* value); 587 | Value(const char* beginValue, const char* endValue); 588 | /** \brief Constructs a value from a static string. 589 | 590 | * Like other value string constructor but do not duplicate the string for 591 | * internal storage. The given string must remain alive after the call to this 592 | * constructor. 593 | * Example of usage: 594 | * \code 595 | * Json::Value aValue( StaticString("some text") ); 596 | * \endcode 597 | */ 598 | Value(const StaticString& value); 599 | Value(const std::string& value); 600 | #ifdef JSON_USE_CPPTL 601 | Value(const CppTL::ConstString& value); 602 | #endif 603 | Value(bool value); 604 | Value(const Value& other); 605 | ~Value(); 606 | 607 | Value& operator=(Value other); 608 | /// Swap values. 609 | /// \note Currently, comments are intentionally not swapped, for 610 | /// both logic and efficiency. 611 | void swap(Value& other); 612 | 613 | ValueType type() const; 614 | 615 | bool operator<(const Value& other) const; 616 | bool operator<=(const Value& other) const; 617 | bool operator>=(const Value& other) const; 618 | bool operator>(const Value& other) const; 619 | 620 | bool operator==(const Value& other) const; 621 | bool operator!=(const Value& other) const; 622 | 623 | int compare(const Value& other) const; 624 | 625 | const char* asCString() const; 626 | std::string asString() const; 627 | #ifdef JSON_USE_CPPTL 628 | CppTL::ConstString asConstString() const; 629 | #endif 630 | Int asInt() const; 631 | UInt asUInt() const; 632 | #if defined(JSON_HAS_INT64) 633 | Int64 asInt64() const; 634 | UInt64 asUInt64() const; 635 | #endif // if defined(JSON_HAS_INT64) 636 | LargestInt asLargestInt() const; 637 | LargestUInt asLargestUInt() const; 638 | float asFloat() const; 639 | double asDouble() const; 640 | bool asBool() const; 641 | 642 | bool isNull() const; 643 | bool isBool() const; 644 | bool isInt() const; 645 | bool isInt64() const; 646 | bool isUInt() const; 647 | bool isUInt64() const; 648 | bool isIntegral() const; 649 | bool isDouble() const; 650 | bool isNumeric() const; 651 | bool isString() const; 652 | bool isArray() const; 653 | bool isObject() const; 654 | 655 | bool isConvertibleTo(ValueType other) const; 656 | 657 | /// Number of values in array or object 658 | ArrayIndex size() const; 659 | 660 | /// \brief Return true if empty array, empty object, or null; 661 | /// otherwise, false. 662 | bool empty() const; 663 | 664 | /// Return isNull() 665 | bool operator!() const; 666 | 667 | /// Remove all object members and array elements. 668 | /// \pre type() is arrayValue, objectValue, or nullValue 669 | /// \post type() is unchanged 670 | void clear(); 671 | 672 | /// Resize the array to size elements. 673 | /// New elements are initialized to null. 674 | /// May only be called on nullValue or arrayValue. 675 | /// \pre type() is arrayValue or nullValue 676 | /// \post type() is arrayValue 677 | void resize(ArrayIndex size); 678 | 679 | /// Access an array element (zero based index ). 680 | /// If the array contains less than index element, then null value are 681 | /// inserted 682 | /// in the array so that its size is index+1. 683 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 684 | /// this from the operator[] which takes a string.) 685 | Value& operator[](ArrayIndex index); 686 | 687 | /// Access an array element (zero based index ). 688 | /// If the array contains less than index element, then null value are 689 | /// inserted 690 | /// in the array so that its size is index+1. 691 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 692 | /// this from the operator[] which takes a string.) 693 | Value& operator[](int index); 694 | 695 | /// Access an array element (zero based index ) 696 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 697 | /// this from the operator[] which takes a string.) 698 | const Value& operator[](ArrayIndex index) const; 699 | 700 | /// Access an array element (zero based index ) 701 | /// (You may need to say 'value[0u]' to get your compiler to distinguish 702 | /// this from the operator[] which takes a string.) 703 | const Value& operator[](int index) const; 704 | 705 | /// If the array contains at least index+1 elements, returns the element 706 | /// value, 707 | /// otherwise returns defaultValue. 708 | Value get(ArrayIndex index, const Value& defaultValue) const; 709 | /// Return true if index < size(). 710 | bool isValidIndex(ArrayIndex index) const; 711 | /// \brief Append value to array at the end. 712 | /// 713 | /// Equivalent to jsonvalue[jsonvalue.size()] = value; 714 | Value& append(const Value& value); 715 | 716 | /// Access an object value by name, create a null member if it does not exist. 717 | Value& operator[](const char* key); 718 | /// Access an object value by name, returns null if there is no member with 719 | /// that name. 720 | const Value& operator[](const char* key) const; 721 | /// Access an object value by name, create a null member if it does not exist. 722 | Value& operator[](const std::string& key); 723 | /// Access an object value by name, returns null if there is no member with 724 | /// that name. 725 | const Value& operator[](const std::string& key) const; 726 | /** \brief Access an object value by name, create a null member if it does not 727 | exist. 728 | 729 | * If the object as no entry for that name, then the member name used to store 730 | * the new entry is not duplicated. 731 | * Example of use: 732 | * \code 733 | * Json::Value object; 734 | * static const StaticString code("code"); 735 | * object[code] = 1234; 736 | * \endcode 737 | */ 738 | Value& operator[](const StaticString& key); 739 | #ifdef JSON_USE_CPPTL 740 | /// Access an object value by name, create a null member if it does not exist. 741 | Value& operator[](const CppTL::ConstString& key); 742 | /// Access an object value by name, returns null if there is no member with 743 | /// that name. 744 | const Value& operator[](const CppTL::ConstString& key) const; 745 | #endif 746 | /// Return the member named key if it exist, defaultValue otherwise. 747 | Value get(const char* key, const Value& defaultValue) const; 748 | /// Return the member named key if it exist, defaultValue otherwise. 749 | Value get(const std::string& key, const Value& defaultValue) const; 750 | #ifdef JSON_USE_CPPTL 751 | /// Return the member named key if it exist, defaultValue otherwise. 752 | Value get(const CppTL::ConstString& key, const Value& defaultValue) const; 753 | #endif 754 | /// \brief Remove and return the named member. 755 | /// 756 | /// Do nothing if it did not exist. 757 | /// \return the removed Value, or null. 758 | /// \pre type() is objectValue or nullValue 759 | /// \post type() is unchanged 760 | Value removeMember(const char* key); 761 | /// Same as removeMember(const char*) 762 | Value removeMember(const std::string& key); 763 | 764 | /// Return true if the object has a member named key. 765 | bool isMember(const char* key) const; 766 | /// Return true if the object has a member named key. 767 | bool isMember(const std::string& key) const; 768 | #ifdef JSON_USE_CPPTL 769 | /// Return true if the object has a member named key. 770 | bool isMember(const CppTL::ConstString& key) const; 771 | #endif 772 | 773 | /// \brief Return a list of the member names. 774 | /// 775 | /// If null, return an empty list. 776 | /// \pre type() is objectValue or nullValue 777 | /// \post if type() was nullValue, it remains nullValue 778 | Members getMemberNames() const; 779 | 780 | //# ifdef JSON_USE_CPPTL 781 | // EnumMemberNames enumMemberNames() const; 782 | // EnumValues enumValues() const; 783 | //# endif 784 | 785 | /// Comments must be //... or /* ... */ 786 | void setComment(const char* comment, CommentPlacement placement); 787 | /// Comments must be //... or /* ... */ 788 | void setComment(const std::string& comment, CommentPlacement placement); 789 | bool hasComment(CommentPlacement placement) const; 790 | /// Include delimiters and embedded newlines. 791 | std::string getComment(CommentPlacement placement) const; 792 | 793 | std::string toStyledString() const; 794 | 795 | const_iterator begin() const; 796 | const_iterator end() const; 797 | 798 | iterator begin(); 799 | iterator end(); 800 | 801 | // Accessors for the [start, limit) range of bytes within the JSON text from 802 | // which this value was parsed, if any. 803 | void setOffsetStart(size_t start); 804 | void setOffsetLimit(size_t limit); 805 | size_t getOffsetStart() const; 806 | size_t getOffsetLimit() const; 807 | 808 | private: 809 | Value& resolveReference(const char* key, bool isStatic); 810 | 811 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 812 | inline bool isItemAvailable() const { return itemIsUsed_ == 0; } 813 | 814 | inline void setItemUsed(bool isUsed = true) { itemIsUsed_ = isUsed ? 1 : 0; } 815 | 816 | inline bool isMemberNameStatic() const { return memberNameIsStatic_ == 0; } 817 | 818 | inline void setMemberNameIsStatic(bool isStatic) { 819 | memberNameIsStatic_ = isStatic ? 1 : 0; 820 | } 821 | #endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP 822 | 823 | private: 824 | struct CommentInfo { 825 | CommentInfo(); 826 | ~CommentInfo(); 827 | 828 | void setComment(const char* text); 829 | 830 | char* comment_; 831 | }; 832 | 833 | // struct MemberNamesTransform 834 | //{ 835 | // typedef const char *result_type; 836 | // const char *operator()( const CZString &name ) const 837 | // { 838 | // return name.c_str(); 839 | // } 840 | //}; 841 | 842 | union ValueHolder { 843 | LargestInt int_; 844 | LargestUInt uint_; 845 | double real_; 846 | bool bool_; 847 | char* string_; 848 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 849 | ValueInternalArray* array_; 850 | ValueInternalMap* map_; 851 | #else 852 | ObjectValues* map_; 853 | #endif 854 | } value_; 855 | ValueType type_ : 8; 856 | int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. 857 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 858 | unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. 859 | int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. 860 | #endif 861 | CommentInfo* comments_; 862 | 863 | // [start, limit) byte offsets in the source JSON text from which this Value 864 | // was extracted. 865 | size_t start_; 866 | size_t limit_; 867 | }; 868 | 869 | /** \brief Experimental and untested: represents an element of the "path" to 870 | * access a node. 871 | */ 872 | class JSON_API PathArgument { 873 | public: 874 | friend class Path; 875 | 876 | PathArgument(); 877 | PathArgument(ArrayIndex index); 878 | PathArgument(const char* key); 879 | PathArgument(const std::string& key); 880 | 881 | private: 882 | enum Kind { 883 | kindNone = 0, 884 | kindIndex, 885 | kindKey 886 | }; 887 | std::string key_; 888 | ArrayIndex index_; 889 | Kind kind_; 890 | }; 891 | 892 | /** \brief Experimental and untested: represents a "path" to access a node. 893 | * 894 | * Syntax: 895 | * - "." => root node 896 | * - ".[n]" => elements at index 'n' of root node (an array value) 897 | * - ".name" => member named 'name' of root node (an object value) 898 | * - ".name1.name2.name3" 899 | * - ".[0][1][2].name1[3]" 900 | * - ".%" => member name is provided as parameter 901 | * - ".[%]" => index is provied as parameter 902 | */ 903 | class JSON_API Path { 904 | public: 905 | Path(const std::string& path, 906 | const PathArgument& a1 = PathArgument(), 907 | const PathArgument& a2 = PathArgument(), 908 | const PathArgument& a3 = PathArgument(), 909 | const PathArgument& a4 = PathArgument(), 910 | const PathArgument& a5 = PathArgument()); 911 | 912 | const Value& resolve(const Value& root) const; 913 | Value resolve(const Value& root, const Value& defaultValue) const; 914 | /// Creates the "path" to access the specified node and returns a reference on 915 | /// the node. 916 | Value& make(Value& root) const; 917 | 918 | private: 919 | typedef std::vector InArgs; 920 | typedef std::vector Args; 921 | 922 | void makePath(const std::string& path, const InArgs& in); 923 | void addPathInArg(const std::string& path, 924 | const InArgs& in, 925 | InArgs::const_iterator& itInArg, 926 | PathArgument::Kind kind); 927 | void invalidPath(const std::string& path, int location); 928 | 929 | Args args_; 930 | }; 931 | 932 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 933 | /** \brief Allocator to customize Value internal map. 934 | * Below is an example of a simple implementation (default implementation 935 | actually 936 | * use memory pool for speed). 937 | * \code 938 | class DefaultValueMapAllocator : public ValueMapAllocator 939 | { 940 | public: // overridden from ValueMapAllocator 941 | virtual ValueInternalMap *newMap() 942 | { 943 | return new ValueInternalMap(); 944 | } 945 | 946 | virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) 947 | { 948 | return new ValueInternalMap( other ); 949 | } 950 | 951 | virtual void destructMap( ValueInternalMap *map ) 952 | { 953 | delete map; 954 | } 955 | 956 | virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) 957 | { 958 | return new ValueInternalLink[size]; 959 | } 960 | 961 | virtual void releaseMapBuckets( ValueInternalLink *links ) 962 | { 963 | delete [] links; 964 | } 965 | 966 | virtual ValueInternalLink *allocateMapLink() 967 | { 968 | return new ValueInternalLink(); 969 | } 970 | 971 | virtual void releaseMapLink( ValueInternalLink *link ) 972 | { 973 | delete link; 974 | } 975 | }; 976 | * \endcode 977 | */ 978 | class JSON_API ValueMapAllocator { 979 | public: 980 | virtual ~ValueMapAllocator(); 981 | virtual ValueInternalMap* newMap() = 0; 982 | virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) = 0; 983 | virtual void destructMap(ValueInternalMap* map) = 0; 984 | virtual ValueInternalLink* allocateMapBuckets(unsigned int size) = 0; 985 | virtual void releaseMapBuckets(ValueInternalLink* links) = 0; 986 | virtual ValueInternalLink* allocateMapLink() = 0; 987 | virtual void releaseMapLink(ValueInternalLink* link) = 0; 988 | }; 989 | 990 | /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). 991 | * \internal previous_ & next_ allows for bidirectional traversal. 992 | */ 993 | class JSON_API ValueInternalLink { 994 | public: 995 | enum { 996 | itemPerLink = 6 997 | }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. 998 | enum InternalFlags { 999 | flagAvailable = 0, 1000 | flagUsed = 1 1001 | }; 1002 | 1003 | ValueInternalLink(); 1004 | 1005 | ~ValueInternalLink(); 1006 | 1007 | Value items_[itemPerLink]; 1008 | char* keys_[itemPerLink]; 1009 | ValueInternalLink* previous_; 1010 | ValueInternalLink* next_; 1011 | }; 1012 | 1013 | /** \brief A linked page based hash-table implementation used internally by 1014 | *Value. 1015 | * \internal ValueInternalMap is a tradional bucket based hash-table, with a 1016 | *linked 1017 | * list in each bucket to handle collision. There is an addional twist in that 1018 | * each node of the collision linked list is a page containing a fixed amount of 1019 | * value. This provides a better compromise between memory usage and speed. 1020 | * 1021 | * Each bucket is made up of a chained list of ValueInternalLink. The last 1022 | * link of a given bucket can be found in the 'previous_' field of the following 1023 | *bucket. 1024 | * The last link of the last bucket is stored in tailLink_ as it has no 1025 | *following bucket. 1026 | * Only the last link of a bucket may contains 'available' item. The last link 1027 | *always 1028 | * contains at least one element unless is it the bucket one very first link. 1029 | */ 1030 | class JSON_API ValueInternalMap { 1031 | friend class ValueIteratorBase; 1032 | friend class Value; 1033 | 1034 | public: 1035 | typedef unsigned int HashKey; 1036 | typedef unsigned int BucketIndex; 1037 | 1038 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 1039 | struct IteratorState { 1040 | IteratorState() : map_(0), link_(0), itemIndex_(0), bucketIndex_(0) {} 1041 | ValueInternalMap* map_; 1042 | ValueInternalLink* link_; 1043 | BucketIndex itemIndex_; 1044 | BucketIndex bucketIndex_; 1045 | }; 1046 | #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 1047 | 1048 | ValueInternalMap(); 1049 | ValueInternalMap(const ValueInternalMap& other); 1050 | ValueInternalMap& operator=(ValueInternalMap other); 1051 | ~ValueInternalMap(); 1052 | 1053 | void swap(ValueInternalMap& other); 1054 | 1055 | BucketIndex size() const; 1056 | 1057 | void clear(); 1058 | 1059 | bool reserveDelta(BucketIndex growth); 1060 | 1061 | bool reserve(BucketIndex newItemCount); 1062 | 1063 | const Value* find(const char* key) const; 1064 | 1065 | Value* find(const char* key); 1066 | 1067 | Value& resolveReference(const char* key, bool isStatic); 1068 | 1069 | void remove(const char* key); 1070 | 1071 | void doActualRemove(ValueInternalLink* link, 1072 | BucketIndex index, 1073 | BucketIndex bucketIndex); 1074 | 1075 | ValueInternalLink*& getLastLinkInBucket(BucketIndex bucketIndex); 1076 | 1077 | Value& setNewItem(const char* key, 1078 | bool isStatic, 1079 | ValueInternalLink* link, 1080 | BucketIndex index); 1081 | 1082 | Value& unsafeAdd(const char* key, bool isStatic, HashKey hashedKey); 1083 | 1084 | HashKey hash(const char* key) const; 1085 | 1086 | int compare(const ValueInternalMap& other) const; 1087 | 1088 | private: 1089 | void makeBeginIterator(IteratorState& it) const; 1090 | void makeEndIterator(IteratorState& it) const; 1091 | static bool equals(const IteratorState& x, const IteratorState& other); 1092 | static void increment(IteratorState& iterator); 1093 | static void incrementBucket(IteratorState& iterator); 1094 | static void decrement(IteratorState& iterator); 1095 | static const char* key(const IteratorState& iterator); 1096 | static const char* key(const IteratorState& iterator, bool& isStatic); 1097 | static Value& value(const IteratorState& iterator); 1098 | static int distance(const IteratorState& x, const IteratorState& y); 1099 | 1100 | private: 1101 | ValueInternalLink* buckets_; 1102 | ValueInternalLink* tailLink_; 1103 | BucketIndex bucketsSize_; 1104 | BucketIndex itemCount_; 1105 | }; 1106 | 1107 | /** \brief A simplified deque implementation used internally by Value. 1108 | * \internal 1109 | * It is based on a list of fixed "page", each page contains a fixed number of 1110 | *items. 1111 | * Instead of using a linked-list, a array of pointer is used for fast item 1112 | *look-up. 1113 | * Look-up for an element is as follow: 1114 | * - compute page index: pageIndex = itemIndex / itemsPerPage 1115 | * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] 1116 | * 1117 | * Insertion is amortized constant time (only the array containing the index of 1118 | *pointers 1119 | * need to be reallocated when items are appended). 1120 | */ 1121 | class JSON_API ValueInternalArray { 1122 | friend class Value; 1123 | friend class ValueIteratorBase; 1124 | 1125 | public: 1126 | enum { 1127 | itemsPerPage = 8 1128 | }; // should be a power of 2 for fast divide and modulo. 1129 | typedef Value::ArrayIndex ArrayIndex; 1130 | typedef unsigned int PageIndex; 1131 | 1132 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 1133 | struct IteratorState // Must be a POD 1134 | { 1135 | IteratorState() : array_(0), currentPageIndex_(0), currentItemIndex_(0) {} 1136 | ValueInternalArray* array_; 1137 | Value** currentPageIndex_; 1138 | unsigned int currentItemIndex_; 1139 | }; 1140 | #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 1141 | 1142 | ValueInternalArray(); 1143 | ValueInternalArray(const ValueInternalArray& other); 1144 | ValueInternalArray& operator=(ValueInternalArray other); 1145 | ~ValueInternalArray(); 1146 | void swap(ValueInternalArray& other); 1147 | 1148 | void clear(); 1149 | void resize(ArrayIndex newSize); 1150 | 1151 | Value& resolveReference(ArrayIndex index); 1152 | 1153 | Value* find(ArrayIndex index) const; 1154 | 1155 | ArrayIndex size() const; 1156 | 1157 | int compare(const ValueInternalArray& other) const; 1158 | 1159 | private: 1160 | static bool equals(const IteratorState& x, const IteratorState& other); 1161 | static void increment(IteratorState& iterator); 1162 | static void decrement(IteratorState& iterator); 1163 | static Value& dereference(const IteratorState& iterator); 1164 | static Value& unsafeDereference(const IteratorState& iterator); 1165 | static int distance(const IteratorState& x, const IteratorState& y); 1166 | static ArrayIndex indexOf(const IteratorState& iterator); 1167 | void makeBeginIterator(IteratorState& it) const; 1168 | void makeEndIterator(IteratorState& it) const; 1169 | void makeIterator(IteratorState& it, ArrayIndex index) const; 1170 | 1171 | void makeIndexValid(ArrayIndex index); 1172 | 1173 | Value** pages_; 1174 | ArrayIndex size_; 1175 | PageIndex pageCount_; 1176 | }; 1177 | 1178 | /** \brief Experimental: do not use. Allocator to customize Value internal 1179 | array. 1180 | * Below is an example of a simple implementation (actual implementation use 1181 | * memory pool). 1182 | \code 1183 | class DefaultValueArrayAllocator : public ValueArrayAllocator 1184 | { 1185 | public: // overridden from ValueArrayAllocator 1186 | virtual ~DefaultValueArrayAllocator() 1187 | { 1188 | } 1189 | 1190 | virtual ValueInternalArray *newArray() 1191 | { 1192 | return new ValueInternalArray(); 1193 | } 1194 | 1195 | virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) 1196 | { 1197 | return new ValueInternalArray( other ); 1198 | } 1199 | 1200 | virtual void destruct( ValueInternalArray *array ) 1201 | { 1202 | delete array; 1203 | } 1204 | 1205 | virtual void reallocateArrayPageIndex( Value **&indexes, 1206 | ValueInternalArray::PageIndex 1207 | &indexCount, 1208 | ValueInternalArray::PageIndex 1209 | minNewIndexCount ) 1210 | { 1211 | ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; 1212 | if ( minNewIndexCount > newIndexCount ) 1213 | newIndexCount = minNewIndexCount; 1214 | void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); 1215 | if ( !newIndexes ) 1216 | throw std::bad_alloc(); 1217 | indexCount = newIndexCount; 1218 | indexes = static_cast( newIndexes ); 1219 | } 1220 | virtual void releaseArrayPageIndex( Value **indexes, 1221 | ValueInternalArray::PageIndex indexCount ) 1222 | { 1223 | if ( indexes ) 1224 | free( indexes ); 1225 | } 1226 | 1227 | virtual Value *allocateArrayPage() 1228 | { 1229 | return static_cast( malloc( sizeof(Value) * 1230 | ValueInternalArray::itemsPerPage ) ); 1231 | } 1232 | 1233 | virtual void releaseArrayPage( Value *value ) 1234 | { 1235 | if ( value ) 1236 | free( value ); 1237 | } 1238 | }; 1239 | \endcode 1240 | */ 1241 | class JSON_API ValueArrayAllocator { 1242 | public: 1243 | virtual ~ValueArrayAllocator(); 1244 | virtual ValueInternalArray* newArray() = 0; 1245 | virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) = 0; 1246 | virtual void destructArray(ValueInternalArray* array) = 0; 1247 | /** \brief Reallocate array page index. 1248 | * Reallocates an array of pointer on each page. 1249 | * \param indexes [input] pointer on the current index. May be \c NULL. 1250 | * [output] pointer on the new index of at least 1251 | * \a minNewIndexCount pages. 1252 | * \param indexCount [input] current number of pages in the index. 1253 | * [output] number of page the reallocated index can handle. 1254 | * \b MUST be >= \a minNewIndexCount. 1255 | * \param minNewIndexCount Minimum number of page the new index must be able 1256 | * to 1257 | * handle. 1258 | */ 1259 | virtual void 1260 | reallocateArrayPageIndex(Value**& indexes, 1261 | ValueInternalArray::PageIndex& indexCount, 1262 | ValueInternalArray::PageIndex minNewIndexCount) = 0; 1263 | virtual void 1264 | releaseArrayPageIndex(Value** indexes, 1265 | ValueInternalArray::PageIndex indexCount) = 0; 1266 | virtual Value* allocateArrayPage() = 0; 1267 | virtual void releaseArrayPage(Value* value) = 0; 1268 | }; 1269 | #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP 1270 | 1271 | /** \brief base class for Value iterators. 1272 | * 1273 | */ 1274 | class JSON_API ValueIteratorBase { 1275 | public: 1276 | typedef std::bidirectional_iterator_tag iterator_category; 1277 | typedef unsigned int size_t; 1278 | typedef int difference_type; 1279 | typedef ValueIteratorBase SelfType; 1280 | 1281 | ValueIteratorBase(); 1282 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1283 | explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); 1284 | #else 1285 | ValueIteratorBase(const ValueInternalArray::IteratorState& state); 1286 | ValueIteratorBase(const ValueInternalMap::IteratorState& state); 1287 | #endif 1288 | 1289 | bool operator==(const SelfType& other) const { return isEqual(other); } 1290 | 1291 | bool operator!=(const SelfType& other) const { return !isEqual(other); } 1292 | 1293 | difference_type operator-(const SelfType& other) const { 1294 | return computeDistance(other); 1295 | } 1296 | 1297 | /// Return either the index or the member name of the referenced value as a 1298 | /// Value. 1299 | Value key() const; 1300 | 1301 | /// Return the index of the referenced Value. -1 if it is not an arrayValue. 1302 | UInt index() const; 1303 | 1304 | /// Return the member name of the referenced Value. "" if it is not an 1305 | /// objectValue. 1306 | const char* memberName() const; 1307 | 1308 | protected: 1309 | Value& deref() const; 1310 | 1311 | void increment(); 1312 | 1313 | void decrement(); 1314 | 1315 | difference_type computeDistance(const SelfType& other) const; 1316 | 1317 | bool isEqual(const SelfType& other) const; 1318 | 1319 | void copy(const SelfType& other); 1320 | 1321 | private: 1322 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1323 | Value::ObjectValues::iterator current_; 1324 | // Indicates that iterator is for a null value. 1325 | bool isNull_; 1326 | #else 1327 | union { 1328 | ValueInternalArray::IteratorState array_; 1329 | ValueInternalMap::IteratorState map_; 1330 | } iterator_; 1331 | bool isArray_; 1332 | #endif 1333 | }; 1334 | 1335 | /** \brief const iterator for object and array value. 1336 | * 1337 | */ 1338 | class JSON_API ValueConstIterator : public ValueIteratorBase { 1339 | friend class Value; 1340 | 1341 | public: 1342 | typedef const Value value_type; 1343 | typedef unsigned int size_t; 1344 | typedef int difference_type; 1345 | typedef const Value& reference; 1346 | typedef const Value* pointer; 1347 | typedef ValueConstIterator SelfType; 1348 | 1349 | ValueConstIterator(); 1350 | 1351 | private: 1352 | /*! \internal Use by Value to create an iterator. 1353 | */ 1354 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1355 | explicit ValueConstIterator(const Value::ObjectValues::iterator& current); 1356 | #else 1357 | ValueConstIterator(const ValueInternalArray::IteratorState& state); 1358 | ValueConstIterator(const ValueInternalMap::IteratorState& state); 1359 | #endif 1360 | public: 1361 | SelfType& operator=(const ValueIteratorBase& other); 1362 | 1363 | SelfType operator++(int) { 1364 | SelfType temp(*this); 1365 | ++*this; 1366 | return temp; 1367 | } 1368 | 1369 | SelfType operator--(int) { 1370 | SelfType temp(*this); 1371 | --*this; 1372 | return temp; 1373 | } 1374 | 1375 | SelfType& operator--() { 1376 | decrement(); 1377 | return *this; 1378 | } 1379 | 1380 | SelfType& operator++() { 1381 | increment(); 1382 | return *this; 1383 | } 1384 | 1385 | reference operator*() const { return deref(); } 1386 | 1387 | pointer operator->() const { return &deref(); } 1388 | }; 1389 | 1390 | /** \brief Iterator for object and array value. 1391 | */ 1392 | class JSON_API ValueIterator : public ValueIteratorBase { 1393 | friend class Value; 1394 | 1395 | public: 1396 | typedef Value value_type; 1397 | typedef unsigned int size_t; 1398 | typedef int difference_type; 1399 | typedef Value& reference; 1400 | typedef Value* pointer; 1401 | typedef ValueIterator SelfType; 1402 | 1403 | ValueIterator(); 1404 | ValueIterator(const ValueConstIterator& other); 1405 | ValueIterator(const ValueIterator& other); 1406 | 1407 | private: 1408 | /*! \internal Use by Value to create an iterator. 1409 | */ 1410 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1411 | explicit ValueIterator(const Value::ObjectValues::iterator& current); 1412 | #else 1413 | ValueIterator(const ValueInternalArray::IteratorState& state); 1414 | ValueIterator(const ValueInternalMap::IteratorState& state); 1415 | #endif 1416 | public: 1417 | SelfType& operator=(const SelfType& other); 1418 | 1419 | SelfType operator++(int) { 1420 | SelfType temp(*this); 1421 | ++*this; 1422 | return temp; 1423 | } 1424 | 1425 | SelfType operator--(int) { 1426 | SelfType temp(*this); 1427 | --*this; 1428 | return temp; 1429 | } 1430 | 1431 | SelfType& operator--() { 1432 | decrement(); 1433 | return *this; 1434 | } 1435 | 1436 | SelfType& operator++() { 1437 | increment(); 1438 | return *this; 1439 | } 1440 | 1441 | reference operator*() const { return deref(); } 1442 | 1443 | pointer operator->() const { return &deref(); } 1444 | }; 1445 | 1446 | } // namespace Json 1447 | 1448 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1449 | #pragma warning(pop) 1450 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1451 | 1452 | #endif // CPPTL_JSON_H_INCLUDED 1453 | 1454 | // ////////////////////////////////////////////////////////////////////// 1455 | // End of content of file: include/json/value.h 1456 | // ////////////////////////////////////////////////////////////////////// 1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | // ////////////////////////////////////////////////////////////////////// 1464 | // Beginning of content of file: include/json/reader.h 1465 | // ////////////////////////////////////////////////////////////////////// 1466 | 1467 | // Copyright 2007-2010 Baptiste Lepilleur 1468 | // Distributed under MIT license, or public domain if desired and 1469 | // recognized in your jurisdiction. 1470 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 1471 | 1472 | #ifndef CPPTL_JSON_READER_H_INCLUDED 1473 | #define CPPTL_JSON_READER_H_INCLUDED 1474 | 1475 | #if !defined(JSON_IS_AMALGAMATION) 1476 | #include "features.h" 1477 | #include "value.h" 1478 | #endif // if !defined(JSON_IS_AMALGAMATION) 1479 | #include 1480 | #include 1481 | #include 1482 | #include 1483 | 1484 | // Disable warning C4251: : needs to have dll-interface to 1485 | // be used by... 1486 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1487 | #pragma warning(push) 1488 | #pragma warning(disable : 4251) 1489 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1490 | 1491 | namespace Json { 1492 | 1493 | /** \brief Unserialize a JSON document into a 1494 | *Value. 1495 | * 1496 | */ 1497 | class JSON_API Reader { 1498 | public: 1499 | typedef char Char; 1500 | typedef const Char* Location; 1501 | 1502 | /** \brief An error tagged with where in the JSON text it was encountered. 1503 | * 1504 | * The offsets give the [start, limit) range of bytes within the text. Note 1505 | * that this is bytes, not codepoints. 1506 | * 1507 | */ 1508 | struct StructuredError { 1509 | size_t offset_start; 1510 | size_t offset_limit; 1511 | std::string message; 1512 | }; 1513 | 1514 | /** \brief Constructs a Reader allowing all features 1515 | * for parsing. 1516 | */ 1517 | Reader(); 1518 | 1519 | /** \brief Constructs a Reader allowing the specified feature set 1520 | * for parsing. 1521 | */ 1522 | Reader(const Features& features); 1523 | 1524 | /** \brief Read a Value from a JSON 1525 | * document. 1526 | * \param document UTF-8 encoded string containing the document to read. 1527 | * \param root [out] Contains the root value of the document if it was 1528 | * successfully parsed. 1529 | * \param collectComments \c true to collect comment and allow writing them 1530 | * back during 1531 | * serialization, \c false to discard comments. 1532 | * This parameter is ignored if 1533 | * Features::allowComments_ 1534 | * is \c false. 1535 | * \return \c true if the document was successfully parsed, \c false if an 1536 | * error occurred. 1537 | */ 1538 | bool 1539 | parse(const std::string& document, Value& root, bool collectComments = true); 1540 | 1541 | /** \brief Read a Value from a JSON 1542 | document. 1543 | * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the 1544 | document to read. 1545 | * \param endDoc Pointer on the end of the UTF-8 encoded string of the 1546 | document to read. 1547 | \ Must be >= beginDoc. 1548 | * \param root [out] Contains the root value of the document if it was 1549 | * successfully parsed. 1550 | * \param collectComments \c true to collect comment and allow writing them 1551 | back during 1552 | * serialization, \c false to discard comments. 1553 | * This parameter is ignored if 1554 | Features::allowComments_ 1555 | * is \c false. 1556 | * \return \c true if the document was successfully parsed, \c false if an 1557 | error occurred. 1558 | */ 1559 | bool parse(const char* beginDoc, 1560 | const char* endDoc, 1561 | Value& root, 1562 | bool collectComments = true); 1563 | 1564 | /// \brief Parse from input stream. 1565 | /// \see Json::operator>>(std::istream&, Json::Value&). 1566 | bool parse(std::istream& is, Value& root, bool collectComments = true); 1567 | 1568 | /** \brief Returns a user friendly string that list errors in the parsed 1569 | * document. 1570 | * \return Formatted error message with the list of errors with their location 1571 | * in 1572 | * the parsed document. An empty string is returned if no error 1573 | * occurred 1574 | * during parsing. 1575 | * \deprecated Use getFormattedErrorMessages() instead (typo fix). 1576 | */ 1577 | JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") 1578 | std::string getFormatedErrorMessages() const; 1579 | 1580 | /** \brief Returns a user friendly string that list errors in the parsed 1581 | * document. 1582 | * \return Formatted error message with the list of errors with their location 1583 | * in 1584 | * the parsed document. An empty string is returned if no error 1585 | * occurred 1586 | * during parsing. 1587 | */ 1588 | std::string getFormattedErrorMessages() const; 1589 | 1590 | /** \brief Returns a vector of structured erros encounted while parsing. 1591 | * \return A (possibly empty) vector of StructuredError objects. Currently 1592 | * only one error can be returned, but the caller should tolerate 1593 | * multiple 1594 | * errors. This can occur if the parser recovers from a non-fatal 1595 | * parse error and then encounters additional errors. 1596 | */ 1597 | std::vector getStructuredErrors() const; 1598 | 1599 | private: 1600 | enum TokenType { 1601 | tokenEndOfStream = 0, 1602 | tokenObjectBegin, 1603 | tokenObjectEnd, 1604 | tokenArrayBegin, 1605 | tokenArrayEnd, 1606 | tokenString, 1607 | tokenNumber, 1608 | tokenTrue, 1609 | tokenFalse, 1610 | tokenNull, 1611 | tokenArraySeparator, 1612 | tokenMemberSeparator, 1613 | tokenComment, 1614 | tokenError 1615 | }; 1616 | 1617 | class Token { 1618 | public: 1619 | TokenType type_; 1620 | Location start_; 1621 | Location end_; 1622 | }; 1623 | 1624 | class ErrorInfo { 1625 | public: 1626 | Token token_; 1627 | std::string message_; 1628 | Location extra_; 1629 | }; 1630 | 1631 | typedef std::deque Errors; 1632 | 1633 | bool expectToken(TokenType type, Token& token, const char* message); 1634 | bool readToken(Token& token); 1635 | void skipSpaces(); 1636 | bool match(Location pattern, int patternLength); 1637 | bool readComment(); 1638 | bool readCStyleComment(); 1639 | bool readCppStyleComment(); 1640 | bool readString(); 1641 | void readNumber(); 1642 | bool readValue(); 1643 | bool readObject(Token& token); 1644 | bool readArray(Token& token); 1645 | bool decodeNumber(Token& token); 1646 | bool decodeNumber(Token& token, Value& decoded); 1647 | bool decodeString(Token& token); 1648 | bool decodeString(Token& token, std::string& decoded); 1649 | bool decodeDouble(Token& token); 1650 | bool decodeDouble(Token& token, Value& decoded); 1651 | bool decodeUnicodeCodePoint(Token& token, 1652 | Location& current, 1653 | Location end, 1654 | unsigned int& unicode); 1655 | bool decodeUnicodeEscapeSequence(Token& token, 1656 | Location& current, 1657 | Location end, 1658 | unsigned int& unicode); 1659 | bool addError(const std::string& message, Token& token, Location extra = 0); 1660 | bool recoverFromError(TokenType skipUntilToken); 1661 | bool addErrorAndRecover(const std::string& message, 1662 | Token& token, 1663 | TokenType skipUntilToken); 1664 | void skipUntilSpace(); 1665 | Value& currentValue(); 1666 | Char getNextChar(); 1667 | void 1668 | getLocationLineAndColumn(Location location, int& line, int& column) const; 1669 | std::string getLocationLineAndColumn(Location location) const; 1670 | void addComment(Location begin, Location end, CommentPlacement placement); 1671 | void skipCommentTokens(Token& token); 1672 | 1673 | typedef std::stack Nodes; 1674 | Nodes nodes_; 1675 | Errors errors_; 1676 | std::string document_; 1677 | Location begin_; 1678 | Location end_; 1679 | Location current_; 1680 | Location lastValueEnd_; 1681 | Value* lastValue_; 1682 | std::string commentsBefore_; 1683 | Features features_; 1684 | bool collectComments_; 1685 | }; 1686 | 1687 | /** \brief Read from 'sin' into 'root'. 1688 | 1689 | Always keep comments from the input JSON. 1690 | 1691 | This can be used to read a file into a particular sub-object. 1692 | For example: 1693 | \code 1694 | Json::Value root; 1695 | cin >> root["dir"]["file"]; 1696 | cout << root; 1697 | \endcode 1698 | Result: 1699 | \verbatim 1700 | { 1701 | "dir": { 1702 | "file": { 1703 | // The input stream JSON would be nested here. 1704 | } 1705 | } 1706 | } 1707 | \endverbatim 1708 | \throw std::exception on parse error. 1709 | \see Json::operator<<() 1710 | */ 1711 | JSON_API std::istream& operator>>(std::istream&, Value&); 1712 | 1713 | } // namespace Json 1714 | 1715 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1716 | #pragma warning(pop) 1717 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1718 | 1719 | #endif // CPPTL_JSON_READER_H_INCLUDED 1720 | 1721 | // ////////////////////////////////////////////////////////////////////// 1722 | // End of content of file: include/json/reader.h 1723 | // ////////////////////////////////////////////////////////////////////// 1724 | 1725 | 1726 | 1727 | 1728 | 1729 | 1730 | // ////////////////////////////////////////////////////////////////////// 1731 | // Beginning of content of file: include/json/writer.h 1732 | // ////////////////////////////////////////////////////////////////////// 1733 | 1734 | // Copyright 2007-2010 Baptiste Lepilleur 1735 | // Distributed under MIT license, or public domain if desired and 1736 | // recognized in your jurisdiction. 1737 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 1738 | 1739 | #ifndef JSON_WRITER_H_INCLUDED 1740 | #define JSON_WRITER_H_INCLUDED 1741 | 1742 | #if !defined(JSON_IS_AMALGAMATION) 1743 | #include "value.h" 1744 | #endif // if !defined(JSON_IS_AMALGAMATION) 1745 | #include 1746 | #include 1747 | 1748 | // Disable warning C4251: : needs to have dll-interface to 1749 | // be used by... 1750 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1751 | #pragma warning(push) 1752 | #pragma warning(disable : 4251) 1753 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1754 | 1755 | namespace Json { 1756 | 1757 | class Value; 1758 | 1759 | /** \brief Abstract class for writers. 1760 | */ 1761 | class JSON_API Writer { 1762 | public: 1763 | virtual ~Writer(); 1764 | 1765 | virtual std::string write(const Value& root) = 0; 1766 | }; 1767 | 1768 | /** \brief Outputs a Value in JSON format 1769 | *without formatting (not human friendly). 1770 | * 1771 | * The JSON document is written in a single line. It is not intended for 'human' 1772 | *consumption, 1773 | * but may be usefull to support feature such as RPC where bandwith is limited. 1774 | * \sa Reader, Value 1775 | */ 1776 | class JSON_API FastWriter : public Writer { 1777 | public: 1778 | FastWriter(); 1779 | virtual ~FastWriter() {} 1780 | 1781 | void enableYAMLCompatibility(); 1782 | 1783 | /** \brief Drop the "null" string from the writer's output for nullValues. 1784 | * Strictly speaking, this is not valid JSON. But when the output is being 1785 | * fed to a browser's Javascript, it makes for smaller output and the 1786 | * browser can handle the output just fine. 1787 | */ 1788 | void dropNullPlaceholders(); 1789 | 1790 | void omitEndingLineFeed(); 1791 | 1792 | public: // overridden from Writer 1793 | virtual std::string write(const Value& root); 1794 | 1795 | private: 1796 | void writeValue(const Value& value); 1797 | 1798 | std::string document_; 1799 | bool yamlCompatiblityEnabled_; 1800 | bool dropNullPlaceholders_; 1801 | bool omitEndingLineFeed_; 1802 | }; 1803 | 1804 | /** \brief Writes a Value in JSON format in a 1805 | *human friendly way. 1806 | * 1807 | * The rules for line break and indent are as follow: 1808 | * - Object value: 1809 | * - if empty then print {} without indent and line break 1810 | * - if not empty the print '{', line break & indent, print one value per 1811 | *line 1812 | * and then unindent and line break and print '}'. 1813 | * - Array value: 1814 | * - if empty then print [] without indent and line break 1815 | * - if the array contains no object value, empty array or some other value 1816 | *types, 1817 | * and all the values fit on one lines, then print the array on a single 1818 | *line. 1819 | * - otherwise, it the values do not fit on one line, or the array contains 1820 | * object or non empty array, then print one value per line. 1821 | * 1822 | * If the Value have comments then they are outputed according to their 1823 | *#CommentPlacement. 1824 | * 1825 | * \sa Reader, Value, Value::setComment() 1826 | */ 1827 | class JSON_API StyledWriter : public Writer { 1828 | public: 1829 | StyledWriter(); 1830 | virtual ~StyledWriter() {} 1831 | 1832 | public: // overridden from Writer 1833 | /** \brief Serialize a Value in JSON format. 1834 | * \param root Value to serialize. 1835 | * \return String containing the JSON document that represents the root value. 1836 | */ 1837 | virtual std::string write(const Value& root); 1838 | 1839 | private: 1840 | void writeValue(const Value& value); 1841 | void writeArrayValue(const Value& value); 1842 | bool isMultineArray(const Value& value); 1843 | void pushValue(const std::string& value); 1844 | void writeIndent(); 1845 | void writeWithIndent(const std::string& value); 1846 | void indent(); 1847 | void unindent(); 1848 | void writeCommentBeforeValue(const Value& root); 1849 | void writeCommentAfterValueOnSameLine(const Value& root); 1850 | bool hasCommentForValue(const Value& value); 1851 | static std::string normalizeEOL(const std::string& text); 1852 | 1853 | typedef std::vector ChildValues; 1854 | 1855 | ChildValues childValues_; 1856 | std::string document_; 1857 | std::string indentString_; 1858 | int rightMargin_; 1859 | int indentSize_; 1860 | bool addChildValues_; 1861 | }; 1862 | 1863 | /** \brief Writes a Value in JSON format in a 1864 | human friendly way, 1865 | to a stream rather than to a string. 1866 | * 1867 | * The rules for line break and indent are as follow: 1868 | * - Object value: 1869 | * - if empty then print {} without indent and line break 1870 | * - if not empty the print '{', line break & indent, print one value per 1871 | line 1872 | * and then unindent and line break and print '}'. 1873 | * - Array value: 1874 | * - if empty then print [] without indent and line break 1875 | * - if the array contains no object value, empty array or some other value 1876 | types, 1877 | * and all the values fit on one lines, then print the array on a single 1878 | line. 1879 | * - otherwise, it the values do not fit on one line, or the array contains 1880 | * object or non empty array, then print one value per line. 1881 | * 1882 | * If the Value have comments then they are outputed according to their 1883 | #CommentPlacement. 1884 | * 1885 | * \param indentation Each level will be indented by this amount extra. 1886 | * \sa Reader, Value, Value::setComment() 1887 | */ 1888 | class JSON_API StyledStreamWriter { 1889 | public: 1890 | StyledStreamWriter(std::string indentation = "\t"); 1891 | ~StyledStreamWriter() {} 1892 | 1893 | public: 1894 | /** \brief Serialize a Value in JSON format. 1895 | * \param out Stream to write to. (Can be ostringstream, e.g.) 1896 | * \param root Value to serialize. 1897 | * \note There is no point in deriving from Writer, since write() should not 1898 | * return a value. 1899 | */ 1900 | void write(std::ostream& out, const Value& root); 1901 | 1902 | private: 1903 | void writeValue(const Value& value); 1904 | void writeArrayValue(const Value& value); 1905 | bool isMultineArray(const Value& value); 1906 | void pushValue(const std::string& value); 1907 | void writeIndent(); 1908 | void writeWithIndent(const std::string& value); 1909 | void indent(); 1910 | void unindent(); 1911 | void writeCommentBeforeValue(const Value& root); 1912 | void writeCommentAfterValueOnSameLine(const Value& root); 1913 | bool hasCommentForValue(const Value& value); 1914 | static std::string normalizeEOL(const std::string& text); 1915 | 1916 | typedef std::vector ChildValues; 1917 | 1918 | ChildValues childValues_; 1919 | std::ostream* document_; 1920 | std::string indentString_; 1921 | int rightMargin_; 1922 | std::string indentation_; 1923 | bool addChildValues_; 1924 | }; 1925 | 1926 | #if defined(JSON_HAS_INT64) 1927 | std::string JSON_API valueToString(Int value); 1928 | std::string JSON_API valueToString(UInt value); 1929 | #endif // if defined(JSON_HAS_INT64) 1930 | std::string JSON_API valueToString(LargestInt value); 1931 | std::string JSON_API valueToString(LargestUInt value); 1932 | std::string JSON_API valueToString(double value); 1933 | std::string JSON_API valueToString(bool value); 1934 | std::string JSON_API valueToQuotedString(const char* value); 1935 | 1936 | /// \brief Output using the StyledStreamWriter. 1937 | /// \see Json::operator>>() 1938 | JSON_API std::ostream& operator<<(std::ostream&, const Value& root); 1939 | 1940 | } // namespace Json 1941 | 1942 | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1943 | #pragma warning(pop) 1944 | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) 1945 | 1946 | #endif // JSON_WRITER_H_INCLUDED 1947 | 1948 | // ////////////////////////////////////////////////////////////////////// 1949 | // End of content of file: include/json/writer.h 1950 | // ////////////////////////////////////////////////////////////////////// 1951 | 1952 | 1953 | 1954 | 1955 | 1956 | 1957 | // ////////////////////////////////////////////////////////////////////// 1958 | // Beginning of content of file: include/json/assertions.h 1959 | // ////////////////////////////////////////////////////////////////////// 1960 | 1961 | // Copyright 2007-2010 Baptiste Lepilleur 1962 | // Distributed under MIT license, or public domain if desired and 1963 | // recognized in your jurisdiction. 1964 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 1965 | 1966 | #ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED 1967 | #define CPPTL_JSON_ASSERTIONS_H_INCLUDED 1968 | 1969 | #include 1970 | 1971 | #if !defined(JSON_IS_AMALGAMATION) 1972 | #include "config.h" 1973 | #endif // if !defined(JSON_IS_AMALGAMATION) 1974 | 1975 | #if JSON_USE_EXCEPTION 1976 | #include 1977 | #define JSON_ASSERT(condition) \ 1978 | assert(condition); // @todo <= change this into an exception throw 1979 | #define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message); 1980 | #else // JSON_USE_EXCEPTION 1981 | #define JSON_ASSERT(condition) assert(condition); 1982 | 1983 | // The call to assert() will show the failure message in debug builds. In 1984 | // release bugs we write to invalid memory in order to crash hard, so that a 1985 | // debugger or crash reporter gets the chance to take over. We still call exit() 1986 | // afterward in order to tell the compiler that this macro doesn't return. 1987 | #define JSON_FAIL_MESSAGE(message) \ 1988 | { \ 1989 | assert(false&& message); \ 1990 | strcpy(reinterpret_cast(666), message); \ 1991 | exit(123); \ 1992 | } 1993 | 1994 | #endif 1995 | 1996 | #define JSON_ASSERT_MESSAGE(condition, message) \ 1997 | if (!(condition)) { \ 1998 | JSON_FAIL_MESSAGE(message) \ 1999 | } 2000 | 2001 | #endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED 2002 | 2003 | // ////////////////////////////////////////////////////////////////////// 2004 | // End of content of file: include/json/assertions.h 2005 | // ////////////////////////////////////////////////////////////////////// 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | #endif //ifndef JSON_AMALGATED_H_INCLUDED 2012 | 2013 | #ifndef INCLUDE_CPP 2014 | #define INCLUDE_CPP 2015 | #include "jsoncpp.cpp" 2016 | #endif -------------------------------------------------------------------------------- /jsoncpp/jsoncpp.cpp: -------------------------------------------------------------------------------- 1 | /// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). 2 | /// It is intented to be used with #include 3 | 4 | // ////////////////////////////////////////////////////////////////////// 5 | // Beginning of content of file: LICENSE 6 | // ////////////////////////////////////////////////////////////////////// 7 | 8 | /* 9 | The JsonCpp library's source code, including accompanying documentation, 10 | tests and demonstration applications, are licensed under the following 11 | conditions... 12 | 13 | The author (Baptiste Lepilleur) explicitly disclaims copyright in all 14 | jurisdictions which recognize such a disclaimer. In such jurisdictions, 15 | this software is released into the Public Domain. 16 | 17 | In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 18 | 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is 19 | released under the terms of the MIT License (see below). 20 | 21 | In jurisdictions which recognize Public Domain property, the user of this 22 | software may choose to accept it either as 1) Public Domain, 2) under the 23 | conditions of the MIT License (see below), or 3) under the terms of dual 24 | Public Domain/MIT License conditions described here, as they choose. 25 | 26 | The MIT License is about as close to Public Domain as a license can get, and is 27 | described in clear, concise terms at: 28 | 29 | http://en.wikipedia.org/wiki/MIT_License 30 | 31 | The full text of the MIT License follows: 32 | 33 | ======================================================================== 34 | Copyright (c) 2007-2010 Baptiste Lepilleur 35 | 36 | Permission is hereby granted, free of charge, to any person 37 | obtaining a copy of this software and associated documentation 38 | files (the "Software"), to deal in the Software without 39 | restriction, including without limitation the rights to use, copy, 40 | modify, merge, publish, distribute, sublicense, and/or sell copies 41 | of the Software, and to permit persons to whom the Software is 42 | furnished to do so, subject to the following conditions: 43 | 44 | The above copyright notice and this permission notice shall be 45 | included in all copies or substantial portions of the Software. 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 48 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 50 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 51 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 52 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 53 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 54 | SOFTWARE. 55 | ======================================================================== 56 | (END LICENSE TEXT) 57 | 58 | The MIT license is compatible with both the GPL and commercial 59 | software, affording one all of the rights of Public Domain with the 60 | minor nuisance of being required to keep the above copyright notice 61 | and license text in the source code. Note also that by accepting the 62 | Public Domain "license" you can re-license your copy using whatever 63 | license you like. 64 | 65 | */ 66 | 67 | // ////////////////////////////////////////////////////////////////////// 68 | // End of content of file: LICENSE 69 | // ////////////////////////////////////////////////////////////////////// 70 | 71 | 72 | 73 | 74 | 75 | 76 | #include "json.h" 77 | 78 | 79 | // ////////////////////////////////////////////////////////////////////// 80 | // Beginning of content of file: src/lib_json/json_tool.h 81 | // ////////////////////////////////////////////////////////////////////// 82 | 83 | // Copyright 2007-2010 Baptiste Lepilleur 84 | // Distributed under MIT license, or public domain if desired and 85 | // recognized in your jurisdiction. 86 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 87 | 88 | #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED 89 | #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED 90 | 91 | /* This header provides common string manipulation support, such as UTF-8, 92 | * portable conversion from/to string... 93 | * 94 | * It is an internal header that must not be exposed. 95 | */ 96 | 97 | namespace Json { 98 | 99 | /// Converts a unicode code-point to UTF-8. 100 | static inline std::string codePointToUTF8(unsigned int cp) { 101 | std::string result; 102 | 103 | // based on description from http://en.wikipedia.org/wiki/UTF-8 104 | 105 | if (cp <= 0x7f) { 106 | result.resize(1); 107 | result[0] = static_cast(cp); 108 | } else if (cp <= 0x7FF) { 109 | result.resize(2); 110 | result[1] = static_cast(0x80 | (0x3f & cp)); 111 | result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); 112 | } else if (cp <= 0xFFFF) { 113 | result.resize(3); 114 | result[2] = static_cast(0x80 | (0x3f & cp)); 115 | result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); 116 | result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); 117 | } else if (cp <= 0x10FFFF) { 118 | result.resize(4); 119 | result[3] = static_cast(0x80 | (0x3f & cp)); 120 | result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); 121 | result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); 122 | result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); 123 | } 124 | 125 | return result; 126 | } 127 | 128 | /// Returns true if ch is a control character (in range [0,32[). 129 | static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } 130 | 131 | enum { 132 | /// Constant that specify the size of the buffer that must be passed to 133 | /// uintToString. 134 | uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 135 | }; 136 | 137 | // Defines a char buffer for use with uintToString(). 138 | typedef char UIntToStringBuffer[uintToStringBufferSize]; 139 | 140 | /** Converts an unsigned integer to string. 141 | * @param value Unsigned interger to convert to string 142 | * @param current Input/Output string buffer. 143 | * Must have at least uintToStringBufferSize chars free. 144 | */ 145 | static inline void uintToString(LargestUInt value, char*& current) { 146 | *--current = 0; 147 | do { 148 | *--current = char(value % 10) + '0'; 149 | value /= 10; 150 | } while (value != 0); 151 | } 152 | 153 | /** Change ',' to '.' everywhere in buffer. 154 | * 155 | * We had a sophisticated way, but it did not work in WinCE. 156 | * @see https://github.com/open-source-parsers/jsoncpp/pull/9 157 | */ 158 | static inline void fixNumericLocale(char* begin, char* end) { 159 | while (begin < end) { 160 | if (*begin == ',') { 161 | *begin = '.'; 162 | } 163 | ++begin; 164 | } 165 | } 166 | 167 | } // namespace Json { 168 | 169 | #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED 170 | 171 | // ////////////////////////////////////////////////////////////////////// 172 | // End of content of file: src/lib_json/json_tool.h 173 | // ////////////////////////////////////////////////////////////////////// 174 | 175 | 176 | 177 | 178 | 179 | 180 | // ////////////////////////////////////////////////////////////////////// 181 | // Beginning of content of file: src/lib_json/json_reader.cpp 182 | // ////////////////////////////////////////////////////////////////////// 183 | 184 | // Copyright 2007-2011 Baptiste Lepilleur 185 | // Distributed under MIT license, or public domain if desired and 186 | // recognized in your jurisdiction. 187 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 188 | 189 | #if !defined(JSON_IS_AMALGAMATION) 190 | #include 191 | #include 192 | #include 193 | #include "json_tool.h" 194 | #endif // if !defined(JSON_IS_AMALGAMATION) 195 | #include 196 | #include 197 | #include 198 | #include 199 | #include 200 | 201 | #if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below 202 | #define snprintf _snprintf 203 | #endif 204 | 205 | #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 206 | // Disable warning about strdup being deprecated. 207 | #pragma warning(disable : 4996) 208 | #endif 209 | 210 | namespace Json { 211 | 212 | // Implementation of class Features 213 | // //////////////////////////////// 214 | 215 | Features::Features() 216 | : allowComments_(true), strictRoot_(false), 217 | allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} 218 | 219 | Features Features::all() { return Features(); } 220 | 221 | Features Features::strictMode() { 222 | Features features; 223 | features.allowComments_ = false; 224 | features.strictRoot_ = true; 225 | features.allowDroppedNullPlaceholders_ = false; 226 | features.allowNumericKeys_ = false; 227 | return features; 228 | } 229 | 230 | // Implementation of class Reader 231 | // //////////////////////////////// 232 | 233 | static inline bool in(Reader::Char c, 234 | Reader::Char c1, 235 | Reader::Char c2, 236 | Reader::Char c3, 237 | Reader::Char c4) { 238 | return c == c1 || c == c2 || c == c3 || c == c4; 239 | } 240 | 241 | static inline bool in(Reader::Char c, 242 | Reader::Char c1, 243 | Reader::Char c2, 244 | Reader::Char c3, 245 | Reader::Char c4, 246 | Reader::Char c5) { 247 | return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; 248 | } 249 | 250 | static bool containsNewLine(Reader::Location begin, Reader::Location end) { 251 | for (; begin < end; ++begin) 252 | if (*begin == '\n' || *begin == '\r') 253 | return true; 254 | return false; 255 | } 256 | 257 | // Class Reader 258 | // ////////////////////////////////////////////////////////////////// 259 | 260 | Reader::Reader() 261 | : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), 262 | lastValue_(), commentsBefore_(), features_(Features::all()), 263 | collectComments_() {} 264 | 265 | Reader::Reader(const Features& features) 266 | : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), 267 | lastValue_(), commentsBefore_(), features_(features), collectComments_() { 268 | } 269 | 270 | bool 271 | Reader::parse(const std::string& document, Value& root, bool collectComments) { 272 | document_ = document; 273 | const char* begin = document_.c_str(); 274 | const char* end = begin + document_.length(); 275 | return parse(begin, end, root, collectComments); 276 | } 277 | 278 | bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { 279 | // std::istream_iterator begin(sin); 280 | // std::istream_iterator end; 281 | // Those would allow streamed input from a file, if parse() were a 282 | // template function. 283 | 284 | // Since std::string is reference-counted, this at least does not 285 | // create an extra copy. 286 | std::string doc; 287 | std::getline(sin, doc, (char)EOF); 288 | return parse(doc, root, collectComments); 289 | } 290 | 291 | bool Reader::parse(const char* beginDoc, 292 | const char* endDoc, 293 | Value& root, 294 | bool collectComments) { 295 | if (!features_.allowComments_) { 296 | collectComments = false; 297 | } 298 | 299 | begin_ = beginDoc; 300 | end_ = endDoc; 301 | collectComments_ = collectComments; 302 | current_ = begin_; 303 | lastValueEnd_ = 0; 304 | lastValue_ = 0; 305 | commentsBefore_ = ""; 306 | errors_.clear(); 307 | while (!nodes_.empty()) 308 | nodes_.pop(); 309 | nodes_.push(&root); 310 | 311 | bool successful = readValue(); 312 | Token token; 313 | skipCommentTokens(token); 314 | if (collectComments_ && !commentsBefore_.empty()) 315 | root.setComment(commentsBefore_, commentAfter); 316 | if (features_.strictRoot_) { 317 | if (!root.isArray() && !root.isObject()) { 318 | // Set error location to start of doc, ideally should be first token found 319 | // in doc 320 | token.type_ = tokenError; 321 | token.start_ = beginDoc; 322 | token.end_ = endDoc; 323 | addError( 324 | "A valid JSON document must be either an array or an object value.", 325 | token); 326 | return false; 327 | } 328 | } 329 | return successful; 330 | } 331 | 332 | bool Reader::readValue() { 333 | Token token; 334 | skipCommentTokens(token); 335 | bool successful = true; 336 | 337 | if (collectComments_ && !commentsBefore_.empty()) { 338 | // Remove newline characters at the end of the comments 339 | size_t lastNonNewline = commentsBefore_.find_last_not_of("\r\n"); 340 | if (lastNonNewline != std::string::npos) { 341 | commentsBefore_.erase(lastNonNewline + 1); 342 | } else { 343 | commentsBefore_.clear(); 344 | } 345 | 346 | currentValue().setComment(commentsBefore_, commentBefore); 347 | commentsBefore_ = ""; 348 | } 349 | 350 | switch (token.type_) { 351 | case tokenObjectBegin: 352 | successful = readObject(token); 353 | currentValue().setOffsetLimit(current_ - begin_); 354 | break; 355 | case tokenArrayBegin: 356 | successful = readArray(token); 357 | currentValue().setOffsetLimit(current_ - begin_); 358 | break; 359 | case tokenNumber: 360 | successful = decodeNumber(token); 361 | break; 362 | case tokenString: 363 | successful = decodeString(token); 364 | break; 365 | case tokenTrue: 366 | currentValue() = true; 367 | currentValue().setOffsetStart(token.start_ - begin_); 368 | currentValue().setOffsetLimit(token.end_ - begin_); 369 | break; 370 | case tokenFalse: 371 | currentValue() = false; 372 | currentValue().setOffsetStart(token.start_ - begin_); 373 | currentValue().setOffsetLimit(token.end_ - begin_); 374 | break; 375 | case tokenNull: 376 | currentValue() = Value(); 377 | currentValue().setOffsetStart(token.start_ - begin_); 378 | currentValue().setOffsetLimit(token.end_ - begin_); 379 | break; 380 | case tokenArraySeparator: 381 | if (features_.allowDroppedNullPlaceholders_) { 382 | // "Un-read" the current token and mark the current value as a null 383 | // token. 384 | current_--; 385 | currentValue() = Value(); 386 | currentValue().setOffsetStart(current_ - begin_ - 1); 387 | currentValue().setOffsetLimit(current_ - begin_); 388 | break; 389 | } 390 | // Else, fall through... 391 | default: 392 | currentValue().setOffsetStart(token.start_ - begin_); 393 | currentValue().setOffsetLimit(token.end_ - begin_); 394 | return addError("Syntax error: value, object or array expected.", token); 395 | } 396 | 397 | if (collectComments_) { 398 | lastValueEnd_ = current_; 399 | lastValue_ = ¤tValue(); 400 | } 401 | 402 | return successful; 403 | } 404 | 405 | void Reader::skipCommentTokens(Token& token) { 406 | if (features_.allowComments_) { 407 | do { 408 | readToken(token); 409 | } while (token.type_ == tokenComment); 410 | } else { 411 | readToken(token); 412 | } 413 | } 414 | 415 | bool Reader::expectToken(TokenType type, Token& token, const char* message) { 416 | readToken(token); 417 | if (token.type_ != type) 418 | return addError(message, token); 419 | return true; 420 | } 421 | 422 | bool Reader::readToken(Token& token) { 423 | skipSpaces(); 424 | token.start_ = current_; 425 | Char c = getNextChar(); 426 | bool ok = true; 427 | switch (c) { 428 | case '{': 429 | token.type_ = tokenObjectBegin; 430 | break; 431 | case '}': 432 | token.type_ = tokenObjectEnd; 433 | break; 434 | case '[': 435 | token.type_ = tokenArrayBegin; 436 | break; 437 | case ']': 438 | token.type_ = tokenArrayEnd; 439 | break; 440 | case '"': 441 | token.type_ = tokenString; 442 | ok = readString(); 443 | break; 444 | case '/': 445 | token.type_ = tokenComment; 446 | ok = readComment(); 447 | break; 448 | case '0': 449 | case '1': 450 | case '2': 451 | case '3': 452 | case '4': 453 | case '5': 454 | case '6': 455 | case '7': 456 | case '8': 457 | case '9': 458 | case '-': 459 | token.type_ = tokenNumber; 460 | readNumber(); 461 | break; 462 | case 't': 463 | token.type_ = tokenTrue; 464 | ok = match("rue", 3); 465 | break; 466 | case 'f': 467 | token.type_ = tokenFalse; 468 | ok = match("alse", 4); 469 | break; 470 | case 'n': 471 | token.type_ = tokenNull; 472 | ok = match("ull", 3); 473 | break; 474 | case ',': 475 | token.type_ = tokenArraySeparator; 476 | break; 477 | case ':': 478 | token.type_ = tokenMemberSeparator; 479 | break; 480 | case 0: 481 | token.type_ = tokenEndOfStream; 482 | break; 483 | default: 484 | ok = false; 485 | break; 486 | } 487 | if (!ok) 488 | token.type_ = tokenError; 489 | token.end_ = current_; 490 | return true; 491 | } 492 | 493 | void Reader::skipSpaces() { 494 | while (current_ != end_) { 495 | Char c = *current_; 496 | if (c == ' ' || c == '\t' || c == '\r' || c == '\n') 497 | ++current_; 498 | else 499 | break; 500 | } 501 | } 502 | 503 | bool Reader::match(Location pattern, int patternLength) { 504 | if (end_ - current_ < patternLength) 505 | return false; 506 | int index = patternLength; 507 | while (index--) 508 | if (current_[index] != pattern[index]) 509 | return false; 510 | current_ += patternLength; 511 | return true; 512 | } 513 | 514 | bool Reader::readComment() { 515 | Location commentBegin = current_ - 1; 516 | Char c = getNextChar(); 517 | bool successful = false; 518 | if (c == '*') 519 | successful = readCStyleComment(); 520 | else if (c == '/') 521 | successful = readCppStyleComment(); 522 | if (!successful) 523 | return false; 524 | 525 | if (collectComments_) { 526 | CommentPlacement placement = commentBefore; 527 | if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { 528 | if (c != '*' || !containsNewLine(commentBegin, current_)) 529 | placement = commentAfterOnSameLine; 530 | } 531 | 532 | addComment(commentBegin, current_, placement); 533 | } 534 | return true; 535 | } 536 | 537 | void 538 | Reader::addComment(Location begin, Location end, CommentPlacement placement) { 539 | assert(collectComments_); 540 | if (placement == commentAfterOnSameLine) { 541 | assert(lastValue_ != 0); 542 | lastValue_->setComment(std::string(begin, end), placement); 543 | } else { 544 | commentsBefore_ += std::string(begin, end); 545 | } 546 | } 547 | 548 | bool Reader::readCStyleComment() { 549 | while (current_ != end_) { 550 | Char c = getNextChar(); 551 | if (c == '*' && *current_ == '/') 552 | break; 553 | } 554 | return getNextChar() == '/'; 555 | } 556 | 557 | bool Reader::readCppStyleComment() { 558 | while (current_ != end_) { 559 | Char c = getNextChar(); 560 | if (c == '\r' || c == '\n') 561 | break; 562 | } 563 | return true; 564 | } 565 | 566 | void Reader::readNumber() { 567 | while (current_ != end_) { 568 | if (!(*current_ >= '0' && *current_ <= '9') && 569 | !in(*current_, '.', 'e', 'E', '+', '-')) 570 | break; 571 | ++current_; 572 | } 573 | } 574 | 575 | bool Reader::readString() { 576 | Char c = 0; 577 | while (current_ != end_) { 578 | c = getNextChar(); 579 | if (c == '\\') 580 | getNextChar(); 581 | else if (c == '"') 582 | break; 583 | } 584 | return c == '"'; 585 | } 586 | 587 | bool Reader::readObject(Token& tokenStart) { 588 | Token tokenName; 589 | std::string name; 590 | currentValue() = Value(objectValue); 591 | currentValue().setOffsetStart(tokenStart.start_ - begin_); 592 | while (readToken(tokenName)) { 593 | bool initialTokenOk = true; 594 | while (tokenName.type_ == tokenComment && initialTokenOk) 595 | initialTokenOk = readToken(tokenName); 596 | if (!initialTokenOk) 597 | break; 598 | if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object 599 | return true; 600 | name = ""; 601 | if (tokenName.type_ == tokenString) { 602 | if (!decodeString(tokenName, name)) 603 | return recoverFromError(tokenObjectEnd); 604 | } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { 605 | Value numberName; 606 | if (!decodeNumber(tokenName, numberName)) 607 | return recoverFromError(tokenObjectEnd); 608 | name = numberName.asString(); 609 | } else { 610 | break; 611 | } 612 | 613 | Token colon; 614 | if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { 615 | return addErrorAndRecover( 616 | "Missing ':' after object member name", colon, tokenObjectEnd); 617 | } 618 | Value& value = currentValue()[name]; 619 | nodes_.push(&value); 620 | bool ok = readValue(); 621 | nodes_.pop(); 622 | if (!ok) // error already set 623 | return recoverFromError(tokenObjectEnd); 624 | 625 | Token comma; 626 | if (!readToken(comma) || 627 | (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && 628 | comma.type_ != tokenComment)) { 629 | return addErrorAndRecover( 630 | "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); 631 | } 632 | bool finalizeTokenOk = true; 633 | while (comma.type_ == tokenComment && finalizeTokenOk) 634 | finalizeTokenOk = readToken(comma); 635 | if (comma.type_ == tokenObjectEnd) 636 | return true; 637 | } 638 | return addErrorAndRecover( 639 | "Missing '}' or object member name", tokenName, tokenObjectEnd); 640 | } 641 | 642 | bool Reader::readArray(Token& tokenStart) { 643 | currentValue() = Value(arrayValue); 644 | currentValue().setOffsetStart(tokenStart.start_ - begin_); 645 | skipSpaces(); 646 | if (*current_ == ']') // empty array 647 | { 648 | Token endArray; 649 | readToken(endArray); 650 | return true; 651 | } 652 | int index = 0; 653 | for (;;) { 654 | Value& value = currentValue()[index++]; 655 | nodes_.push(&value); 656 | bool ok = readValue(); 657 | nodes_.pop(); 658 | if (!ok) // error already set 659 | return recoverFromError(tokenArrayEnd); 660 | 661 | Token token; 662 | // Accept Comment after last item in the array. 663 | ok = readToken(token); 664 | while (token.type_ == tokenComment && ok) { 665 | ok = readToken(token); 666 | } 667 | bool badTokenType = 668 | (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); 669 | if (!ok || badTokenType) { 670 | return addErrorAndRecover( 671 | "Missing ',' or ']' in array declaration", token, tokenArrayEnd); 672 | } 673 | if (token.type_ == tokenArrayEnd) 674 | break; 675 | } 676 | return true; 677 | } 678 | 679 | bool Reader::decodeNumber(Token& token) { 680 | Value decoded; 681 | if (!decodeNumber(token, decoded)) 682 | return false; 683 | currentValue() = decoded; 684 | currentValue().setOffsetStart(token.start_ - begin_); 685 | currentValue().setOffsetLimit(token.end_ - begin_); 686 | return true; 687 | } 688 | 689 | bool Reader::decodeNumber(Token& token, Value& decoded) { 690 | bool isDouble = false; 691 | for (Location inspect = token.start_; inspect != token.end_; ++inspect) { 692 | isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') || 693 | (*inspect == '-' && inspect != token.start_); 694 | } 695 | if (isDouble) 696 | return decodeDouble(token, decoded); 697 | // Attempts to parse the number as an integer. If the number is 698 | // larger than the maximum supported value of an integer then 699 | // we decode the number as a double. 700 | Location current = token.start_; 701 | bool isNegative = *current == '-'; 702 | if (isNegative) 703 | ++current; 704 | Value::LargestUInt maxIntegerValue = 705 | isNegative ? Value::LargestUInt(-Value::minLargestInt) 706 | : Value::maxLargestUInt; 707 | Value::LargestUInt threshold = maxIntegerValue / 10; 708 | Value::LargestUInt value = 0; 709 | while (current < token.end_) { 710 | Char c = *current++; 711 | if (c < '0' || c > '9') 712 | return addError("'" + std::string(token.start_, token.end_) + 713 | "' is not a number.", 714 | token); 715 | Value::UInt digit(c - '0'); 716 | if (value >= threshold) { 717 | // We've hit or exceeded the max value divided by 10 (rounded down). If 718 | // a) we've only just touched the limit, b) this is the last digit, and 719 | // c) it's small enough to fit in that rounding delta, we're okay. 720 | // Otherwise treat this number as a double to avoid overflow. 721 | if (value > threshold || current != token.end_ || 722 | digit > maxIntegerValue % 10) { 723 | return decodeDouble(token, decoded); 724 | } 725 | } 726 | value = value * 10 + digit; 727 | } 728 | if (isNegative) 729 | decoded = -Value::LargestInt(value); 730 | else if (value <= Value::LargestUInt(Value::maxInt)) 731 | decoded = Value::LargestInt(value); 732 | else 733 | decoded = value; 734 | return true; 735 | } 736 | 737 | bool Reader::decodeDouble(Token& token) { 738 | Value decoded; 739 | if (!decodeDouble(token, decoded)) 740 | return false; 741 | currentValue() = decoded; 742 | currentValue().setOffsetStart(token.start_ - begin_); 743 | currentValue().setOffsetLimit(token.end_ - begin_); 744 | return true; 745 | } 746 | 747 | bool Reader::decodeDouble(Token& token, Value& decoded) { 748 | double value = 0; 749 | const int bufferSize = 32; 750 | int count; 751 | int length = int(token.end_ - token.start_); 752 | 753 | // Sanity check to avoid buffer overflow exploits. 754 | if (length < 0) { 755 | return addError("Unable to parse token length", token); 756 | } 757 | 758 | // Avoid using a string constant for the format control string given to 759 | // sscanf, as this can cause hard to debug crashes on OS X. See here for more 760 | // info: 761 | // 762 | // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html 763 | char format[] = "%lf"; 764 | 765 | if (length <= bufferSize) { 766 | Char buffer[bufferSize + 1]; 767 | memcpy(buffer, token.start_, length); 768 | buffer[length] = 0; 769 | count = sscanf(buffer, format, &value); 770 | } else { 771 | std::string buffer(token.start_, token.end_); 772 | count = sscanf(buffer.c_str(), format, &value); 773 | } 774 | 775 | if (count != 1) 776 | return addError("'" + std::string(token.start_, token.end_) + 777 | "' is not a number.", 778 | token); 779 | decoded = value; 780 | return true; 781 | } 782 | 783 | bool Reader::decodeString(Token& token) { 784 | std::string decoded; 785 | if (!decodeString(token, decoded)) 786 | return false; 787 | currentValue() = decoded; 788 | currentValue().setOffsetStart(token.start_ - begin_); 789 | currentValue().setOffsetLimit(token.end_ - begin_); 790 | return true; 791 | } 792 | 793 | bool Reader::decodeString(Token& token, std::string& decoded) { 794 | decoded.reserve(token.end_ - token.start_ - 2); 795 | Location current = token.start_ + 1; // skip '"' 796 | Location end = token.end_ - 1; // do not include '"' 797 | while (current != end) { 798 | Char c = *current++; 799 | if (c == '"') 800 | break; 801 | else if (c == '\\') { 802 | if (current == end) 803 | return addError("Empty escape sequence in string", token, current); 804 | Char escape = *current++; 805 | switch (escape) { 806 | case '"': 807 | decoded += '"'; 808 | break; 809 | case '/': 810 | decoded += '/'; 811 | break; 812 | case '\\': 813 | decoded += '\\'; 814 | break; 815 | case 'b': 816 | decoded += '\b'; 817 | break; 818 | case 'f': 819 | decoded += '\f'; 820 | break; 821 | case 'n': 822 | decoded += '\n'; 823 | break; 824 | case 'r': 825 | decoded += '\r'; 826 | break; 827 | case 't': 828 | decoded += '\t'; 829 | break; 830 | case 'u': { 831 | unsigned int unicode; 832 | if (!decodeUnicodeCodePoint(token, current, end, unicode)) 833 | return false; 834 | decoded += codePointToUTF8(unicode); 835 | } break; 836 | default: 837 | return addError("Bad escape sequence in string", token, current); 838 | } 839 | } else { 840 | decoded += c; 841 | } 842 | } 843 | return true; 844 | } 845 | 846 | bool Reader::decodeUnicodeCodePoint(Token& token, 847 | Location& current, 848 | Location end, 849 | unsigned int& unicode) { 850 | 851 | if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) 852 | return false; 853 | if (unicode >= 0xD800 && unicode <= 0xDBFF) { 854 | // surrogate pairs 855 | if (end - current < 6) 856 | return addError( 857 | "additional six characters expected to parse unicode surrogate pair.", 858 | token, 859 | current); 860 | unsigned int surrogatePair; 861 | if (*(current++) == '\\' && *(current++) == 'u') { 862 | if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { 863 | unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); 864 | } else 865 | return false; 866 | } else 867 | return addError("expecting another \\u token to begin the second half of " 868 | "a unicode surrogate pair", 869 | token, 870 | current); 871 | } 872 | return true; 873 | } 874 | 875 | bool Reader::decodeUnicodeEscapeSequence(Token& token, 876 | Location& current, 877 | Location end, 878 | unsigned int& unicode) { 879 | if (end - current < 4) 880 | return addError( 881 | "Bad unicode escape sequence in string: four digits expected.", 882 | token, 883 | current); 884 | unicode = 0; 885 | for (int index = 0; index < 4; ++index) { 886 | Char c = *current++; 887 | unicode *= 16; 888 | if (c >= '0' && c <= '9') 889 | unicode += c - '0'; 890 | else if (c >= 'a' && c <= 'f') 891 | unicode += c - 'a' + 10; 892 | else if (c >= 'A' && c <= 'F') 893 | unicode += c - 'A' + 10; 894 | else 895 | return addError( 896 | "Bad unicode escape sequence in string: hexadecimal digit expected.", 897 | token, 898 | current); 899 | } 900 | return true; 901 | } 902 | 903 | bool 904 | Reader::addError(const std::string& message, Token& token, Location extra) { 905 | ErrorInfo info; 906 | info.token_ = token; 907 | info.message_ = message; 908 | info.extra_ = extra; 909 | errors_.push_back(info); 910 | return false; 911 | } 912 | 913 | bool Reader::recoverFromError(TokenType skipUntilToken) { 914 | int errorCount = int(errors_.size()); 915 | Token skip; 916 | for (;;) { 917 | if (!readToken(skip)) 918 | errors_.resize(errorCount); // discard errors caused by recovery 919 | if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) 920 | break; 921 | } 922 | errors_.resize(errorCount); 923 | return false; 924 | } 925 | 926 | bool Reader::addErrorAndRecover(const std::string& message, 927 | Token& token, 928 | TokenType skipUntilToken) { 929 | addError(message, token); 930 | return recoverFromError(skipUntilToken); 931 | } 932 | 933 | Value& Reader::currentValue() { return *(nodes_.top()); } 934 | 935 | Reader::Char Reader::getNextChar() { 936 | if (current_ == end_) 937 | return 0; 938 | return *current_++; 939 | } 940 | 941 | void Reader::getLocationLineAndColumn(Location location, 942 | int& line, 943 | int& column) const { 944 | Location current = begin_; 945 | Location lastLineStart = current; 946 | line = 0; 947 | while (current < location && current != end_) { 948 | Char c = *current++; 949 | if (c == '\r') { 950 | if (*current == '\n') 951 | ++current; 952 | lastLineStart = current; 953 | ++line; 954 | } else if (c == '\n') { 955 | lastLineStart = current; 956 | ++line; 957 | } 958 | } 959 | // column & line start at 1 960 | column = int(location - lastLineStart) + 1; 961 | ++line; 962 | } 963 | 964 | std::string Reader::getLocationLineAndColumn(Location location) const { 965 | int line, column; 966 | getLocationLineAndColumn(location, line, column); 967 | char buffer[18 + 16 + 16 + 1]; 968 | #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) 969 | #if defined(WINCE) 970 | _snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); 971 | #else 972 | sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column); 973 | #endif 974 | #else 975 | snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); 976 | #endif 977 | return buffer; 978 | } 979 | 980 | // Deprecated. Preserved for backward compatibility 981 | std::string Reader::getFormatedErrorMessages() const { 982 | return getFormattedErrorMessages(); 983 | } 984 | 985 | std::string Reader::getFormattedErrorMessages() const { 986 | std::string formattedMessage; 987 | for (Errors::const_iterator itError = errors_.begin(); 988 | itError != errors_.end(); 989 | ++itError) { 990 | const ErrorInfo& error = *itError; 991 | formattedMessage += 992 | "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; 993 | formattedMessage += " " + error.message_ + "\n"; 994 | if (error.extra_) 995 | formattedMessage += 996 | "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; 997 | } 998 | return formattedMessage; 999 | } 1000 | 1001 | std::vector Reader::getStructuredErrors() const { 1002 | std::vector allErrors; 1003 | for (Errors::const_iterator itError = errors_.begin(); 1004 | itError != errors_.end(); 1005 | ++itError) { 1006 | const ErrorInfo& error = *itError; 1007 | Reader::StructuredError structured; 1008 | structured.offset_start = error.token_.start_ - begin_; 1009 | structured.offset_limit = error.token_.end_ - begin_; 1010 | structured.message = error.message_; 1011 | allErrors.push_back(structured); 1012 | } 1013 | return allErrors; 1014 | } 1015 | 1016 | std::istream& operator>>(std::istream& sin, Value& root) { 1017 | Json::Reader reader; 1018 | bool ok = reader.parse(sin, root, true); 1019 | if (!ok) { 1020 | fprintf(stderr, 1021 | "Error from reader: %s", 1022 | reader.getFormattedErrorMessages().c_str()); 1023 | 1024 | JSON_FAIL_MESSAGE("reader error"); 1025 | } 1026 | return sin; 1027 | } 1028 | 1029 | } // namespace Json 1030 | 1031 | // ////////////////////////////////////////////////////////////////////// 1032 | // End of content of file: src/lib_json/json_reader.cpp 1033 | // ////////////////////////////////////////////////////////////////////// 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | // ////////////////////////////////////////////////////////////////////// 1041 | // Beginning of content of file: src/lib_json/json_batchallocator.h 1042 | // ////////////////////////////////////////////////////////////////////// 1043 | 1044 | // Copyright 2007-2010 Baptiste Lepilleur 1045 | // Distributed under MIT license, or public domain if desired and 1046 | // recognized in your jurisdiction. 1047 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 1048 | 1049 | #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED 1050 | #define JSONCPP_BATCHALLOCATOR_H_INCLUDED 1051 | 1052 | #include 1053 | #include 1054 | 1055 | #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 1056 | 1057 | namespace Json { 1058 | 1059 | /* Fast memory allocator. 1060 | * 1061 | * This memory allocator allocates memory for a batch of object (specified by 1062 | * the page size, the number of object in each page). 1063 | * 1064 | * It does not allow the destruction of a single object. All the allocated 1065 | * objects can be destroyed at once. The memory can be either released or reused 1066 | * for future allocation. 1067 | * 1068 | * The in-place new operator must be used to construct the object using the 1069 | * pointer returned by allocate. 1070 | */ 1071 | template 1072 | class BatchAllocator { 1073 | public: 1074 | BatchAllocator(unsigned int objectsPerPage = 255) 1075 | : freeHead_(0), objectsPerPage_(objectsPerPage) { 1076 | // printf( "Size: %d => %s\n", sizeof(AllocatedType), 1077 | // typeid(AllocatedType).name() ); 1078 | assert(sizeof(AllocatedType) * objectPerAllocation >= 1079 | sizeof(AllocatedType*)); // We must be able to store a slist in the 1080 | // object free space. 1081 | assert(objectsPerPage >= 16); 1082 | batches_ = allocateBatch(0); // allocated a dummy page 1083 | currentBatch_ = batches_; 1084 | } 1085 | 1086 | ~BatchAllocator() { 1087 | for (BatchInfo* batch = batches_; batch;) { 1088 | BatchInfo* nextBatch = batch->next_; 1089 | free(batch); 1090 | batch = nextBatch; 1091 | } 1092 | } 1093 | 1094 | /// allocate space for an array of objectPerAllocation object. 1095 | /// @warning it is the responsability of the caller to call objects 1096 | /// constructors. 1097 | AllocatedType* allocate() { 1098 | if (freeHead_) // returns node from free list. 1099 | { 1100 | AllocatedType* object = freeHead_; 1101 | freeHead_ = *(AllocatedType**)object; 1102 | return object; 1103 | } 1104 | if (currentBatch_->used_ == currentBatch_->end_) { 1105 | currentBatch_ = currentBatch_->next_; 1106 | while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_) 1107 | currentBatch_ = currentBatch_->next_; 1108 | 1109 | if (!currentBatch_) // no free batch found, allocate a new one 1110 | { 1111 | currentBatch_ = allocateBatch(objectsPerPage_); 1112 | currentBatch_->next_ = batches_; // insert at the head of the list 1113 | batches_ = currentBatch_; 1114 | } 1115 | } 1116 | AllocatedType* allocated = currentBatch_->used_; 1117 | currentBatch_->used_ += objectPerAllocation; 1118 | return allocated; 1119 | } 1120 | 1121 | /// Release the object. 1122 | /// @warning it is the responsability of the caller to actually destruct the 1123 | /// object. 1124 | void release(AllocatedType* object) { 1125 | assert(object != 0); 1126 | *(AllocatedType**)object = freeHead_; 1127 | freeHead_ = object; 1128 | } 1129 | 1130 | private: 1131 | struct BatchInfo { 1132 | BatchInfo* next_; 1133 | AllocatedType* used_; 1134 | AllocatedType* end_; 1135 | AllocatedType buffer_[objectPerAllocation]; 1136 | }; 1137 | 1138 | // disabled copy constructor and assignement operator. 1139 | BatchAllocator(const BatchAllocator&); 1140 | void operator=(const BatchAllocator&); 1141 | 1142 | static BatchInfo* allocateBatch(unsigned int objectsPerPage) { 1143 | const unsigned int mallocSize = 1144 | sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation + 1145 | sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; 1146 | BatchInfo* batch = static_cast(malloc(mallocSize)); 1147 | batch->next_ = 0; 1148 | batch->used_ = batch->buffer_; 1149 | batch->end_ = batch->buffer_ + objectsPerPage; 1150 | return batch; 1151 | } 1152 | 1153 | BatchInfo* batches_; 1154 | BatchInfo* currentBatch_; 1155 | /// Head of a single linked list within the allocated space of freeed object 1156 | AllocatedType* freeHead_; 1157 | unsigned int objectsPerPage_; 1158 | }; 1159 | 1160 | } // namespace Json 1161 | 1162 | #endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION 1163 | 1164 | #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED 1165 | 1166 | // ////////////////////////////////////////////////////////////////////// 1167 | // End of content of file: src/lib_json/json_batchallocator.h 1168 | // ////////////////////////////////////////////////////////////////////// 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | // ////////////////////////////////////////////////////////////////////// 1176 | // Beginning of content of file: src/lib_json/json_valueiterator.inl 1177 | // ////////////////////////////////////////////////////////////////////// 1178 | 1179 | // Copyright 2007-2010 Baptiste Lepilleur 1180 | // Distributed under MIT license, or public domain if desired and 1181 | // recognized in your jurisdiction. 1182 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 1183 | 1184 | // included by json_value.cpp 1185 | 1186 | namespace Json { 1187 | 1188 | // ////////////////////////////////////////////////////////////////// 1189 | // ////////////////////////////////////////////////////////////////// 1190 | // ////////////////////////////////////////////////////////////////// 1191 | // class ValueIteratorBase 1192 | // ////////////////////////////////////////////////////////////////// 1193 | // ////////////////////////////////////////////////////////////////// 1194 | // ////////////////////////////////////////////////////////////////// 1195 | 1196 | ValueIteratorBase::ValueIteratorBase() 1197 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1198 | : current_(), isNull_(true) { 1199 | } 1200 | #else 1201 | : isArray_(true), isNull_(true) { 1202 | iterator_.array_ = ValueInternalArray::IteratorState(); 1203 | } 1204 | #endif 1205 | 1206 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1207 | ValueIteratorBase::ValueIteratorBase( 1208 | const Value::ObjectValues::iterator& current) 1209 | : current_(current), isNull_(false) {} 1210 | #else 1211 | ValueIteratorBase::ValueIteratorBase( 1212 | const ValueInternalArray::IteratorState& state) 1213 | : isArray_(true) { 1214 | iterator_.array_ = state; 1215 | } 1216 | 1217 | ValueIteratorBase::ValueIteratorBase( 1218 | const ValueInternalMap::IteratorState& state) 1219 | : isArray_(false) { 1220 | iterator_.map_ = state; 1221 | } 1222 | #endif 1223 | 1224 | Value& ValueIteratorBase::deref() const { 1225 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1226 | return current_->second; 1227 | #else 1228 | if (isArray_) 1229 | return ValueInternalArray::dereference(iterator_.array_); 1230 | return ValueInternalMap::value(iterator_.map_); 1231 | #endif 1232 | } 1233 | 1234 | void ValueIteratorBase::increment() { 1235 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1236 | ++current_; 1237 | #else 1238 | if (isArray_) 1239 | ValueInternalArray::increment(iterator_.array_); 1240 | ValueInternalMap::increment(iterator_.map_); 1241 | #endif 1242 | } 1243 | 1244 | void ValueIteratorBase::decrement() { 1245 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1246 | --current_; 1247 | #else 1248 | if (isArray_) 1249 | ValueInternalArray::decrement(iterator_.array_); 1250 | ValueInternalMap::decrement(iterator_.map_); 1251 | #endif 1252 | } 1253 | 1254 | ValueIteratorBase::difference_type 1255 | ValueIteratorBase::computeDistance(const SelfType& other) const { 1256 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1257 | #ifdef JSON_USE_CPPTL_SMALLMAP 1258 | return current_ - other.current_; 1259 | #else 1260 | // Iterator for null value are initialized using the default 1261 | // constructor, which initialize current_ to the default 1262 | // std::map::iterator. As begin() and end() are two instance 1263 | // of the default std::map::iterator, they can not be compared. 1264 | // To allow this, we handle this comparison specifically. 1265 | if (isNull_ && other.isNull_) { 1266 | return 0; 1267 | } 1268 | 1269 | // Usage of std::distance is not portable (does not compile with Sun Studio 12 1270 | // RogueWave STL, 1271 | // which is the one used by default). 1272 | // Using a portable hand-made version for non random iterator instead: 1273 | // return difference_type( std::distance( current_, other.current_ ) ); 1274 | difference_type myDistance = 0; 1275 | for (Value::ObjectValues::iterator it = current_; it != other.current_; 1276 | ++it) { 1277 | ++myDistance; 1278 | } 1279 | return myDistance; 1280 | #endif 1281 | #else 1282 | if (isArray_) 1283 | return ValueInternalArray::distance(iterator_.array_, 1284 | other.iterator_.array_); 1285 | return ValueInternalMap::distance(iterator_.map_, other.iterator_.map_); 1286 | #endif 1287 | } 1288 | 1289 | bool ValueIteratorBase::isEqual(const SelfType& other) const { 1290 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1291 | if (isNull_) { 1292 | return other.isNull_; 1293 | } 1294 | return current_ == other.current_; 1295 | #else 1296 | if (isArray_) 1297 | return ValueInternalArray::equals(iterator_.array_, other.iterator_.array_); 1298 | return ValueInternalMap::equals(iterator_.map_, other.iterator_.map_); 1299 | #endif 1300 | } 1301 | 1302 | void ValueIteratorBase::copy(const SelfType& other) { 1303 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1304 | current_ = other.current_; 1305 | isNull_ = other.isNull_; 1306 | #else 1307 | if (isArray_) 1308 | iterator_.array_ = other.iterator_.array_; 1309 | iterator_.map_ = other.iterator_.map_; 1310 | #endif 1311 | } 1312 | 1313 | Value ValueIteratorBase::key() const { 1314 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1315 | const Value::CZString czstring = (*current_).first; 1316 | if (czstring.c_str()) { 1317 | if (czstring.isStaticString()) 1318 | return Value(StaticString(czstring.c_str())); 1319 | return Value(czstring.c_str()); 1320 | } 1321 | return Value(czstring.index()); 1322 | #else 1323 | if (isArray_) 1324 | return Value(ValueInternalArray::indexOf(iterator_.array_)); 1325 | bool isStatic; 1326 | const char* memberName = ValueInternalMap::key(iterator_.map_, isStatic); 1327 | if (isStatic) 1328 | return Value(StaticString(memberName)); 1329 | return Value(memberName); 1330 | #endif 1331 | } 1332 | 1333 | UInt ValueIteratorBase::index() const { 1334 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1335 | const Value::CZString czstring = (*current_).first; 1336 | if (!czstring.c_str()) 1337 | return czstring.index(); 1338 | return Value::UInt(-1); 1339 | #else 1340 | if (isArray_) 1341 | return Value::UInt(ValueInternalArray::indexOf(iterator_.array_)); 1342 | return Value::UInt(-1); 1343 | #endif 1344 | } 1345 | 1346 | const char* ValueIteratorBase::memberName() const { 1347 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1348 | const char* name = (*current_).first.c_str(); 1349 | return name ? name : ""; 1350 | #else 1351 | if (!isArray_) 1352 | return ValueInternalMap::key(iterator_.map_); 1353 | return ""; 1354 | #endif 1355 | } 1356 | 1357 | // ////////////////////////////////////////////////////////////////// 1358 | // ////////////////////////////////////////////////////////////////// 1359 | // ////////////////////////////////////////////////////////////////// 1360 | // class ValueConstIterator 1361 | // ////////////////////////////////////////////////////////////////// 1362 | // ////////////////////////////////////////////////////////////////// 1363 | // ////////////////////////////////////////////////////////////////// 1364 | 1365 | ValueConstIterator::ValueConstIterator() {} 1366 | 1367 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1368 | ValueConstIterator::ValueConstIterator( 1369 | const Value::ObjectValues::iterator& current) 1370 | : ValueIteratorBase(current) {} 1371 | #else 1372 | ValueConstIterator::ValueConstIterator( 1373 | const ValueInternalArray::IteratorState& state) 1374 | : ValueIteratorBase(state) {} 1375 | 1376 | ValueConstIterator::ValueConstIterator( 1377 | const ValueInternalMap::IteratorState& state) 1378 | : ValueIteratorBase(state) {} 1379 | #endif 1380 | 1381 | ValueConstIterator& ValueConstIterator:: 1382 | operator=(const ValueIteratorBase& other) { 1383 | copy(other); 1384 | return *this; 1385 | } 1386 | 1387 | // ////////////////////////////////////////////////////////////////// 1388 | // ////////////////////////////////////////////////////////////////// 1389 | // ////////////////////////////////////////////////////////////////// 1390 | // class ValueIterator 1391 | // ////////////////////////////////////////////////////////////////// 1392 | // ////////////////////////////////////////////////////////////////// 1393 | // ////////////////////////////////////////////////////////////////// 1394 | 1395 | ValueIterator::ValueIterator() {} 1396 | 1397 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1398 | ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) 1399 | : ValueIteratorBase(current) {} 1400 | #else 1401 | ValueIterator::ValueIterator(const ValueInternalArray::IteratorState& state) 1402 | : ValueIteratorBase(state) {} 1403 | 1404 | ValueIterator::ValueIterator(const ValueInternalMap::IteratorState& state) 1405 | : ValueIteratorBase(state) {} 1406 | #endif 1407 | 1408 | ValueIterator::ValueIterator(const ValueConstIterator& other) 1409 | : ValueIteratorBase(other) {} 1410 | 1411 | ValueIterator::ValueIterator(const ValueIterator& other) 1412 | : ValueIteratorBase(other) {} 1413 | 1414 | ValueIterator& ValueIterator::operator=(const SelfType& other) { 1415 | copy(other); 1416 | return *this; 1417 | } 1418 | 1419 | } // namespace Json 1420 | 1421 | // ////////////////////////////////////////////////////////////////////// 1422 | // End of content of file: src/lib_json/json_valueiterator.inl 1423 | // ////////////////////////////////////////////////////////////////////// 1424 | 1425 | 1426 | 1427 | 1428 | 1429 | 1430 | // ////////////////////////////////////////////////////////////////////// 1431 | // Beginning of content of file: src/lib_json/json_value.cpp 1432 | // ////////////////////////////////////////////////////////////////////// 1433 | 1434 | // Copyright 2011 Baptiste Lepilleur 1435 | // Distributed under MIT license, or public domain if desired and 1436 | // recognized in your jurisdiction. 1437 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 1438 | 1439 | #if !defined(JSON_IS_AMALGAMATION) 1440 | #include 1441 | #include 1442 | #include 1443 | #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1444 | #include "json_batchallocator.h" 1445 | #endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1446 | #endif // if !defined(JSON_IS_AMALGAMATION) 1447 | #include 1448 | #include 1449 | #include 1450 | #include 1451 | #include 1452 | #ifdef JSON_USE_CPPTL 1453 | #include 1454 | #endif 1455 | #include // size_t 1456 | 1457 | #define JSON_ASSERT_UNREACHABLE assert(false) 1458 | 1459 | namespace Json { 1460 | 1461 | // This is a walkaround to avoid the static initialization of Value::null. 1462 | // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of 1463 | // 8 (instead of 4) as a bit of future-proofing. 1464 | #if defined(__ARMEL__) 1465 | #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) 1466 | #else 1467 | #define ALIGNAS(byte_alignment) 1468 | #endif 1469 | static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; 1470 | const unsigned char& kNullRef = kNull[0]; 1471 | const Value& Value::null = reinterpret_cast(kNullRef); 1472 | 1473 | const Int Value::minInt = Int(~(UInt(-1) / 2)); 1474 | const Int Value::maxInt = Int(UInt(-1) / 2); 1475 | const UInt Value::maxUInt = UInt(-1); 1476 | #if defined(JSON_HAS_INT64) 1477 | const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); 1478 | const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); 1479 | const UInt64 Value::maxUInt64 = UInt64(-1); 1480 | // The constant is hard-coded because some compiler have trouble 1481 | // converting Value::maxUInt64 to a double correctly (AIX/xlC). 1482 | // Assumes that UInt64 is a 64 bits integer. 1483 | static const double maxUInt64AsDouble = 18446744073709551615.0; 1484 | #endif // defined(JSON_HAS_INT64) 1485 | const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); 1486 | const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); 1487 | const LargestUInt Value::maxLargestUInt = LargestUInt(-1); 1488 | 1489 | /// Unknown size marker 1490 | static const unsigned int unknown = (unsigned)-1; 1491 | 1492 | #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 1493 | template 1494 | static inline bool InRange(double d, T min, U max) { 1495 | return d >= min && d <= max; 1496 | } 1497 | #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 1498 | static inline double integerToDouble(Json::UInt64 value) { 1499 | return static_cast(Int64(value / 2)) * 2.0 + Int64(value & 1); 1500 | } 1501 | 1502 | template static inline double integerToDouble(T value) { 1503 | return static_cast(value); 1504 | } 1505 | 1506 | template 1507 | static inline bool InRange(double d, T min, U max) { 1508 | return d >= integerToDouble(min) && d <= integerToDouble(max); 1509 | } 1510 | #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 1511 | 1512 | /** Duplicates the specified string value. 1513 | * @param value Pointer to the string to duplicate. Must be zero-terminated if 1514 | * length is "unknown". 1515 | * @param length Length of the value. if equals to unknown, then it will be 1516 | * computed using strlen(value). 1517 | * @return Pointer on the duplicate instance of string. 1518 | */ 1519 | static inline char* duplicateStringValue(const char* value, 1520 | unsigned int length = unknown) { 1521 | if (length == unknown) 1522 | length = (unsigned int)strlen(value); 1523 | 1524 | // Avoid an integer overflow in the call to malloc below by limiting length 1525 | // to a sane value. 1526 | if (length >= (unsigned)Value::maxInt) 1527 | length = Value::maxInt - 1; 1528 | 1529 | char* newString = static_cast(malloc(length + 1)); 1530 | JSON_ASSERT_MESSAGE(newString != 0, 1531 | "in Json::Value::duplicateStringValue(): " 1532 | "Failed to allocate string value buffer"); 1533 | memcpy(newString, value, length); 1534 | newString[length] = 0; 1535 | return newString; 1536 | } 1537 | 1538 | /** Free the string duplicated by duplicateStringValue(). 1539 | */ 1540 | static inline void releaseStringValue(char* value) { free(value); } 1541 | 1542 | } // namespace Json 1543 | 1544 | // ////////////////////////////////////////////////////////////////// 1545 | // ////////////////////////////////////////////////////////////////// 1546 | // ////////////////////////////////////////////////////////////////// 1547 | // ValueInternals... 1548 | // ////////////////////////////////////////////////////////////////// 1549 | // ////////////////////////////////////////////////////////////////// 1550 | // ////////////////////////////////////////////////////////////////// 1551 | #if !defined(JSON_IS_AMALGAMATION) 1552 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1553 | #include "json_internalarray.inl" 1554 | #include "json_internalmap.inl" 1555 | #endif // JSON_VALUE_USE_INTERNAL_MAP 1556 | 1557 | #include "json_valueiterator.inl" 1558 | #endif // if !defined(JSON_IS_AMALGAMATION) 1559 | 1560 | namespace Json { 1561 | 1562 | // ////////////////////////////////////////////////////////////////// 1563 | // ////////////////////////////////////////////////////////////////// 1564 | // ////////////////////////////////////////////////////////////////// 1565 | // class Value::CommentInfo 1566 | // ////////////////////////////////////////////////////////////////// 1567 | // ////////////////////////////////////////////////////////////////// 1568 | // ////////////////////////////////////////////////////////////////// 1569 | 1570 | Value::CommentInfo::CommentInfo() : comment_(0) {} 1571 | 1572 | Value::CommentInfo::~CommentInfo() { 1573 | if (comment_) 1574 | releaseStringValue(comment_); 1575 | } 1576 | 1577 | void Value::CommentInfo::setComment(const char* text) { 1578 | if (comment_) 1579 | releaseStringValue(comment_); 1580 | JSON_ASSERT(text != 0); 1581 | JSON_ASSERT_MESSAGE( 1582 | text[0] == '\0' || text[0] == '/', 1583 | "in Json::Value::setComment(): Comments must start with /"); 1584 | // It seems that /**/ style comments are acceptable as well. 1585 | comment_ = duplicateStringValue(text); 1586 | } 1587 | 1588 | // ////////////////////////////////////////////////////////////////// 1589 | // ////////////////////////////////////////////////////////////////// 1590 | // ////////////////////////////////////////////////////////////////// 1591 | // class Value::CZString 1592 | // ////////////////////////////////////////////////////////////////// 1593 | // ////////////////////////////////////////////////////////////////// 1594 | // ////////////////////////////////////////////////////////////////// 1595 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1596 | 1597 | // Notes: index_ indicates if the string was allocated when 1598 | // a string is stored. 1599 | 1600 | Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} 1601 | 1602 | Value::CZString::CZString(const char* cstr, DuplicationPolicy allocate) 1603 | : cstr_(allocate == duplicate ? duplicateStringValue(cstr) : cstr), 1604 | index_(allocate) {} 1605 | 1606 | Value::CZString::CZString(const CZString& other) 1607 | : cstr_(other.index_ != noDuplication && other.cstr_ != 0 1608 | ? duplicateStringValue(other.cstr_) 1609 | : other.cstr_), 1610 | index_(other.cstr_ 1611 | ? (other.index_ == noDuplication ? noDuplication : duplicate) 1612 | : other.index_) {} 1613 | 1614 | Value::CZString::~CZString() { 1615 | if (cstr_ && index_ == duplicate) 1616 | releaseStringValue(const_cast(cstr_)); 1617 | } 1618 | 1619 | void Value::CZString::swap(CZString& other) { 1620 | std::swap(cstr_, other.cstr_); 1621 | std::swap(index_, other.index_); 1622 | } 1623 | 1624 | Value::CZString& Value::CZString::operator=(CZString other) { 1625 | swap(other); 1626 | return *this; 1627 | } 1628 | 1629 | bool Value::CZString::operator<(const CZString& other) const { 1630 | if (cstr_) 1631 | return strcmp(cstr_, other.cstr_) < 0; 1632 | return index_ < other.index_; 1633 | } 1634 | 1635 | bool Value::CZString::operator==(const CZString& other) const { 1636 | if (cstr_) 1637 | return strcmp(cstr_, other.cstr_) == 0; 1638 | return index_ == other.index_; 1639 | } 1640 | 1641 | ArrayIndex Value::CZString::index() const { return index_; } 1642 | 1643 | const char* Value::CZString::c_str() const { return cstr_; } 1644 | 1645 | bool Value::CZString::isStaticString() const { return index_ == noDuplication; } 1646 | 1647 | #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP 1648 | 1649 | // ////////////////////////////////////////////////////////////////// 1650 | // ////////////////////////////////////////////////////////////////// 1651 | // ////////////////////////////////////////////////////////////////// 1652 | // class Value::Value 1653 | // ////////////////////////////////////////////////////////////////// 1654 | // ////////////////////////////////////////////////////////////////// 1655 | // ////////////////////////////////////////////////////////////////// 1656 | 1657 | /*! \internal Default constructor initialization must be equivalent to: 1658 | * memset( this, 0, sizeof(Value) ) 1659 | * This optimization is used in ValueInternalMap fast allocator. 1660 | */ 1661 | Value::Value(ValueType type) 1662 | : type_(type), allocated_(false) 1663 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1664 | , 1665 | itemIsUsed_(0) 1666 | #endif 1667 | , 1668 | comments_(0), start_(0), limit_(0) { 1669 | switch (type) { 1670 | case nullValue: 1671 | break; 1672 | case intValue: 1673 | case uintValue: 1674 | value_.int_ = 0; 1675 | break; 1676 | case realValue: 1677 | value_.real_ = 0.0; 1678 | break; 1679 | case stringValue: 1680 | value_.string_ = 0; 1681 | break; 1682 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1683 | case arrayValue: 1684 | case objectValue: 1685 | value_.map_ = new ObjectValues(); 1686 | break; 1687 | #else 1688 | case arrayValue: 1689 | value_.array_ = arrayAllocator()->newArray(); 1690 | break; 1691 | case objectValue: 1692 | value_.map_ = mapAllocator()->newMap(); 1693 | break; 1694 | #endif 1695 | case booleanValue: 1696 | value_.bool_ = false; 1697 | break; 1698 | default: 1699 | JSON_ASSERT_UNREACHABLE; 1700 | } 1701 | } 1702 | 1703 | Value::Value(UInt value) 1704 | : type_(uintValue), allocated_(false) 1705 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1706 | , 1707 | itemIsUsed_(0) 1708 | #endif 1709 | , 1710 | comments_(0), start_(0), limit_(0) { 1711 | value_.uint_ = value; 1712 | } 1713 | 1714 | Value::Value(Int value) 1715 | : type_(intValue), allocated_(false) 1716 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1717 | , 1718 | itemIsUsed_(0) 1719 | #endif 1720 | , 1721 | comments_(0), start_(0), limit_(0) { 1722 | value_.int_ = value; 1723 | } 1724 | 1725 | #if defined(JSON_HAS_INT64) 1726 | Value::Value(Int64 value) 1727 | : type_(intValue), allocated_(false) 1728 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1729 | , 1730 | itemIsUsed_(0) 1731 | #endif 1732 | , 1733 | comments_(0), start_(0), limit_(0) { 1734 | value_.int_ = value; 1735 | } 1736 | 1737 | Value::Value(UInt64 value) 1738 | : type_(uintValue), allocated_(false) 1739 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1740 | , 1741 | itemIsUsed_(0) 1742 | #endif 1743 | , 1744 | comments_(0), start_(0), limit_(0) { 1745 | value_.uint_ = value; 1746 | } 1747 | #endif // defined(JSON_HAS_INT64) 1748 | 1749 | Value::Value(double value) 1750 | : type_(realValue), allocated_(false) 1751 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1752 | , 1753 | itemIsUsed_(0) 1754 | #endif 1755 | , 1756 | comments_(0), start_(0), limit_(0) { 1757 | value_.real_ = value; 1758 | } 1759 | 1760 | Value::Value(const char* value) 1761 | : type_(stringValue), allocated_(true) 1762 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1763 | , 1764 | itemIsUsed_(0) 1765 | #endif 1766 | , 1767 | comments_(0), start_(0), limit_(0) { 1768 | value_.string_ = duplicateStringValue(value); 1769 | } 1770 | 1771 | Value::Value(const char* beginValue, const char* endValue) 1772 | : type_(stringValue), allocated_(true) 1773 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1774 | , 1775 | itemIsUsed_(0) 1776 | #endif 1777 | , 1778 | comments_(0), start_(0), limit_(0) { 1779 | value_.string_ = 1780 | duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue)); 1781 | } 1782 | 1783 | Value::Value(const std::string& value) 1784 | : type_(stringValue), allocated_(true) 1785 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1786 | , 1787 | itemIsUsed_(0) 1788 | #endif 1789 | , 1790 | comments_(0), start_(0), limit_(0) { 1791 | value_.string_ = 1792 | duplicateStringValue(value.c_str(), (unsigned int)value.length()); 1793 | } 1794 | 1795 | Value::Value(const StaticString& value) 1796 | : type_(stringValue), allocated_(false) 1797 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1798 | , 1799 | itemIsUsed_(0) 1800 | #endif 1801 | , 1802 | comments_(0), start_(0), limit_(0) { 1803 | value_.string_ = const_cast(value.c_str()); 1804 | } 1805 | 1806 | #ifdef JSON_USE_CPPTL 1807 | Value::Value(const CppTL::ConstString& value) 1808 | : type_(stringValue), allocated_(true) 1809 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1810 | , 1811 | itemIsUsed_(0) 1812 | #endif 1813 | , 1814 | comments_(0), start_(0), limit_(0) { 1815 | value_.string_ = duplicateStringValue(value, value.length()); 1816 | } 1817 | #endif 1818 | 1819 | Value::Value(bool value) 1820 | : type_(booleanValue), allocated_(false) 1821 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1822 | , 1823 | itemIsUsed_(0) 1824 | #endif 1825 | , 1826 | comments_(0), start_(0), limit_(0) { 1827 | value_.bool_ = value; 1828 | } 1829 | 1830 | Value::Value(const Value& other) 1831 | : type_(other.type_), allocated_(false) 1832 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 1833 | , 1834 | itemIsUsed_(0) 1835 | #endif 1836 | , 1837 | comments_(0), start_(other.start_), limit_(other.limit_) { 1838 | switch (type_) { 1839 | case nullValue: 1840 | case intValue: 1841 | case uintValue: 1842 | case realValue: 1843 | case booleanValue: 1844 | value_ = other.value_; 1845 | break; 1846 | case stringValue: 1847 | if (other.value_.string_) { 1848 | value_.string_ = duplicateStringValue(other.value_.string_); 1849 | allocated_ = true; 1850 | } else { 1851 | value_.string_ = 0; 1852 | allocated_ = false; 1853 | } 1854 | break; 1855 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1856 | case arrayValue: 1857 | case objectValue: 1858 | value_.map_ = new ObjectValues(*other.value_.map_); 1859 | break; 1860 | #else 1861 | case arrayValue: 1862 | value_.array_ = arrayAllocator()->newArrayCopy(*other.value_.array_); 1863 | break; 1864 | case objectValue: 1865 | value_.map_ = mapAllocator()->newMapCopy(*other.value_.map_); 1866 | break; 1867 | #endif 1868 | default: 1869 | JSON_ASSERT_UNREACHABLE; 1870 | } 1871 | if (other.comments_) { 1872 | comments_ = new CommentInfo[numberOfCommentPlacement]; 1873 | for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { 1874 | const CommentInfo& otherComment = other.comments_[comment]; 1875 | if (otherComment.comment_) 1876 | comments_[comment].setComment(otherComment.comment_); 1877 | } 1878 | } 1879 | } 1880 | 1881 | Value::~Value() { 1882 | switch (type_) { 1883 | case nullValue: 1884 | case intValue: 1885 | case uintValue: 1886 | case realValue: 1887 | case booleanValue: 1888 | break; 1889 | case stringValue: 1890 | if (allocated_) 1891 | releaseStringValue(value_.string_); 1892 | break; 1893 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1894 | case arrayValue: 1895 | case objectValue: 1896 | delete value_.map_; 1897 | break; 1898 | #else 1899 | case arrayValue: 1900 | arrayAllocator()->destructArray(value_.array_); 1901 | break; 1902 | case objectValue: 1903 | mapAllocator()->destructMap(value_.map_); 1904 | break; 1905 | #endif 1906 | default: 1907 | JSON_ASSERT_UNREACHABLE; 1908 | } 1909 | 1910 | if (comments_) 1911 | delete[] comments_; 1912 | } 1913 | 1914 | Value& Value::operator=(Value other) { 1915 | swap(other); 1916 | return *this; 1917 | } 1918 | 1919 | void Value::swap(Value& other) { 1920 | ValueType temp = type_; 1921 | type_ = other.type_; 1922 | other.type_ = temp; 1923 | std::swap(value_, other.value_); 1924 | int temp2 = allocated_; 1925 | allocated_ = other.allocated_; 1926 | other.allocated_ = temp2; 1927 | std::swap(start_, other.start_); 1928 | std::swap(limit_, other.limit_); 1929 | } 1930 | 1931 | ValueType Value::type() const { return type_; } 1932 | 1933 | int Value::compare(const Value& other) const { 1934 | if (*this < other) 1935 | return -1; 1936 | if (*this > other) 1937 | return 1; 1938 | return 0; 1939 | } 1940 | 1941 | bool Value::operator<(const Value& other) const { 1942 | int typeDelta = type_ - other.type_; 1943 | if (typeDelta) 1944 | return typeDelta < 0 ? true : false; 1945 | switch (type_) { 1946 | case nullValue: 1947 | return false; 1948 | case intValue: 1949 | return value_.int_ < other.value_.int_; 1950 | case uintValue: 1951 | return value_.uint_ < other.value_.uint_; 1952 | case realValue: 1953 | return value_.real_ < other.value_.real_; 1954 | case booleanValue: 1955 | return value_.bool_ < other.value_.bool_; 1956 | case stringValue: 1957 | return (value_.string_ == 0 && other.value_.string_) || 1958 | (other.value_.string_ && value_.string_ && 1959 | strcmp(value_.string_, other.value_.string_) < 0); 1960 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 1961 | case arrayValue: 1962 | case objectValue: { 1963 | int delta = int(value_.map_->size() - other.value_.map_->size()); 1964 | if (delta) 1965 | return delta < 0; 1966 | return (*value_.map_) < (*other.value_.map_); 1967 | } 1968 | #else 1969 | case arrayValue: 1970 | return value_.array_->compare(*(other.value_.array_)) < 0; 1971 | case objectValue: 1972 | return value_.map_->compare(*(other.value_.map_)) < 0; 1973 | #endif 1974 | default: 1975 | JSON_ASSERT_UNREACHABLE; 1976 | } 1977 | return false; // unreachable 1978 | } 1979 | 1980 | bool Value::operator<=(const Value& other) const { return !(other < *this); } 1981 | 1982 | bool Value::operator>=(const Value& other) const { return !(*this < other); } 1983 | 1984 | bool Value::operator>(const Value& other) const { return other < *this; } 1985 | 1986 | bool Value::operator==(const Value& other) const { 1987 | // if ( type_ != other.type_ ) 1988 | // GCC 2.95.3 says: 1989 | // attempt to take address of bit-field structure member `Json::Value::type_' 1990 | // Beats me, but a temp solves the problem. 1991 | int temp = other.type_; 1992 | if (type_ != temp) 1993 | return false; 1994 | switch (type_) { 1995 | case nullValue: 1996 | return true; 1997 | case intValue: 1998 | return value_.int_ == other.value_.int_; 1999 | case uintValue: 2000 | return value_.uint_ == other.value_.uint_; 2001 | case realValue: 2002 | return value_.real_ == other.value_.real_; 2003 | case booleanValue: 2004 | return value_.bool_ == other.value_.bool_; 2005 | case stringValue: 2006 | return (value_.string_ == other.value_.string_) || 2007 | (other.value_.string_ && value_.string_ && 2008 | strcmp(value_.string_, other.value_.string_) == 0); 2009 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 2010 | case arrayValue: 2011 | case objectValue: 2012 | return value_.map_->size() == other.value_.map_->size() && 2013 | (*value_.map_) == (*other.value_.map_); 2014 | #else 2015 | case arrayValue: 2016 | return value_.array_->compare(*(other.value_.array_)) == 0; 2017 | case objectValue: 2018 | return value_.map_->compare(*(other.value_.map_)) == 0; 2019 | #endif 2020 | default: 2021 | JSON_ASSERT_UNREACHABLE; 2022 | } 2023 | return false; // unreachable 2024 | } 2025 | 2026 | bool Value::operator!=(const Value& other) const { return !(*this == other); } 2027 | 2028 | const char* Value::asCString() const { 2029 | JSON_ASSERT_MESSAGE(type_ == stringValue, 2030 | "in Json::Value::asCString(): requires stringValue"); 2031 | return value_.string_; 2032 | } 2033 | 2034 | std::string Value::asString() const { 2035 | switch (type_) { 2036 | case nullValue: 2037 | return ""; 2038 | case stringValue: 2039 | return value_.string_ ? value_.string_ : ""; 2040 | case booleanValue: 2041 | return value_.bool_ ? "true" : "false"; 2042 | case intValue: 2043 | return valueToString(value_.int_); 2044 | case uintValue: 2045 | return valueToString(value_.uint_); 2046 | case realValue: 2047 | return valueToString(value_.real_); 2048 | default: 2049 | JSON_FAIL_MESSAGE("Type is not convertible to string"); 2050 | } 2051 | } 2052 | 2053 | #ifdef JSON_USE_CPPTL 2054 | CppTL::ConstString Value::asConstString() const { 2055 | return CppTL::ConstString(asString().c_str()); 2056 | } 2057 | #endif 2058 | 2059 | Value::Int Value::asInt() const { 2060 | switch (type_) { 2061 | case intValue: 2062 | JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); 2063 | return Int(value_.int_); 2064 | case uintValue: 2065 | JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); 2066 | return Int(value_.uint_); 2067 | case realValue: 2068 | JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), 2069 | "double out of Int range"); 2070 | return Int(value_.real_); 2071 | case nullValue: 2072 | return 0; 2073 | case booleanValue: 2074 | return value_.bool_ ? 1 : 0; 2075 | default: 2076 | break; 2077 | } 2078 | JSON_FAIL_MESSAGE("Value is not convertible to Int."); 2079 | } 2080 | 2081 | Value::UInt Value::asUInt() const { 2082 | switch (type_) { 2083 | case intValue: 2084 | JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); 2085 | return UInt(value_.int_); 2086 | case uintValue: 2087 | JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); 2088 | return UInt(value_.uint_); 2089 | case realValue: 2090 | JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), 2091 | "double out of UInt range"); 2092 | return UInt(value_.real_); 2093 | case nullValue: 2094 | return 0; 2095 | case booleanValue: 2096 | return value_.bool_ ? 1 : 0; 2097 | default: 2098 | break; 2099 | } 2100 | JSON_FAIL_MESSAGE("Value is not convertible to UInt."); 2101 | } 2102 | 2103 | #if defined(JSON_HAS_INT64) 2104 | 2105 | Value::Int64 Value::asInt64() const { 2106 | switch (type_) { 2107 | case intValue: 2108 | return Int64(value_.int_); 2109 | case uintValue: 2110 | JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); 2111 | return Int64(value_.uint_); 2112 | case realValue: 2113 | JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), 2114 | "double out of Int64 range"); 2115 | return Int64(value_.real_); 2116 | case nullValue: 2117 | return 0; 2118 | case booleanValue: 2119 | return value_.bool_ ? 1 : 0; 2120 | default: 2121 | break; 2122 | } 2123 | JSON_FAIL_MESSAGE("Value is not convertible to Int64."); 2124 | } 2125 | 2126 | Value::UInt64 Value::asUInt64() const { 2127 | switch (type_) { 2128 | case intValue: 2129 | JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); 2130 | return UInt64(value_.int_); 2131 | case uintValue: 2132 | return UInt64(value_.uint_); 2133 | case realValue: 2134 | JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), 2135 | "double out of UInt64 range"); 2136 | return UInt64(value_.real_); 2137 | case nullValue: 2138 | return 0; 2139 | case booleanValue: 2140 | return value_.bool_ ? 1 : 0; 2141 | default: 2142 | break; 2143 | } 2144 | JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); 2145 | } 2146 | #endif // if defined(JSON_HAS_INT64) 2147 | 2148 | LargestInt Value::asLargestInt() const { 2149 | #if defined(JSON_NO_INT64) 2150 | return asInt(); 2151 | #else 2152 | return asInt64(); 2153 | #endif 2154 | } 2155 | 2156 | LargestUInt Value::asLargestUInt() const { 2157 | #if defined(JSON_NO_INT64) 2158 | return asUInt(); 2159 | #else 2160 | return asUInt64(); 2161 | #endif 2162 | } 2163 | 2164 | double Value::asDouble() const { 2165 | switch (type_) { 2166 | case intValue: 2167 | return static_cast(value_.int_); 2168 | case uintValue: 2169 | #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2170 | return static_cast(value_.uint_); 2171 | #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2172 | return integerToDouble(value_.uint_); 2173 | #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2174 | case realValue: 2175 | return value_.real_; 2176 | case nullValue: 2177 | return 0.0; 2178 | case booleanValue: 2179 | return value_.bool_ ? 1.0 : 0.0; 2180 | default: 2181 | break; 2182 | } 2183 | JSON_FAIL_MESSAGE("Value is not convertible to double."); 2184 | } 2185 | 2186 | float Value::asFloat() const { 2187 | switch (type_) { 2188 | case intValue: 2189 | return static_cast(value_.int_); 2190 | case uintValue: 2191 | #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2192 | return static_cast(value_.uint_); 2193 | #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2194 | return integerToDouble(value_.uint_); 2195 | #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2196 | case realValue: 2197 | return static_cast(value_.real_); 2198 | case nullValue: 2199 | return 0.0; 2200 | case booleanValue: 2201 | return value_.bool_ ? 1.0f : 0.0f; 2202 | default: 2203 | break; 2204 | } 2205 | JSON_FAIL_MESSAGE("Value is not convertible to float."); 2206 | } 2207 | 2208 | bool Value::asBool() const { 2209 | switch (type_) { 2210 | case booleanValue: 2211 | return value_.bool_; 2212 | case nullValue: 2213 | return false; 2214 | case intValue: 2215 | return value_.int_ ? true : false; 2216 | case uintValue: 2217 | return value_.uint_ ? true : false; 2218 | case realValue: 2219 | return value_.real_ ? true : false; 2220 | default: 2221 | break; 2222 | } 2223 | JSON_FAIL_MESSAGE("Value is not convertible to bool."); 2224 | } 2225 | 2226 | bool Value::isConvertibleTo(ValueType other) const { 2227 | switch (other) { 2228 | case nullValue: 2229 | return (isNumeric() && asDouble() == 0.0) || 2230 | (type_ == booleanValue && value_.bool_ == false) || 2231 | (type_ == stringValue && asString() == "") || 2232 | (type_ == arrayValue && value_.map_->size() == 0) || 2233 | (type_ == objectValue && value_.map_->size() == 0) || 2234 | type_ == nullValue; 2235 | case intValue: 2236 | return isInt() || 2237 | (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || 2238 | type_ == booleanValue || type_ == nullValue; 2239 | case uintValue: 2240 | return isUInt() || 2241 | (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || 2242 | type_ == booleanValue || type_ == nullValue; 2243 | case realValue: 2244 | return isNumeric() || type_ == booleanValue || type_ == nullValue; 2245 | case booleanValue: 2246 | return isNumeric() || type_ == booleanValue || type_ == nullValue; 2247 | case stringValue: 2248 | return isNumeric() || type_ == booleanValue || type_ == stringValue || 2249 | type_ == nullValue; 2250 | case arrayValue: 2251 | return type_ == arrayValue || type_ == nullValue; 2252 | case objectValue: 2253 | return type_ == objectValue || type_ == nullValue; 2254 | } 2255 | JSON_ASSERT_UNREACHABLE; 2256 | return false; 2257 | } 2258 | 2259 | /// Number of values in array or object 2260 | ArrayIndex Value::size() const { 2261 | switch (type_) { 2262 | case nullValue: 2263 | case intValue: 2264 | case uintValue: 2265 | case realValue: 2266 | case booleanValue: 2267 | case stringValue: 2268 | return 0; 2269 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 2270 | case arrayValue: // size of the array is highest index + 1 2271 | if (!value_.map_->empty()) { 2272 | ObjectValues::const_iterator itLast = value_.map_->end(); 2273 | --itLast; 2274 | return (*itLast).first.index() + 1; 2275 | } 2276 | return 0; 2277 | case objectValue: 2278 | return ArrayIndex(value_.map_->size()); 2279 | #else 2280 | case arrayValue: 2281 | return Int(value_.array_->size()); 2282 | case objectValue: 2283 | return Int(value_.map_->size()); 2284 | #endif 2285 | } 2286 | JSON_ASSERT_UNREACHABLE; 2287 | return 0; // unreachable; 2288 | } 2289 | 2290 | bool Value::empty() const { 2291 | if (isNull() || isArray() || isObject()) 2292 | return size() == 0u; 2293 | else 2294 | return false; 2295 | } 2296 | 2297 | bool Value::operator!() const { return isNull(); } 2298 | 2299 | void Value::clear() { 2300 | JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || 2301 | type_ == objectValue, 2302 | "in Json::Value::clear(): requires complex value"); 2303 | start_ = 0; 2304 | limit_ = 0; 2305 | switch (type_) { 2306 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 2307 | case arrayValue: 2308 | case objectValue: 2309 | value_.map_->clear(); 2310 | break; 2311 | #else 2312 | case arrayValue: 2313 | value_.array_->clear(); 2314 | break; 2315 | case objectValue: 2316 | value_.map_->clear(); 2317 | break; 2318 | #endif 2319 | default: 2320 | break; 2321 | } 2322 | } 2323 | 2324 | void Value::resize(ArrayIndex newSize) { 2325 | JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, 2326 | "in Json::Value::resize(): requires arrayValue"); 2327 | if (type_ == nullValue) 2328 | *this = Value(arrayValue); 2329 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 2330 | ArrayIndex oldSize = size(); 2331 | if (newSize == 0) 2332 | clear(); 2333 | else if (newSize > oldSize) 2334 | (*this)[newSize - 1]; 2335 | else { 2336 | for (ArrayIndex index = newSize; index < oldSize; ++index) { 2337 | value_.map_->erase(index); 2338 | } 2339 | assert(size() == newSize); 2340 | } 2341 | #else 2342 | value_.array_->resize(newSize); 2343 | #endif 2344 | } 2345 | 2346 | Value& Value::operator[](ArrayIndex index) { 2347 | JSON_ASSERT_MESSAGE( 2348 | type_ == nullValue || type_ == arrayValue, 2349 | "in Json::Value::operator[](ArrayIndex): requires arrayValue"); 2350 | if (type_ == nullValue) 2351 | *this = Value(arrayValue); 2352 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 2353 | CZString key(index); 2354 | ObjectValues::iterator it = value_.map_->lower_bound(key); 2355 | if (it != value_.map_->end() && (*it).first == key) 2356 | return (*it).second; 2357 | 2358 | ObjectValues::value_type defaultValue(key, null); 2359 | it = value_.map_->insert(it, defaultValue); 2360 | return (*it).second; 2361 | #else 2362 | return value_.array_->resolveReference(index); 2363 | #endif 2364 | } 2365 | 2366 | Value& Value::operator[](int index) { 2367 | JSON_ASSERT_MESSAGE( 2368 | index >= 0, 2369 | "in Json::Value::operator[](int index): index cannot be negative"); 2370 | return (*this)[ArrayIndex(index)]; 2371 | } 2372 | 2373 | const Value& Value::operator[](ArrayIndex index) const { 2374 | JSON_ASSERT_MESSAGE( 2375 | type_ == nullValue || type_ == arrayValue, 2376 | "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); 2377 | if (type_ == nullValue) 2378 | return null; 2379 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 2380 | CZString key(index); 2381 | ObjectValues::const_iterator it = value_.map_->find(key); 2382 | if (it == value_.map_->end()) 2383 | return null; 2384 | return (*it).second; 2385 | #else 2386 | Value* value = value_.array_->find(index); 2387 | return value ? *value : null; 2388 | #endif 2389 | } 2390 | 2391 | const Value& Value::operator[](int index) const { 2392 | JSON_ASSERT_MESSAGE( 2393 | index >= 0, 2394 | "in Json::Value::operator[](int index) const: index cannot be negative"); 2395 | return (*this)[ArrayIndex(index)]; 2396 | } 2397 | 2398 | Value& Value::operator[](const char* key) { 2399 | return resolveReference(key, false); 2400 | } 2401 | 2402 | Value& Value::resolveReference(const char* key, bool isStatic) { 2403 | JSON_ASSERT_MESSAGE( 2404 | type_ == nullValue || type_ == objectValue, 2405 | "in Json::Value::resolveReference(): requires objectValue"); 2406 | if (type_ == nullValue) 2407 | *this = Value(objectValue); 2408 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 2409 | CZString actualKey( 2410 | key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy); 2411 | ObjectValues::iterator it = value_.map_->lower_bound(actualKey); 2412 | if (it != value_.map_->end() && (*it).first == actualKey) 2413 | return (*it).second; 2414 | 2415 | ObjectValues::value_type defaultValue(actualKey, null); 2416 | it = value_.map_->insert(it, defaultValue); 2417 | Value& value = (*it).second; 2418 | return value; 2419 | #else 2420 | return value_.map_->resolveReference(key, isStatic); 2421 | #endif 2422 | } 2423 | 2424 | Value Value::get(ArrayIndex index, const Value& defaultValue) const { 2425 | const Value* value = &((*this)[index]); 2426 | return value == &null ? defaultValue : *value; 2427 | } 2428 | 2429 | bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } 2430 | 2431 | const Value& Value::operator[](const char* key) const { 2432 | JSON_ASSERT_MESSAGE( 2433 | type_ == nullValue || type_ == objectValue, 2434 | "in Json::Value::operator[](char const*)const: requires objectValue"); 2435 | if (type_ == nullValue) 2436 | return null; 2437 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 2438 | CZString actualKey(key, CZString::noDuplication); 2439 | ObjectValues::const_iterator it = value_.map_->find(actualKey); 2440 | if (it == value_.map_->end()) 2441 | return null; 2442 | return (*it).second; 2443 | #else 2444 | const Value* value = value_.map_->find(key); 2445 | return value ? *value : null; 2446 | #endif 2447 | } 2448 | 2449 | Value& Value::operator[](const std::string& key) { 2450 | return (*this)[key.c_str()]; 2451 | } 2452 | 2453 | const Value& Value::operator[](const std::string& key) const { 2454 | return (*this)[key.c_str()]; 2455 | } 2456 | 2457 | Value& Value::operator[](const StaticString& key) { 2458 | return resolveReference(key, true); 2459 | } 2460 | 2461 | #ifdef JSON_USE_CPPTL 2462 | Value& Value::operator[](const CppTL::ConstString& key) { 2463 | return (*this)[key.c_str()]; 2464 | } 2465 | 2466 | const Value& Value::operator[](const CppTL::ConstString& key) const { 2467 | return (*this)[key.c_str()]; 2468 | } 2469 | #endif 2470 | 2471 | Value& Value::append(const Value& value) { return (*this)[size()] = value; } 2472 | 2473 | Value Value::get(const char* key, const Value& defaultValue) const { 2474 | const Value* value = &((*this)[key]); 2475 | return value == &null ? defaultValue : *value; 2476 | } 2477 | 2478 | Value Value::get(const std::string& key, const Value& defaultValue) const { 2479 | return get(key.c_str(), defaultValue); 2480 | } 2481 | 2482 | Value Value::removeMember(const char* key) { 2483 | JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, 2484 | "in Json::Value::removeMember(): requires objectValue"); 2485 | if (type_ == nullValue) 2486 | return null; 2487 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 2488 | CZString actualKey(key, CZString::noDuplication); 2489 | ObjectValues::iterator it = value_.map_->find(actualKey); 2490 | if (it == value_.map_->end()) 2491 | return null; 2492 | Value old(it->second); 2493 | value_.map_->erase(it); 2494 | return old; 2495 | #else 2496 | Value* value = value_.map_->find(key); 2497 | if (value) { 2498 | Value old(*value); 2499 | value_.map_.remove(key); 2500 | return old; 2501 | } else { 2502 | return null; 2503 | } 2504 | #endif 2505 | } 2506 | 2507 | Value Value::removeMember(const std::string& key) { 2508 | return removeMember(key.c_str()); 2509 | } 2510 | 2511 | #ifdef JSON_USE_CPPTL 2512 | Value Value::get(const CppTL::ConstString& key, 2513 | const Value& defaultValue) const { 2514 | return get(key.c_str(), defaultValue); 2515 | } 2516 | #endif 2517 | 2518 | bool Value::isMember(const char* key) const { 2519 | const Value* value = &((*this)[key]); 2520 | return value != &null; 2521 | } 2522 | 2523 | bool Value::isMember(const std::string& key) const { 2524 | return isMember(key.c_str()); 2525 | } 2526 | 2527 | #ifdef JSON_USE_CPPTL 2528 | bool Value::isMember(const CppTL::ConstString& key) const { 2529 | return isMember(key.c_str()); 2530 | } 2531 | #endif 2532 | 2533 | Value::Members Value::getMemberNames() const { 2534 | JSON_ASSERT_MESSAGE( 2535 | type_ == nullValue || type_ == objectValue, 2536 | "in Json::Value::getMemberNames(), value must be objectValue"); 2537 | if (type_ == nullValue) 2538 | return Value::Members(); 2539 | Members members; 2540 | members.reserve(value_.map_->size()); 2541 | #ifndef JSON_VALUE_USE_INTERNAL_MAP 2542 | ObjectValues::const_iterator it = value_.map_->begin(); 2543 | ObjectValues::const_iterator itEnd = value_.map_->end(); 2544 | for (; it != itEnd; ++it) 2545 | members.push_back(std::string((*it).first.c_str())); 2546 | #else 2547 | ValueInternalMap::IteratorState it; 2548 | ValueInternalMap::IteratorState itEnd; 2549 | value_.map_->makeBeginIterator(it); 2550 | value_.map_->makeEndIterator(itEnd); 2551 | for (; !ValueInternalMap::equals(it, itEnd); ValueInternalMap::increment(it)) 2552 | members.push_back(std::string(ValueInternalMap::key(it))); 2553 | #endif 2554 | return members; 2555 | } 2556 | // 2557 | //# ifdef JSON_USE_CPPTL 2558 | // EnumMemberNames 2559 | // Value::enumMemberNames() const 2560 | //{ 2561 | // if ( type_ == objectValue ) 2562 | // { 2563 | // return CppTL::Enum::any( CppTL::Enum::transform( 2564 | // CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), 2565 | // MemberNamesTransform() ) ); 2566 | // } 2567 | // return EnumMemberNames(); 2568 | //} 2569 | // 2570 | // 2571 | // EnumValues 2572 | // Value::enumValues() const 2573 | //{ 2574 | // if ( type_ == objectValue || type_ == arrayValue ) 2575 | // return CppTL::Enum::anyValues( *(value_.map_), 2576 | // CppTL::Type() ); 2577 | // return EnumValues(); 2578 | //} 2579 | // 2580 | //# endif 2581 | 2582 | static bool IsIntegral(double d) { 2583 | double integral_part; 2584 | return modf(d, &integral_part) == 0.0; 2585 | } 2586 | 2587 | bool Value::isNull() const { return type_ == nullValue; } 2588 | 2589 | bool Value::isBool() const { return type_ == booleanValue; } 2590 | 2591 | bool Value::isInt() const { 2592 | switch (type_) { 2593 | case intValue: 2594 | return value_.int_ >= minInt && value_.int_ <= maxInt; 2595 | case uintValue: 2596 | return value_.uint_ <= UInt(maxInt); 2597 | case realValue: 2598 | return value_.real_ >= minInt && value_.real_ <= maxInt && 2599 | IsIntegral(value_.real_); 2600 | default: 2601 | break; 2602 | } 2603 | return false; 2604 | } 2605 | 2606 | bool Value::isUInt() const { 2607 | switch (type_) { 2608 | case intValue: 2609 | return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); 2610 | case uintValue: 2611 | return value_.uint_ <= maxUInt; 2612 | case realValue: 2613 | return value_.real_ >= 0 && value_.real_ <= maxUInt && 2614 | IsIntegral(value_.real_); 2615 | default: 2616 | break; 2617 | } 2618 | return false; 2619 | } 2620 | 2621 | bool Value::isInt64() const { 2622 | #if defined(JSON_HAS_INT64) 2623 | switch (type_) { 2624 | case intValue: 2625 | return true; 2626 | case uintValue: 2627 | return value_.uint_ <= UInt64(maxInt64); 2628 | case realValue: 2629 | // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a 2630 | // double, so double(maxInt64) will be rounded up to 2^63. Therefore we 2631 | // require the value to be strictly less than the limit. 2632 | return value_.real_ >= double(minInt64) && 2633 | value_.real_ < double(maxInt64) && IsIntegral(value_.real_); 2634 | default: 2635 | break; 2636 | } 2637 | #endif // JSON_HAS_INT64 2638 | return false; 2639 | } 2640 | 2641 | bool Value::isUInt64() const { 2642 | #if defined(JSON_HAS_INT64) 2643 | switch (type_) { 2644 | case intValue: 2645 | return value_.int_ >= 0; 2646 | case uintValue: 2647 | return true; 2648 | case realValue: 2649 | // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a 2650 | // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we 2651 | // require the value to be strictly less than the limit. 2652 | return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && 2653 | IsIntegral(value_.real_); 2654 | default: 2655 | break; 2656 | } 2657 | #endif // JSON_HAS_INT64 2658 | return false; 2659 | } 2660 | 2661 | bool Value::isIntegral() const { 2662 | #if defined(JSON_HAS_INT64) 2663 | return isInt64() || isUInt64(); 2664 | #else 2665 | return isInt() || isUInt(); 2666 | #endif 2667 | } 2668 | 2669 | bool Value::isDouble() const { return type_ == realValue || isIntegral(); } 2670 | 2671 | bool Value::isNumeric() const { return isIntegral() || isDouble(); } 2672 | 2673 | bool Value::isString() const { return type_ == stringValue; } 2674 | 2675 | bool Value::isArray() const { return type_ == arrayValue; } 2676 | 2677 | bool Value::isObject() const { return type_ == objectValue; } 2678 | 2679 | void Value::setComment(const char* comment, CommentPlacement placement) { 2680 | if (!comments_) 2681 | comments_ = new CommentInfo[numberOfCommentPlacement]; 2682 | comments_[placement].setComment(comment); 2683 | } 2684 | 2685 | void Value::setComment(const std::string& comment, CommentPlacement placement) { 2686 | setComment(comment.c_str(), placement); 2687 | } 2688 | 2689 | bool Value::hasComment(CommentPlacement placement) const { 2690 | return comments_ != 0 && comments_[placement].comment_ != 0; 2691 | } 2692 | 2693 | std::string Value::getComment(CommentPlacement placement) const { 2694 | if (hasComment(placement)) 2695 | return comments_[placement].comment_; 2696 | return ""; 2697 | } 2698 | 2699 | void Value::setOffsetStart(size_t start) { start_ = start; } 2700 | 2701 | void Value::setOffsetLimit(size_t limit) { limit_ = limit; } 2702 | 2703 | size_t Value::getOffsetStart() const { return start_; } 2704 | 2705 | size_t Value::getOffsetLimit() const { return limit_; } 2706 | 2707 | std::string Value::toStyledString() const { 2708 | StyledWriter writer; 2709 | return writer.write(*this); 2710 | } 2711 | 2712 | Value::const_iterator Value::begin() const { 2713 | switch (type_) { 2714 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 2715 | case arrayValue: 2716 | if (value_.array_) { 2717 | ValueInternalArray::IteratorState it; 2718 | value_.array_->makeBeginIterator(it); 2719 | return const_iterator(it); 2720 | } 2721 | break; 2722 | case objectValue: 2723 | if (value_.map_) { 2724 | ValueInternalMap::IteratorState it; 2725 | value_.map_->makeBeginIterator(it); 2726 | return const_iterator(it); 2727 | } 2728 | break; 2729 | #else 2730 | case arrayValue: 2731 | case objectValue: 2732 | if (value_.map_) 2733 | return const_iterator(value_.map_->begin()); 2734 | break; 2735 | #endif 2736 | default: 2737 | break; 2738 | } 2739 | return const_iterator(); 2740 | } 2741 | 2742 | Value::const_iterator Value::end() const { 2743 | switch (type_) { 2744 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 2745 | case arrayValue: 2746 | if (value_.array_) { 2747 | ValueInternalArray::IteratorState it; 2748 | value_.array_->makeEndIterator(it); 2749 | return const_iterator(it); 2750 | } 2751 | break; 2752 | case objectValue: 2753 | if (value_.map_) { 2754 | ValueInternalMap::IteratorState it; 2755 | value_.map_->makeEndIterator(it); 2756 | return const_iterator(it); 2757 | } 2758 | break; 2759 | #else 2760 | case arrayValue: 2761 | case objectValue: 2762 | if (value_.map_) 2763 | return const_iterator(value_.map_->end()); 2764 | break; 2765 | #endif 2766 | default: 2767 | break; 2768 | } 2769 | return const_iterator(); 2770 | } 2771 | 2772 | Value::iterator Value::begin() { 2773 | switch (type_) { 2774 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 2775 | case arrayValue: 2776 | if (value_.array_) { 2777 | ValueInternalArray::IteratorState it; 2778 | value_.array_->makeBeginIterator(it); 2779 | return iterator(it); 2780 | } 2781 | break; 2782 | case objectValue: 2783 | if (value_.map_) { 2784 | ValueInternalMap::IteratorState it; 2785 | value_.map_->makeBeginIterator(it); 2786 | return iterator(it); 2787 | } 2788 | break; 2789 | #else 2790 | case arrayValue: 2791 | case objectValue: 2792 | if (value_.map_) 2793 | return iterator(value_.map_->begin()); 2794 | break; 2795 | #endif 2796 | default: 2797 | break; 2798 | } 2799 | return iterator(); 2800 | } 2801 | 2802 | Value::iterator Value::end() { 2803 | switch (type_) { 2804 | #ifdef JSON_VALUE_USE_INTERNAL_MAP 2805 | case arrayValue: 2806 | if (value_.array_) { 2807 | ValueInternalArray::IteratorState it; 2808 | value_.array_->makeEndIterator(it); 2809 | return iterator(it); 2810 | } 2811 | break; 2812 | case objectValue: 2813 | if (value_.map_) { 2814 | ValueInternalMap::IteratorState it; 2815 | value_.map_->makeEndIterator(it); 2816 | return iterator(it); 2817 | } 2818 | break; 2819 | #else 2820 | case arrayValue: 2821 | case objectValue: 2822 | if (value_.map_) 2823 | return iterator(value_.map_->end()); 2824 | break; 2825 | #endif 2826 | default: 2827 | break; 2828 | } 2829 | return iterator(); 2830 | } 2831 | 2832 | // class PathArgument 2833 | // ////////////////////////////////////////////////////////////////// 2834 | 2835 | PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} 2836 | 2837 | PathArgument::PathArgument(ArrayIndex index) 2838 | : key_(), index_(index), kind_(kindIndex) {} 2839 | 2840 | PathArgument::PathArgument(const char* key) 2841 | : key_(key), index_(), kind_(kindKey) {} 2842 | 2843 | PathArgument::PathArgument(const std::string& key) 2844 | : key_(key.c_str()), index_(), kind_(kindKey) {} 2845 | 2846 | // class Path 2847 | // ////////////////////////////////////////////////////////////////// 2848 | 2849 | Path::Path(const std::string& path, 2850 | const PathArgument& a1, 2851 | const PathArgument& a2, 2852 | const PathArgument& a3, 2853 | const PathArgument& a4, 2854 | const PathArgument& a5) { 2855 | InArgs in; 2856 | in.push_back(&a1); 2857 | in.push_back(&a2); 2858 | in.push_back(&a3); 2859 | in.push_back(&a4); 2860 | in.push_back(&a5); 2861 | makePath(path, in); 2862 | } 2863 | 2864 | void Path::makePath(const std::string& path, const InArgs& in) { 2865 | const char* current = path.c_str(); 2866 | const char* end = current + path.length(); 2867 | InArgs::const_iterator itInArg = in.begin(); 2868 | while (current != end) { 2869 | if (*current == '[') { 2870 | ++current; 2871 | if (*current == '%') 2872 | addPathInArg(path, in, itInArg, PathArgument::kindIndex); 2873 | else { 2874 | ArrayIndex index = 0; 2875 | for (; current != end && *current >= '0' && *current <= '9'; ++current) 2876 | index = index * 10 + ArrayIndex(*current - '0'); 2877 | args_.push_back(index); 2878 | } 2879 | if (current == end || *current++ != ']') 2880 | invalidPath(path, int(current - path.c_str())); 2881 | } else if (*current == '%') { 2882 | addPathInArg(path, in, itInArg, PathArgument::kindKey); 2883 | ++current; 2884 | } else if (*current == '.') { 2885 | ++current; 2886 | } else { 2887 | const char* beginName = current; 2888 | while (current != end && !strchr("[.", *current)) 2889 | ++current; 2890 | args_.push_back(std::string(beginName, current)); 2891 | } 2892 | } 2893 | } 2894 | 2895 | void Path::addPathInArg(const std::string& /*path*/, 2896 | const InArgs& in, 2897 | InArgs::const_iterator& itInArg, 2898 | PathArgument::Kind kind) { 2899 | if (itInArg == in.end()) { 2900 | // Error: missing argument %d 2901 | } else if ((*itInArg)->kind_ != kind) { 2902 | // Error: bad argument type 2903 | } else { 2904 | args_.push_back(**itInArg); 2905 | } 2906 | } 2907 | 2908 | void Path::invalidPath(const std::string& /*path*/, int /*location*/) { 2909 | // Error: invalid path. 2910 | } 2911 | 2912 | const Value& Path::resolve(const Value& root) const { 2913 | const Value* node = &root; 2914 | for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { 2915 | const PathArgument& arg = *it; 2916 | if (arg.kind_ == PathArgument::kindIndex) { 2917 | if (!node->isArray() || !node->isValidIndex(arg.index_)) { 2918 | // Error: unable to resolve path (array value expected at position... 2919 | } 2920 | node = &((*node)[arg.index_]); 2921 | } else if (arg.kind_ == PathArgument::kindKey) { 2922 | if (!node->isObject()) { 2923 | // Error: unable to resolve path (object value expected at position...) 2924 | } 2925 | node = &((*node)[arg.key_]); 2926 | if (node == &Value::null) { 2927 | // Error: unable to resolve path (object has no member named '' at 2928 | // position...) 2929 | } 2930 | } 2931 | } 2932 | return *node; 2933 | } 2934 | 2935 | Value Path::resolve(const Value& root, const Value& defaultValue) const { 2936 | const Value* node = &root; 2937 | for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { 2938 | const PathArgument& arg = *it; 2939 | if (arg.kind_ == PathArgument::kindIndex) { 2940 | if (!node->isArray() || !node->isValidIndex(arg.index_)) 2941 | return defaultValue; 2942 | node = &((*node)[arg.index_]); 2943 | } else if (arg.kind_ == PathArgument::kindKey) { 2944 | if (!node->isObject()) 2945 | return defaultValue; 2946 | node = &((*node)[arg.key_]); 2947 | if (node == &Value::null) 2948 | return defaultValue; 2949 | } 2950 | } 2951 | return *node; 2952 | } 2953 | 2954 | Value& Path::make(Value& root) const { 2955 | Value* node = &root; 2956 | for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { 2957 | const PathArgument& arg = *it; 2958 | if (arg.kind_ == PathArgument::kindIndex) { 2959 | if (!node->isArray()) { 2960 | // Error: node is not an array at position ... 2961 | } 2962 | node = &((*node)[arg.index_]); 2963 | } else if (arg.kind_ == PathArgument::kindKey) { 2964 | if (!node->isObject()) { 2965 | // Error: node is not an object at position... 2966 | } 2967 | node = &((*node)[arg.key_]); 2968 | } 2969 | } 2970 | return *node; 2971 | } 2972 | 2973 | } // namespace Json 2974 | 2975 | // ////////////////////////////////////////////////////////////////////// 2976 | // End of content of file: src/lib_json/json_value.cpp 2977 | // ////////////////////////////////////////////////////////////////////// 2978 | 2979 | 2980 | 2981 | 2982 | 2983 | 2984 | // ////////////////////////////////////////////////////////////////////// 2985 | // Beginning of content of file: src/lib_json/json_writer.cpp 2986 | // ////////////////////////////////////////////////////////////////////// 2987 | 2988 | // Copyright 2011 Baptiste Lepilleur 2989 | // Distributed under MIT license, or public domain if desired and 2990 | // recognized in your jurisdiction. 2991 | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 2992 | 2993 | #if !defined(JSON_IS_AMALGAMATION) 2994 | #include 2995 | #include "json_tool.h" 2996 | #endif // if !defined(JSON_IS_AMALGAMATION) 2997 | #include 2998 | #include 2999 | #include 3000 | #include 3001 | #include 3002 | #include 3003 | #include 3004 | 3005 | #if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below 3006 | #include 3007 | #define isfinite _finite 3008 | #define snprintf _snprintf 3009 | #endif 3010 | 3011 | #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 3012 | // Disable warning about strdup being deprecated. 3013 | #pragma warning(disable : 4996) 3014 | #endif 3015 | 3016 | namespace Json { 3017 | 3018 | static bool containsControlCharacter(const char* str) { 3019 | while (*str) { 3020 | if (isControlCharacter(*(str++))) 3021 | return true; 3022 | } 3023 | return false; 3024 | } 3025 | 3026 | std::string valueToString(LargestInt value) { 3027 | UIntToStringBuffer buffer; 3028 | char* current = buffer + sizeof(buffer); 3029 | bool isNegative = value < 0; 3030 | if (isNegative) 3031 | value = -value; 3032 | uintToString(LargestUInt(value), current); 3033 | if (isNegative) 3034 | *--current = '-'; 3035 | assert(current >= buffer); 3036 | return current; 3037 | } 3038 | 3039 | std::string valueToString(LargestUInt value) { 3040 | UIntToStringBuffer buffer; 3041 | char* current = buffer + sizeof(buffer); 3042 | uintToString(value, current); 3043 | assert(current >= buffer); 3044 | return current; 3045 | } 3046 | 3047 | #if defined(JSON_HAS_INT64) 3048 | 3049 | std::string valueToString(Int value) { 3050 | return valueToString(LargestInt(value)); 3051 | } 3052 | 3053 | std::string valueToString(UInt value) { 3054 | return valueToString(LargestUInt(value)); 3055 | } 3056 | 3057 | #endif // # if defined(JSON_HAS_INT64) 3058 | 3059 | std::string valueToString(double value) { 3060 | // Allocate a buffer that is more than large enough to store the 16 digits of 3061 | // precision requested below. 3062 | char buffer[32]; 3063 | int len = -1; 3064 | 3065 | // Print into the buffer. We need not request the alternative representation 3066 | // that always has a decimal point because JSON doesn't distingish the 3067 | // concepts of reals and integers. 3068 | #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with 3069 | // visual studio 2005 to 3070 | // avoid warning. 3071 | #if defined(WINCE) 3072 | len = _snprintf(buffer, sizeof(buffer), "%.16g", value); 3073 | #else 3074 | len = sprintf_s(buffer, sizeof(buffer), "%.16g", value); 3075 | #endif 3076 | #else 3077 | if (std::isfinite(value)) { 3078 | len = snprintf(buffer, sizeof(buffer), "%.16g", value); 3079 | } else { 3080 | // IEEE standard states that NaN values will not compare to themselves 3081 | if (value != value) { 3082 | len = snprintf(buffer, sizeof(buffer), "null"); 3083 | } else if (value < 0) { 3084 | len = snprintf(buffer, sizeof(buffer), "-1e+9999"); 3085 | } else { 3086 | len = snprintf(buffer, sizeof(buffer), "1e+9999"); 3087 | } 3088 | // For those, we do not need to call fixNumLoc, but it is fast. 3089 | } 3090 | #endif 3091 | assert(len >= 0); 3092 | fixNumericLocale(buffer, buffer + len); 3093 | return buffer; 3094 | } 3095 | 3096 | std::string valueToString(bool value) { return value ? "true" : "false"; } 3097 | 3098 | std::string valueToQuotedString(const char* value) { 3099 | if (value == NULL) 3100 | return ""; 3101 | // Not sure how to handle unicode... 3102 | if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && 3103 | !containsControlCharacter(value)) 3104 | return std::string("\"") + value + "\""; 3105 | // We have to walk value and escape any special characters. 3106 | // Appending to std::string is not efficient, but this should be rare. 3107 | // (Note: forward slashes are *not* rare, but I am not escaping them.) 3108 | std::string::size_type maxsize = 3109 | strlen(value) * 2 + 3; // allescaped+quotes+NULL 3110 | std::string result; 3111 | result.reserve(maxsize); // to avoid lots of mallocs 3112 | result += "\""; 3113 | for (const char* c = value; *c != 0; ++c) { 3114 | switch (*c) { 3115 | case '\"': 3116 | result += "\\\""; 3117 | break; 3118 | case '\\': 3119 | result += "\\\\"; 3120 | break; 3121 | case '\b': 3122 | result += "\\b"; 3123 | break; 3124 | case '\f': 3125 | result += "\\f"; 3126 | break; 3127 | case '\n': 3128 | result += "\\n"; 3129 | break; 3130 | case '\r': 3131 | result += "\\r"; 3132 | break; 3133 | case '\t': 3134 | result += "\\t"; 3135 | break; 3136 | // case '/': 3137 | // Even though \/ is considered a legal escape in JSON, a bare 3138 | // slash is also legal, so I see no reason to escape it. 3139 | // (I hope I am not misunderstanding something. 3140 | // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); 3149 | result += oss.str(); 3150 | } else { 3151 | result += *c; 3152 | } 3153 | break; 3154 | } 3155 | } 3156 | result += "\""; 3157 | return result; 3158 | } 3159 | 3160 | // Class Writer 3161 | // ////////////////////////////////////////////////////////////////// 3162 | Writer::~Writer() {} 3163 | 3164 | // Class FastWriter 3165 | // ////////////////////////////////////////////////////////////////// 3166 | 3167 | FastWriter::FastWriter() 3168 | : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), 3169 | omitEndingLineFeed_(false) {} 3170 | 3171 | void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } 3172 | 3173 | void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } 3174 | 3175 | void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } 3176 | 3177 | std::string FastWriter::write(const Value& root) { 3178 | document_ = ""; 3179 | writeValue(root); 3180 | if (!omitEndingLineFeed_) 3181 | document_ += "\n"; 3182 | return document_; 3183 | } 3184 | 3185 | void FastWriter::writeValue(const Value& value) { 3186 | switch (value.type()) { 3187 | case nullValue: 3188 | if (!dropNullPlaceholders_) 3189 | document_ += "null"; 3190 | break; 3191 | case intValue: 3192 | document_ += valueToString(value.asLargestInt()); 3193 | break; 3194 | case uintValue: 3195 | document_ += valueToString(value.asLargestUInt()); 3196 | break; 3197 | case realValue: 3198 | document_ += valueToString(value.asDouble()); 3199 | break; 3200 | case stringValue: 3201 | document_ += valueToQuotedString(value.asCString()); 3202 | break; 3203 | case booleanValue: 3204 | document_ += valueToString(value.asBool()); 3205 | break; 3206 | case arrayValue: { 3207 | document_ += "["; 3208 | int size = value.size(); 3209 | for (int index = 0; index < size; ++index) { 3210 | if (index > 0) 3211 | document_ += ","; 3212 | writeValue(value[index]); 3213 | } 3214 | document_ += "]"; 3215 | } break; 3216 | case objectValue: { 3217 | Value::Members members(value.getMemberNames()); 3218 | document_ += "{"; 3219 | for (Value::Members::iterator it = members.begin(); it != members.end(); 3220 | ++it) { 3221 | const std::string& name = *it; 3222 | if (it != members.begin()) 3223 | document_ += ","; 3224 | document_ += valueToQuotedString(name.c_str()); 3225 | document_ += yamlCompatiblityEnabled_ ? ": " : ":"; 3226 | writeValue(value[name]); 3227 | } 3228 | document_ += "}"; 3229 | } break; 3230 | } 3231 | } 3232 | 3233 | // Class StyledWriter 3234 | // ////////////////////////////////////////////////////////////////// 3235 | 3236 | StyledWriter::StyledWriter() 3237 | : rightMargin_(74), indentSize_(3), addChildValues_() {} 3238 | 3239 | std::string StyledWriter::write(const Value& root) { 3240 | document_ = ""; 3241 | addChildValues_ = false; 3242 | indentString_ = ""; 3243 | writeCommentBeforeValue(root); 3244 | writeValue(root); 3245 | writeCommentAfterValueOnSameLine(root); 3246 | document_ += "\n"; 3247 | return document_; 3248 | } 3249 | 3250 | void StyledWriter::writeValue(const Value& value) { 3251 | switch (value.type()) { 3252 | case nullValue: 3253 | pushValue("null"); 3254 | break; 3255 | case intValue: 3256 | pushValue(valueToString(value.asLargestInt())); 3257 | break; 3258 | case uintValue: 3259 | pushValue(valueToString(value.asLargestUInt())); 3260 | break; 3261 | case realValue: 3262 | pushValue(valueToString(value.asDouble())); 3263 | break; 3264 | case stringValue: 3265 | pushValue(valueToQuotedString(value.asCString())); 3266 | break; 3267 | case booleanValue: 3268 | pushValue(valueToString(value.asBool())); 3269 | break; 3270 | case arrayValue: 3271 | writeArrayValue(value); 3272 | break; 3273 | case objectValue: { 3274 | Value::Members members(value.getMemberNames()); 3275 | if (members.empty()) 3276 | pushValue("{}"); 3277 | else { 3278 | writeWithIndent("{"); 3279 | indent(); 3280 | Value::Members::iterator it = members.begin(); 3281 | for (;;) { 3282 | const std::string& name = *it; 3283 | const Value& childValue = value[name]; 3284 | writeCommentBeforeValue(childValue); 3285 | writeWithIndent(valueToQuotedString(name.c_str())); 3286 | document_ += " : "; 3287 | writeValue(childValue); 3288 | if (++it == members.end()) { 3289 | writeCommentAfterValueOnSameLine(childValue); 3290 | break; 3291 | } 3292 | document_ += ","; 3293 | writeCommentAfterValueOnSameLine(childValue); 3294 | } 3295 | unindent(); 3296 | writeWithIndent("}"); 3297 | } 3298 | } break; 3299 | } 3300 | } 3301 | 3302 | void StyledWriter::writeArrayValue(const Value& value) { 3303 | unsigned size = value.size(); 3304 | if (size == 0) 3305 | pushValue("[]"); 3306 | else { 3307 | bool isArrayMultiLine = isMultineArray(value); 3308 | if (isArrayMultiLine) { 3309 | writeWithIndent("["); 3310 | indent(); 3311 | bool hasChildValue = !childValues_.empty(); 3312 | unsigned index = 0; 3313 | for (;;) { 3314 | const Value& childValue = value[index]; 3315 | writeCommentBeforeValue(childValue); 3316 | if (hasChildValue) 3317 | writeWithIndent(childValues_[index]); 3318 | else { 3319 | writeIndent(); 3320 | writeValue(childValue); 3321 | } 3322 | if (++index == size) { 3323 | writeCommentAfterValueOnSameLine(childValue); 3324 | break; 3325 | } 3326 | document_ += ","; 3327 | writeCommentAfterValueOnSameLine(childValue); 3328 | } 3329 | unindent(); 3330 | writeWithIndent("]"); 3331 | } else // output on a single line 3332 | { 3333 | assert(childValues_.size() == size); 3334 | document_ += "[ "; 3335 | for (unsigned index = 0; index < size; ++index) { 3336 | if (index > 0) 3337 | document_ += ", "; 3338 | document_ += childValues_[index]; 3339 | } 3340 | document_ += " ]"; 3341 | } 3342 | } 3343 | } 3344 | 3345 | bool StyledWriter::isMultineArray(const Value& value) { 3346 | int size = value.size(); 3347 | bool isMultiLine = size * 3 >= rightMargin_; 3348 | childValues_.clear(); 3349 | for (int index = 0; index < size && !isMultiLine; ++index) { 3350 | const Value& childValue = value[index]; 3351 | isMultiLine = 3352 | isMultiLine || ((childValue.isArray() || childValue.isObject()) && 3353 | childValue.size() > 0); 3354 | } 3355 | if (!isMultiLine) // check if line length > max line length 3356 | { 3357 | childValues_.reserve(size); 3358 | addChildValues_ = true; 3359 | int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' 3360 | for (int index = 0; index < size; ++index) { 3361 | writeValue(value[index]); 3362 | lineLength += int(childValues_[index].length()); 3363 | } 3364 | addChildValues_ = false; 3365 | isMultiLine = isMultiLine || lineLength >= rightMargin_; 3366 | } 3367 | return isMultiLine; 3368 | } 3369 | 3370 | void StyledWriter::pushValue(const std::string& value) { 3371 | if (addChildValues_) 3372 | childValues_.push_back(value); 3373 | else 3374 | document_ += value; 3375 | } 3376 | 3377 | void StyledWriter::writeIndent() { 3378 | if (!document_.empty()) { 3379 | char last = document_[document_.length() - 1]; 3380 | if (last == ' ') // already indented 3381 | return; 3382 | if (last != '\n') // Comments may add new-line 3383 | document_ += '\n'; 3384 | } 3385 | document_ += indentString_; 3386 | } 3387 | 3388 | void StyledWriter::writeWithIndent(const std::string& value) { 3389 | writeIndent(); 3390 | document_ += value; 3391 | } 3392 | 3393 | void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } 3394 | 3395 | void StyledWriter::unindent() { 3396 | assert(int(indentString_.size()) >= indentSize_); 3397 | indentString_.resize(indentString_.size() - indentSize_); 3398 | } 3399 | 3400 | void StyledWriter::writeCommentBeforeValue(const Value& root) { 3401 | if (!root.hasComment(commentBefore)) 3402 | return; 3403 | 3404 | document_ += "\n"; 3405 | writeIndent(); 3406 | std::string normalizedComment = normalizeEOL(root.getComment(commentBefore)); 3407 | std::string::const_iterator iter = normalizedComment.begin(); 3408 | while (iter != normalizedComment.end()) { 3409 | document_ += *iter; 3410 | if (*iter == '\n' && *(iter + 1) == '/') 3411 | writeIndent(); 3412 | ++iter; 3413 | } 3414 | 3415 | // Comments are stripped of newlines, so add one here 3416 | document_ += "\n"; 3417 | } 3418 | 3419 | void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { 3420 | if (root.hasComment(commentAfterOnSameLine)) 3421 | document_ += " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); 3422 | 3423 | if (root.hasComment(commentAfter)) { 3424 | document_ += "\n"; 3425 | document_ += normalizeEOL(root.getComment(commentAfter)); 3426 | document_ += "\n"; 3427 | } 3428 | } 3429 | 3430 | bool StyledWriter::hasCommentForValue(const Value& value) { 3431 | return value.hasComment(commentBefore) || 3432 | value.hasComment(commentAfterOnSameLine) || 3433 | value.hasComment(commentAfter); 3434 | } 3435 | 3436 | std::string StyledWriter::normalizeEOL(const std::string& text) { 3437 | std::string normalized; 3438 | normalized.reserve(text.length()); 3439 | const char* begin = text.c_str(); 3440 | const char* end = begin + text.length(); 3441 | const char* current = begin; 3442 | while (current != end) { 3443 | char c = *current++; 3444 | if (c == '\r') // mac or dos EOL 3445 | { 3446 | if (*current == '\n') // convert dos EOL 3447 | ++current; 3448 | normalized += '\n'; 3449 | } else // handle unix EOL & other char 3450 | normalized += c; 3451 | } 3452 | return normalized; 3453 | } 3454 | 3455 | // Class StyledStreamWriter 3456 | // ////////////////////////////////////////////////////////////////// 3457 | 3458 | StyledStreamWriter::StyledStreamWriter(std::string indentation) 3459 | : document_(NULL), rightMargin_(74), indentation_(indentation), 3460 | addChildValues_() {} 3461 | 3462 | void StyledStreamWriter::write(std::ostream& out, const Value& root) { 3463 | document_ = &out; 3464 | addChildValues_ = false; 3465 | indentString_ = ""; 3466 | writeCommentBeforeValue(root); 3467 | writeValue(root); 3468 | writeCommentAfterValueOnSameLine(root); 3469 | *document_ << "\n"; 3470 | document_ = NULL; // Forget the stream, for safety. 3471 | } 3472 | 3473 | void StyledStreamWriter::writeValue(const Value& value) { 3474 | switch (value.type()) { 3475 | case nullValue: 3476 | pushValue("null"); 3477 | break; 3478 | case intValue: 3479 | pushValue(valueToString(value.asLargestInt())); 3480 | break; 3481 | case uintValue: 3482 | pushValue(valueToString(value.asLargestUInt())); 3483 | break; 3484 | case realValue: 3485 | pushValue(valueToString(value.asDouble())); 3486 | break; 3487 | case stringValue: 3488 | pushValue(valueToQuotedString(value.asCString())); 3489 | break; 3490 | case booleanValue: 3491 | pushValue(valueToString(value.asBool())); 3492 | break; 3493 | case arrayValue: 3494 | writeArrayValue(value); 3495 | break; 3496 | case objectValue: { 3497 | Value::Members members(value.getMemberNames()); 3498 | if (members.empty()) 3499 | pushValue("{}"); 3500 | else { 3501 | writeWithIndent("{"); 3502 | indent(); 3503 | Value::Members::iterator it = members.begin(); 3504 | for (;;) { 3505 | const std::string& name = *it; 3506 | const Value& childValue = value[name]; 3507 | writeCommentBeforeValue(childValue); 3508 | writeWithIndent(valueToQuotedString(name.c_str())); 3509 | *document_ << " : "; 3510 | writeValue(childValue); 3511 | if (++it == members.end()) { 3512 | writeCommentAfterValueOnSameLine(childValue); 3513 | break; 3514 | } 3515 | *document_ << ","; 3516 | writeCommentAfterValueOnSameLine(childValue); 3517 | } 3518 | unindent(); 3519 | writeWithIndent("}"); 3520 | } 3521 | } break; 3522 | } 3523 | } 3524 | 3525 | void StyledStreamWriter::writeArrayValue(const Value& value) { 3526 | unsigned size = value.size(); 3527 | if (size == 0) 3528 | pushValue("[]"); 3529 | else { 3530 | bool isArrayMultiLine = isMultineArray(value); 3531 | if (isArrayMultiLine) { 3532 | writeWithIndent("["); 3533 | indent(); 3534 | bool hasChildValue = !childValues_.empty(); 3535 | unsigned index = 0; 3536 | for (;;) { 3537 | const Value& childValue = value[index]; 3538 | writeCommentBeforeValue(childValue); 3539 | if (hasChildValue) 3540 | writeWithIndent(childValues_[index]); 3541 | else { 3542 | writeIndent(); 3543 | writeValue(childValue); 3544 | } 3545 | if (++index == size) { 3546 | writeCommentAfterValueOnSameLine(childValue); 3547 | break; 3548 | } 3549 | *document_ << ","; 3550 | writeCommentAfterValueOnSameLine(childValue); 3551 | } 3552 | unindent(); 3553 | writeWithIndent("]"); 3554 | } else // output on a single line 3555 | { 3556 | assert(childValues_.size() == size); 3557 | *document_ << "[ "; 3558 | for (unsigned index = 0; index < size; ++index) { 3559 | if (index > 0) 3560 | *document_ << ", "; 3561 | *document_ << childValues_[index]; 3562 | } 3563 | *document_ << " ]"; 3564 | } 3565 | } 3566 | } 3567 | 3568 | bool StyledStreamWriter::isMultineArray(const Value& value) { 3569 | int size = value.size(); 3570 | bool isMultiLine = size * 3 >= rightMargin_; 3571 | childValues_.clear(); 3572 | for (int index = 0; index < size && !isMultiLine; ++index) { 3573 | const Value& childValue = value[index]; 3574 | isMultiLine = 3575 | isMultiLine || ((childValue.isArray() || childValue.isObject()) && 3576 | childValue.size() > 0); 3577 | } 3578 | if (!isMultiLine) // check if line length > max line length 3579 | { 3580 | childValues_.reserve(size); 3581 | addChildValues_ = true; 3582 | int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' 3583 | for (int index = 0; index < size; ++index) { 3584 | writeValue(value[index]); 3585 | lineLength += int(childValues_[index].length()); 3586 | } 3587 | addChildValues_ = false; 3588 | isMultiLine = isMultiLine || lineLength >= rightMargin_; 3589 | } 3590 | return isMultiLine; 3591 | } 3592 | 3593 | void StyledStreamWriter::pushValue(const std::string& value) { 3594 | if (addChildValues_) 3595 | childValues_.push_back(value); 3596 | else 3597 | *document_ << value; 3598 | } 3599 | 3600 | void StyledStreamWriter::writeIndent() { 3601 | /* 3602 | Some comments in this method would have been nice. ;-) 3603 | 3604 | if ( !document_.empty() ) 3605 | { 3606 | char last = document_[document_.length()-1]; 3607 | if ( last == ' ' ) // already indented 3608 | return; 3609 | if ( last != '\n' ) // Comments may add new-line 3610 | *document_ << '\n'; 3611 | } 3612 | */ 3613 | *document_ << '\n' << indentString_; 3614 | } 3615 | 3616 | void StyledStreamWriter::writeWithIndent(const std::string& value) { 3617 | writeIndent(); 3618 | *document_ << value; 3619 | } 3620 | 3621 | void StyledStreamWriter::indent() { indentString_ += indentation_; } 3622 | 3623 | void StyledStreamWriter::unindent() { 3624 | assert(indentString_.size() >= indentation_.size()); 3625 | indentString_.resize(indentString_.size() - indentation_.size()); 3626 | } 3627 | 3628 | void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { 3629 | if (!root.hasComment(commentBefore)) 3630 | return; 3631 | *document_ << normalizeEOL(root.getComment(commentBefore)); 3632 | *document_ << "\n"; 3633 | } 3634 | 3635 | void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { 3636 | if (root.hasComment(commentAfterOnSameLine)) 3637 | *document_ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine)); 3638 | 3639 | if (root.hasComment(commentAfter)) { 3640 | *document_ << "\n"; 3641 | *document_ << normalizeEOL(root.getComment(commentAfter)); 3642 | *document_ << "\n"; 3643 | } 3644 | } 3645 | 3646 | bool StyledStreamWriter::hasCommentForValue(const Value& value) { 3647 | return value.hasComment(commentBefore) || 3648 | value.hasComment(commentAfterOnSameLine) || 3649 | value.hasComment(commentAfter); 3650 | } 3651 | 3652 | std::string StyledStreamWriter::normalizeEOL(const std::string& text) { 3653 | std::string normalized; 3654 | normalized.reserve(text.length()); 3655 | const char* begin = text.c_str(); 3656 | const char* end = begin + text.length(); 3657 | const char* current = begin; 3658 | while (current != end) { 3659 | char c = *current++; 3660 | if (c == '\r') // mac or dos EOL 3661 | { 3662 | if (*current == '\n') // convert dos EOL 3663 | ++current; 3664 | normalized += '\n'; 3665 | } else // handle unix EOL & other char 3666 | normalized += c; 3667 | } 3668 | return normalized; 3669 | } 3670 | 3671 | std::ostream& operator<<(std::ostream& sout, const Value& root) { 3672 | Json::StyledStreamWriter writer; 3673 | writer.write(sout, root); 3674 | return sout; 3675 | } 3676 | 3677 | } // namespace Json 3678 | 3679 | // ////////////////////////////////////////////////////////////////////// 3680 | // End of content of file: src/lib_json/json_writer.cpp 3681 | // ////////////////////////////////////////////////////////////////////// 3682 | 3683 | 3684 | 3685 | 3686 | 3687 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/main.cpp -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | make: main.exe training.exe 2 | 3 | main.exe: main.cpp function.h 4 | g++ main.cpp -o main -O2 5 | 6 | training.exe: training.cpp function.h 7 | g++ training.cpp -o training -O2 8 | 9 | .PHONY: clean 10 | clean: 11 | del *.exe -------------------------------------------------------------------------------- /merge.cpp: -------------------------------------------------------------------------------- 1 | #define __DEBUG 2 | 3 | #include "function.h" 4 | 5 | using namespace std; 6 | 7 | #define MAXLIMIT 10000000 8 | 9 | struct node{long long ll; int cs, id;}; 10 | bool operator < (const node &a, const node &b){return a.ll>b.ll;} 11 | priority_queuenum; 12 | 13 | struct js{long long ll; int cs;}; 14 | bool operator < (const js &a, const js &b){return a.cs>b.cs;} 15 | priority_queuers; 16 | 17 | inline void PushIn(long long ll, int cs) 18 | { 19 | if ((int)rs.size() < MAXLIMIT) 20 | rs.push((js){ll,cs}); 21 | else if (cs > rs.top().cs) 22 | rs.pop(), rs.push((js){ll,cs}); 23 | } 24 | 25 | char str[50]; 26 | int num_tot = 0; 27 | ifstream G[79]; 28 | 29 | inline void GetNum(int f) 30 | { 31 | long long id; 32 | int tmp; 33 | if (G[f] >> id >> tmp) 34 | { 35 | num.push((node){id,tmp,f}); 36 | num_tot ++; 37 | if (num_tot % 100000 == 0) printf("%d\n", num_tot); 38 | } 39 | } 40 | 41 | inline void StoreData() 42 | { 43 | ofstream fout("2-word"); 44 | 45 | while (!rs.empty()) 46 | { 47 | js iter = rs.top(); rs.pop(); 48 | fout << iter.ll << ' ' << iter.cs << endl; 49 | } 50 | } 51 | 52 | int main() 53 | { 54 | char Filename[30] = "data/00"; 55 | 56 | for(int f=1; f<=75; f++) 57 | { 58 | Filename[5] = f/10 + '0'; 59 | Filename[6] = f%10 + '0'; 60 | 61 | G[f].open(Filename); 62 | 63 | GetNum(f); 64 | } 65 | 66 | long long ll; 67 | int cs; 68 | while (!num.empty()) 69 | { 70 | ll = num.top().ll; 71 | cs = 0; 72 | 73 | while (!num.empty() && num.top().ll == ll) 74 | { 75 | cs += num.top().cs; 76 | GetNum(num.top().id); 77 | num.pop(); 78 | } 79 | 80 | PushIn(ll, cs); 81 | } 82 | 83 | StoreData(); 84 | 85 | return 0; 86 | } -------------------------------------------------------------------------------- /output.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a44629e18a5e5a582643a192c3cdc646db9acc947bb2d74db44fcc22a173c774 3 | size 229778 4 | -------------------------------------------------------------------------------- /pinyin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/pinyin -------------------------------------------------------------------------------- /release/README.md: -------------------------------------------------------------------------------- 1 | ## 文件夹说明 2 | 3 | `bin`:可执行程序和数据文件 4 | 5 | `src`:源文件 6 | 7 | `data`:程序输入输出 8 | 9 | ## 源程序说明 10 | 11 | `bin/pinyin.exe`:基于字的二元模型的转换程序。使用指令:`pinyin.exe ` 12 | 13 | `bin/pinyin_2.exe`:基于词的二元模型的转换程序。使用指令:`pinyin_2.exe ` 14 | 15 | `bin/diff.exe`:比较程序,通过比较求得程序转换的准确率,需要提供一个标准文件。使用指令:`diff.exe ` 16 | 17 | `src/character`:基于字的二元模型的转换程序源码。 18 | 19 | `src/word`:基于词的二元模型的转换程序源码。 -------------------------------------------------------------------------------- /release/bin/1-gram: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/bin/1-gram -------------------------------------------------------------------------------- /release/bin/1-word: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/bin/1-word -------------------------------------------------------------------------------- /release/bin/2-gram: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/bin/2-gram -------------------------------------------------------------------------------- /release/bin/2-word.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/bin/2-word.zip -------------------------------------------------------------------------------- /release/bin/diff.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/bin/diff.exe -------------------------------------------------------------------------------- /release/bin/pinyin.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/bin/pinyin.exe -------------------------------------------------------------------------------- /release/bin/pinyin_2.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/bin/pinyin_2.exe -------------------------------------------------------------------------------- /release/src/character/function.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/src/character/function.h -------------------------------------------------------------------------------- /release/src/character/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/src/character/main.cpp -------------------------------------------------------------------------------- /release/src/diff.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/src/diff.cpp -------------------------------------------------------------------------------- /release/src/word/function.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/src/word/function.h -------------------------------------------------------------------------------- /release/src/word/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/release/src/word/main.cpp -------------------------------------------------------------------------------- /result.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:967d23ab100521f2f9a7d59ba3c3395206f81e675f89dbdd19ce51513e15163c 3 | size 391034 4 | -------------------------------------------------------------------------------- /result/1-word.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b733d90693a51404874a3000498fe03138df480f60e236b5ab9dd9edf9e7c973 3 | size 20330 4 | -------------------------------------------------------------------------------- /result/2-gram-v2.2.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:39430d8ee2e0136d8ae157a32bc93b46ef1115fa010a0332db81ed1672cfbe69 3 | size 19208 4 | -------------------------------------------------------------------------------- /result/2-gram_v1.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bc7dc6f3dde819fb59dbb48bf5751685cce20a2d7a4246e486abccc14c8e66ac 3 | size 19353 4 | -------------------------------------------------------------------------------- /result/2-gram_v2.0.1.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ad2fe1241bb4e4f7edd3fee23139aaabe85fe07fc6bf9652ec63f29cffa81161 3 | size 18964 4 | -------------------------------------------------------------------------------- /result/2-gram_v2.1.1.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ab6c833b7344e76649f2504c35a2d4dc48a4648bc1c59969f8f07d09ce78a0c7 3 | size 19966 4 | -------------------------------------------------------------------------------- /result/2-gram_v2.1.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ded8f071f76d30b8af1e25eb525ccec31419d3c059ae06e69993f4f8bccf86c5 3 | size 19216 4 | -------------------------------------------------------------------------------- /result/2-gram_v2.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7bf44cb0a79f92ebd30bd58530fe25337e93952ca5f28ef1f41211716c0e4576 3 | size 19074 4 | -------------------------------------------------------------------------------- /result/2-word.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fab5f7a54015c4b34413b1e2cbfb8702b40a4499a517de4ff2a8bba4aff483e9 3 | size 18992 4 | -------------------------------------------------------------------------------- /test/HSK.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fce6365c46dc6bfca80cf41fb283b69c3596408097d94a9530af5a03fe22ec8a 3 | size 245755 4 | -------------------------------------------------------------------------------- /test/answer.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eefdd7bebd57fe980f390285ccab5333362ca4911c26ab361fff2003676a57ed 3 | size 229778 4 | -------------------------------------------------------------------------------- /test/input.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:14013324b620ad69af4ee3044b14ddce94de86c292bda69b154fc7d3fe225cf6 3 | size 426186 4 | -------------------------------------------------------------------------------- /test/make.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from pypinyin import pinyin, lazy_pinyin, Style 4 | import jieba 5 | 6 | def foobar(char): 7 | return 'fuck' 8 | 9 | A = open('answer.txt', 'r', encoding='gbk') 10 | I = open('input.txt', 'w') 11 | 12 | while True: 13 | line = A.readline() 14 | if not line: 15 | break 16 | I.write(' '.join(lazy_pinyin(jieba.cut(line, cut_all=False), errors=foobar))+'\n') 17 | 18 | A.close() 19 | I.close() 20 | -------------------------------------------------------------------------------- /tmp.txt: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4c09f337d42d4f837bd6e62dcb610e456a69b4e22800a756fc94894f0927e777 3 | size 47038 4 | -------------------------------------------------------------------------------- /training.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Konano/Artificial-Intelligence-Input-Method/30ae63ced6890a33ab28fab6d23fda6256b8aa17/training.cpp -------------------------------------------------------------------------------- /trans.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | int main() 13 | { 14 | ifstream fin("tmp.txt"); 15 | ofstream fout1("input.txt"); 16 | ofstream fout2("answer.txt"); 17 | 18 | string str; 19 | while (getline(fin, str) && str != "") 20 | { 21 | if ('A' <= str[0] && str[0] <= 'Z') str[0]=str[0]-'A'+'a'; 22 | fout1 << str << endl; 23 | getline(fin, str); 24 | fout2 << str << endl; 25 | } 26 | return 0; 27 | } --------------------------------------------------------------------------------