Merge lp:~qqworini/ubuntu-rssreader-app/add-non-google-support into lp:ubuntu-rssreader-app

Proposed by Joey Chan
Status: Merged
Approved by: Roman Shchekin
Approved revision: 417
Merged at revision: 415
Proposed branch: lp:~qqworini/ubuntu-rssreader-app/add-non-google-support
Merge into: lp:ubuntu-rssreader-app
Diff against target: 14900 lines (+14343/-44)
52 files modified
shorts.apparmor (+3/-1)
shorts/CMakeLists.txt (+1/-0)
shorts/main.cpp (+5/-1)
shorts/po/com.ubuntu.shorts.pot (+74/-34)
shorts/qml/CMakeLists.txt (+1/-0)
shorts/qml/components/NetworkManager.qml (+144/-2)
shorts/qml/components/OptionsKeeper.qml (+19/-1)
shorts/qml/nongoogle/AppendNGFeedPage.qml (+254/-0)
shorts/qml/nongoogle/CMakeLists.txt (+6/-0)
shorts/qml/nongoogle/Positioner.qml (+114/-0)
shorts/qml/nongoogle/XmlNetwork.qml (+84/-0)
shorts/qml/pages/PageSettings.qml (+62/-0)
shorts/qml/shorts-app.qml (+56/-2)
shorts/shorts.pro (+42/-3)
shorts/shorts.qrc (+4/-0)
shorts/xml2json/rapidjson/allocators.h (+245/-0)
shorts/xml2json/rapidjson/document.h (+1969/-0)
shorts/xml2json/rapidjson/encodedstream.h (+290/-0)
shorts/xml2json/rapidjson/encodings.h (+630/-0)
shorts/xml2json/rapidjson/error/en.h (+71/-0)
shorts/xml2json/rapidjson/error/error.h (+150/-0)
shorts/xml2json/rapidjson/filereadstream.h (+94/-0)
shorts/xml2json/rapidjson/filestream.h (+73/-0)
shorts/xml2json/rapidjson/filewritestream.h (+97/-0)
shorts/xml2json/rapidjson/internal/biginteger.h (+294/-0)
shorts/xml2json/rapidjson/internal/diyfp.h (+268/-0)
shorts/xml2json/rapidjson/internal/dtoa.h (+225/-0)
shorts/xml2json/rapidjson/internal/ieee754.h (+90/-0)
shorts/xml2json/rapidjson/internal/itoa.h (+306/-0)
shorts/xml2json/rapidjson/internal/meta.h (+189/-0)
shorts/xml2json/rapidjson/internal/pow10.h (+59/-0)
shorts/xml2json/rapidjson/internal/stack.h (+183/-0)
shorts/xml2json/rapidjson/internal/strfunc.h (+43/-0)
shorts/xml2json/rapidjson/internal/strtod.h (+285/-0)
shorts/xml2json/rapidjson/memorybuffer.h (+76/-0)
shorts/xml2json/rapidjson/memorystream.h (+67/-0)
shorts/xml2json/rapidjson/msinttypes/inttypes.h (+312/-0)
shorts/xml2json/rapidjson/msinttypes/stdint.h (+296/-0)
shorts/xml2json/rapidjson/prettywriter.h (+211/-0)
shorts/xml2json/rapidjson/rapidjson.h (+629/-0)
shorts/xml2json/rapidjson/reader.h (+1444/-0)
shorts/xml2json/rapidjson/stringbuffer.h (+99/-0)
shorts/xml2json/rapidjson/writer.h (+401/-0)
shorts/xml2json/rapidxml/license.txt (+52/-0)
shorts/xml2json/rapidxml/manual.html (+406/-0)
shorts/xml2json/rapidxml/rapidxml.hpp (+2924/-0)
shorts/xml2json/rapidxml/rapidxml_iterators.hpp (+174/-0)
shorts/xml2json/rapidxml/rapidxml_print.hpp (+425/-0)
shorts/xml2json/rapidxml/rapidxml_utils.hpp (+122/-0)
shorts/xml2json/utilities.cpp (+46/-0)
shorts/xml2json/utilities.h (+24/-0)
shorts/xml2json/xml2json.hpp (+205/-0)
To merge this branch: bzr merge lp:~qqworini/ubuntu-rssreader-app/add-non-google-support
Reviewer Review Type Date Requested Status
Roman Shchekin Needs Fixing
Jenkins Bot continuous-integration Approve
Review via email: mp+280614@code.launchpad.net

Commit message

remove useless commented code

Description of the change

remove useless commented code

To post a comment you must log in.
Revision history for this message
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Roman Shchekin (mrqtros) wrote :

See inline comments.

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'shorts.apparmor'
2--- shorts.apparmor 2015-10-24 07:06:24 +0000
3+++ shorts.apparmor 2015-12-15 16:05:21 +0000
4@@ -1,7 +1,9 @@
5 {
6 "policy_groups": [
7 "networking",
8- "content_exchange_source"
9+ "content_exchange_source",
10+ "content_exchange",
11+ "location"
12 ],
13 "policy_version": 1.3
14 }
15
16=== modified file 'shorts/CMakeLists.txt'
17--- shorts/CMakeLists.txt 2015-08-11 12:07:22 +0000
18+++ shorts/CMakeLists.txt 2015-12-15 16:05:21 +0000
19@@ -5,6 +5,7 @@
20 main.cpp
21 CachingNetworkManagerFactory.cpp
22 shorts.qrc
23+ xml2json/utilities.cpp
24
25 )
26
27
28=== modified file 'shorts/main.cpp'
29--- shorts/main.cpp 2015-07-19 14:29:20 +0000
30+++ shorts/main.cpp 2015-12-15 16:05:21 +0000
31@@ -1,8 +1,9 @@
32 #include <QGuiApplication>
33 #include <QQmlApplicationEngine>
34-#include <QQuickView>
35+#include <QtQuick>
36
37 #include "CachingNetworkManagerFactory.h"
38+#include "xml2json/utilities.h"
39
40 int main(int argc, char *argv[])
41 {
42@@ -16,6 +17,9 @@
43 CachingNetworkManagerFactory *managerFactory = new CachingNetworkManagerFactory();
44 view.engine()->setNetworkAccessManagerFactory(managerFactory);
45
46+ Utilities *utilities = new Utilities();
47+ view.engine()->rootContext()->setContextProperty("utilities", utilities);
48+
49 view.setSource(QUrl(QStringLiteral("qrc:///qml/shorts-app.qml")));
50 // view.setSource(QUrl("./share/qml/shorts-app.qml"));
51 view.setResizeMode(QQuickView::SizeRootObjectToView);
52
53=== modified file 'shorts/po/com.ubuntu.shorts.pot'
54--- shorts/po/com.ubuntu.shorts.pot 2015-12-01 17:03:50 +0000
55+++ shorts/po/com.ubuntu.shorts.pot 2015-12-15 16:05:21 +0000
56@@ -8,7 +8,7 @@
57 msgstr ""
58 "Project-Id-Version: \n"
59 "Report-Msgid-Bugs-To: \n"
60-"POT-Creation-Date: 2015-12-01 17:27+0800\n"
61+"POT-Creation-Date: 2015-12-03 17:59+0800\n"
62 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
63 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
64 "Language-Team: LANGUAGE <LL@li.org>\n"
65@@ -42,11 +42,41 @@
66 msgid "Large"
67 msgstr ""
68
69-#: ../qml/pages/AppendFeedPage.qml:31 ../qml/shorts-app.qml:243
70-#: ../qml/shorts-app.qml:378
71+#: ../qml/nongoogle/AppendNGFeedPage.qml:30 ../qml/pages/AppendFeedPage.qml:31
72+#: ../qml/shorts-app.qml:255 ../qml/shorts-app.qml:390
73+#: ../qml/shorts-app.qml:398
74 msgid "Add feeds"
75 msgstr ""
76
77+#: ../qml/nongoogle/AppendNGFeedPage.qml:105
78+#: ../qml/pages/AppendFeedPage.qml:137
79+msgid "Type a keyword or URL"
80+msgstr ""
81+
82+#: ../qml/nongoogle/AppendNGFeedPage.qml:162
83+msgid "Feed Title:"
84+msgstr ""
85+
86+#: ../qml/nongoogle/AppendNGFeedPage.qml:170
87+#: ../qml/nongoogle/AppendNGFeedPage.qml:185
88+msgid "No data"
89+msgstr ""
90+
91+#: ../qml/nongoogle/AppendNGFeedPage.qml:177
92+msgid "Feed Description:"
93+msgstr ""
94+
95+#: ../qml/nongoogle/AppendNGFeedPage.qml:210
96+#: ../qml/pages/AppendFeedPage.qml:243 ../qml/pages/CreateTopicPage.qml:38
97+#: ../qml/pages/TopicManagement.qml:239 ../qml/shorts-app.qml:481
98+msgid "Cancel"
99+msgstr ""
100+
101+#: ../qml/nongoogle/AppendNGFeedPage.qml:243
102+#: ../qml/pages/AppendFeedPage.qml:276
103+msgid "Next"
104+msgstr ""
105+
106 #: ../qml/pages/AppendFeedPage.qml:69
107 msgid "Failed to perform a feed search by keyword"
108 msgstr ""
109@@ -59,23 +89,10 @@
110 msgid "Failed to perform a feed search by URL"
111 msgstr ""
112
113-#: ../qml/pages/AppendFeedPage.qml:137
114-msgid "Type a keyword or URL"
115-msgstr ""
116-
117 #: ../qml/pages/AppendFeedPage.qml:185
118 msgid "Search results"
119 msgstr ""
120
121-#: ../qml/pages/AppendFeedPage.qml:243 ../qml/pages/CreateTopicPage.qml:38
122-#: ../qml/pages/TopicManagement.qml:239 ../qml/shorts-app.qml:456
123-msgid "Cancel"
124-msgstr ""
125-
126-#: ../qml/pages/AppendFeedPage.qml:276
127-msgid "Next"
128-msgstr ""
129-
130 #: ../qml/pages/AppendFeedPage.qml:305 ../qml/pages/CreateTopicPage.qml:181
131 msgid "No feeds"
132 msgstr ""
133@@ -118,6 +135,7 @@
134
135 #: ../qml/pages/ChooseTopicPage.qml:109 ../qml/pages/ChooseTopicPage.qml:122
136 #: ../qml/pages/CreateTopicPage.qml:66 ../qml/pages/CreateTopicPage.qml:78
137+#: ../qml/shorts-app.qml:568
138 msgid "Warning"
139 msgstr ""
140
141@@ -161,7 +179,15 @@
142 msgid "Topic: "
143 msgstr ""
144
145-#: ../qml/pages/TopicManagement.qml:13 ../qml/shorts-app.qml:217
146+#: ../qml/pages/PageSettings.qml:9 ../qml/shorts-app.qml:239
147+msgid "Settings"
148+msgstr ""
149+
150+#: ../qml/pages/PageSettings.qml:21
151+msgid "Use Google Search: "
152+msgstr ""
153+
154+#: ../qml/pages/TopicManagement.qml:13 ../qml/shorts-app.qml:219
155 msgid "Edit topics"
156 msgstr ""
157
158@@ -173,74 +199,88 @@
159 msgid "Add Feed"
160 msgstr ""
161
162-#: ../qml/shorts-app.qml:184
163+#: ../qml/shorts-app.qml:186
164 msgid "Refresh"
165 msgstr ""
166
167-#: ../qml/shorts-app.qml:191
168+#: ../qml/shorts-app.qml:193
169 msgid "Grid View"
170 msgstr ""
171
172-#: ../qml/shorts-app.qml:191
173+#: ../qml/shorts-app.qml:193
174 msgid "List view"
175 msgstr ""
176
177-#: ../qml/shorts-app.qml:227
178+#: ../qml/shorts-app.qml:229
179 msgid "Disable night mode"
180 msgstr ""
181
182-#: ../qml/shorts-app.qml:227
183+#: ../qml/shorts-app.qml:229
184 msgid "Enable night mode"
185 msgstr ""
186
187-#: ../qml/shorts-app.qml:309
188+#: ../qml/shorts-app.qml:321
189 msgid "Saved"
190 msgstr ""
191
192-#: ../qml/shorts-app.qml:317 shorts.desktop.in.in.h:1
193+#: ../qml/shorts-app.qml:329 shorts.desktop.in.in.h:1
194 msgid "Shorts"
195 msgstr ""
196
197-#: ../qml/shorts-app.qml:448
198+#: ../qml/shorts-app.qml:473
199 msgid "Checking for new articles"
200 msgstr ""
201
202-#: ../qml/shorts-app.qml:472
203+#: ../qml/shorts-app.qml:497
204 msgid "Perhaps some of the channels have not been updated."
205 msgstr ""
206
207-#: ../qml/shorts-app.qml:473
208+#: ../qml/shorts-app.qml:498
209 msgid "Errors occurred during the update"
210 msgstr ""
211
212-#: ../qml/shorts-app.qml:491
213+#: ../qml/shorts-app.qml:516
214 msgid "+ Add feeds"
215 msgstr ""
216
217-#: ../qml/shorts-app.qml:503
218+#: ../qml/shorts-app.qml:528
219 msgid "Add online accounts"
220 msgstr ""
221
222-#: ../qml/shorts-app.qml:506
223+#: ../qml/shorts-app.qml:531
224 msgid "Online accounts are not available for now"
225 msgstr ""
226
227-#: ../qml/shorts-app.qml:507 ../qml/shorts-app.qml:516
228+#: ../qml/shorts-app.qml:532 ../qml/shorts-app.qml:541
229 msgid "We are sorry"
230 msgstr ""
231
232-#: ../qml/shorts-app.qml:512
233+#: ../qml/shorts-app.qml:537
234 msgid "Import subscriptions"
235 msgstr ""
236
237-#: ../qml/shorts-app.qml:515
238+#: ../qml/shorts-app.qml:540
239 msgid "Importing subscriptions is not available for now"
240 msgstr ""
241
242-#: ../qml/shorts-app.qml:530
243+#: ../qml/shorts-app.qml:555
244 msgid "Ok"
245 msgstr ""
246
247+#: ../qml/shorts-app.qml:569
248+msgid ""
249+"Shorts detects that you're located in an area which blocks Google's IP."
250+"<br><br>"
251+msgstr ""
252+
253+#: ../qml/shorts-app.qml:574
254+msgid "Yes, please."
255+msgstr ""
256+
257+#: ../qml/shorts-app.qml:584
258+msgid "No, thanks."
259+msgstr ""
260+
261 #: ../qml/tabs/BaseTab.qml:153
262 msgid "There are no articles to show"
263 msgstr ""
264
265=== modified file 'shorts/qml/CMakeLists.txt'
266--- shorts/qml/CMakeLists.txt 2015-07-17 14:42:42 +0000
267+++ shorts/qml/CMakeLists.txt 2015-12-15 16:05:21 +0000
268@@ -19,3 +19,4 @@
269 add_subdirectory(pages)
270 add_subdirectory(tabs)
271 add_subdirectory(utils)
272+add_subdirectory(nongoogle)
273
274=== modified file 'shorts/qml/components/NetworkManager.qml'
275--- shorts/qml/components/NetworkManager.qml 2015-10-24 07:06:24 +0000
276+++ shorts/qml/components/NetworkManager.qml 2015-12-15 16:05:21 +0000
277@@ -9,6 +9,9 @@
278 import "../utils/imgSeparator.js" as ImageUtils
279 import "../utils/dateutils.js" as DateUtils
280
281+// below import for non-google usage
282+import "../nongoogle"
283+
284 Item {
285 id: networkManagerRoot
286
287@@ -18,11 +21,21 @@
288 property string operationStatus: "success"
289
290 function updateFeeds(feedsArray, topicId) {
291- d.updateFeeds(feedsArray, topicId)
292+ if (optionsKeeper.useGoogleSearch()) {
293+ d.updateFeeds(feedsArray, topicId)
294+ }
295+ else {
296+ dNG.updateFeeds(feedsArray, topicId)
297+ }
298 }
299
300 function cancelDownload() {
301- d.cancelDownload()
302+ if (optionsKeeper.useGoogleSearch()) {
303+ d.cancelDownload()
304+ }
305+ else {
306+ dNG.cancelDownload()
307+ }
308 }
309
310 /* All private method are inside QtObject.
311@@ -129,4 +142,133 @@
312 }
313 } // GFA
314 } // QtObject
315+
316+ ////////////////////////////////////////// add a new object to refresh non-google feeds
317+ QtObject {
318+ id: dNG
319+
320+ property var feedList: [] // Feed list to update.
321+ property var currentFeed // Current downloading feed.
322+ property int tagId: 0 // Tag to update.
323+
324+ /* Method updates feeds one by another.
325+ * Input: array of objects, each should include
326+ * source, link and id (of feed in DB) properties.
327+ */
328+ function updateFeeds(feedsArray, topicId) {
329+ tagId = topicId || 0
330+
331+ downloadStarted(tagId)
332+
333+ feedList = feedsArray
334+ operationStatus = "success"
335+ updateNextFeed()
336+ }
337+
338+ // For inner usage only.
339+ function updateNextFeed() {
340+ if (feedList.length == 0) {
341+ downloadFinished(tagId)
342+ return
343+ }
344+
345+ currentFeed = feedList.shift()
346+ nonGoogleFeedApi.loadFeed(currentFeed.source)
347+ }
348+
349+ function cancelDownload() {
350+ feedList = []
351+ operationStatus = "abort"
352+ nonGoogleFeedApi.abort()
353+ }
354+
355+ function updateFeedInfo(feedId, feedLink, responseData) {
356+ var entries = responseData.item
357+ var f = responseData
358+
359+ var fde = f.description == undefined ? "" : f.description["#text"] == undefined ? f.description : f.description["#text"]
360+ var fti = f.title == undefined ? "" : f.title["#text"] == undefined ? f.title : f.title["#text"]
361+
362+ DB.updateFeedByXml(feedId, feedLink, fde, fti)
363+ console.log(" -------- UPDATE INFO -------- ")
364+ // console.log(f.title, f.link, f.feedUrl, f.description)
365+
366+ console.time("addArticlesEx")
367+
368+ var newArticles = []
369+ var maxLength = entries.length > 50 ? 50 : entries.length
370+ for (var i = 0; i < maxLength; i++) {
371+ var e = entries[i]
372+
373+ // print("article detail: ", JSON.stringify(e))
374+ // Grab image from for article.
375+ // var articleImage = ImageUtils.grabArticleImage(e)
376+ // e.content = clearFromBadTags(e.content)
377+
378+ var ti = e.title == undefined ? "" : e.title["#text"] == undefined ? e.title : e.title["#text"]
379+ var li = e.link == undefined ? "" : e.link["#text"] == undefined ? e.link : e.link["#text"]
380+ var au = e.author == undefined ? "" : e.author["#text"] == undefined ? e.author : e.author["#text"]
381+ var creator = e.creator == undefined ? "" : e.creator["#text"] == undefined ? e.creator : e.creator["#text"]
382+ var de = e.description == undefined ? "" : e.description["#text"] == undefined ? e.description : e.description["#text"]
383+ var pu = e.pubDate == undefined ? "" : e.pubDate["#text"] == undefined ? e.pubDate : e.pubDate["#text"]
384+ var co = e.content == undefined ? "" : e.content["#text"] == undefined ? e.content : e.content["#text"]
385+ var articleImage = utilities.htmlGetImg(de)
386+ if (articleImage.length == 0) { articleImage = utilities.htmlGetImg(co) }
387+ else {
388+ print("articleImage: ", articleImage[0])
389+ }
390+ // print("date parse 0: ", pu, DateUtils.parseDate(pu))
391+ // print("date parse 1: ", DateUtils.formatRelativeTime(i18n, DateUtils.parseDate(pu)))
392+
393+ var temp =
394+ {
395+ "title": ti,
396+ "content": co == "" ? de : co,
397+ "link": li,
398+ "author": creator == "" ? au : creator,
399+ "description": de,
400+ "pubDate": DateUtils.parseDate(pu),
401+ "guid": Qt.md5(li + pu),
402+ "image" : articleImage.length > 0 ? articleImage[0] : "",
403+ "media_groups" : ""
404+ }
405+
406+ newArticles.push(temp)
407+ }
408+// print("new article length: ", newArticles.length)
409+
410+ // /* Add new articles to DB and restore 'read' status of some of them.
411+ // */
412+ // DB.addArticles(articleModel, feedId, articleProperties);
413+
414+ /* Add new articles to DB and restore 'read' status of some of them. */
415+ try {
416+ DB.addArticlesEx(newArticles, feedId)
417+ } catch (e) {
418+ console.log("Exception:", JSON.stringify(e))
419+ }
420+
421+ console.timeEnd("addArticlesEx")
422+ }
423+
424+ function clearFromBadTags(content) {
425+ /* Remove non empty too. Useless anyway.
426+ */
427+ content = content.replace(/alt=".*?"/g, "")
428+ content = content.replace(/title=".*?"/g, "")
429+ return content
430+ }
431+
432+ property var nonGoogleFeedApi: XmlNetwork {
433+ onLoadResult: {
434+ if (result.rss == undefined || result.rss == "") {
435+// console.log("XML NETWORK GFA:", JSON.stringify(result))
436+ if (operationStatus == "success")
437+ operationStatus = "withErrors"
438+ } else dNG.updateFeedInfo(dNG.currentFeed.id, dNG.currentFeed.link, result.rss.channel)
439+
440+ dNG.updateNextFeed()
441+ }
442+ } // GFA
443+ } // QtObject
444 }
445
446=== modified file 'shorts/qml/components/OptionsKeeper.qml'
447--- shorts/qml/components/OptionsKeeper.qml 2015-10-10 11:24:04 +0000
448+++ shorts/qml/components/OptionsKeeper.qml 2015-12-15 16:05:21 +0000
449@@ -14,6 +14,11 @@
450 fontSize = getFontSize()
451 useDarkTheme = getUseDarkTheme()
452 useListMode = getUseListMode()
453+
454+
455+ if (useGoogleSearch() == undefined ) {
456+ setUseGoogleSearch(true)
457+ }
458 }
459
460 onFontSizeChanged: setFontSize(fontSize)
461@@ -64,6 +69,17 @@
462 return settingsDocument.contents.dbLastUpdate
463 }
464
465+ /////////////////////////////////////////////////////// below two functions are get/set "useGoogleSearch" value
466+ function useGoogleSearch() {
467+ return settingsDocument.contents.useGoogleSearch
468+ }
469+
470+ function setUseGoogleSearch(value) {
471+ var cont = settingsDocument.contents
472+ cont.useGoogleSearch = value
473+ settingsDocument.contents = cont
474+ }
475+
476 U1db.Database {
477 id: settingsDataBase
478 path: "ShortsOptions"
479@@ -75,6 +91,8 @@
480 docId: 'settingsDocument'
481 create: true
482 defaults: { "useDarkTheme" : false, "fontSize" : 1,
483- "useListMode" : false, "dbVersion" : 1.2}
484+ "useListMode" : false, "dbVersion" : 1.2,
485+ "useGoogleSearch" : true
486+ }
487 }
488 } // Item
489
490=== added directory 'shorts/qml/nongoogle'
491=== added file 'shorts/qml/nongoogle/AppendNGFeedPage.qml'
492--- shorts/qml/nongoogle/AppendNGFeedPage.qml 1970-01-01 00:00:00 +0000
493+++ shorts/qml/nongoogle/AppendNGFeedPage.qml 2015-12-15 16:05:21 +0000
494@@ -0,0 +1,254 @@
495+/*
496+ * Copyright (C) 2013, 2014
497+ *
498+ * This program is free software; you can redistribute it and/or modify
499+ * it under the terms of the GNU General Public License as published by
500+ * the Free Software Foundation; version 3.
501+ *
502+ * This program is distributed in the hope that it will be useful,
503+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
504+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
505+ * GNU General Public License for more details.
506+ *
507+ * You should have received a copy of the GNU General Public License
508+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
509+ */
510+
511+import QtQuick 2.4
512+import QtQuick.XmlListModel 2.0
513+import Ubuntu.Components 1.3
514+import Ubuntu.Components.ListItems 1.3 as ListItem
515+import Ubuntu.Components.Popups 1.3
516+
517+import "../utils/databasemodule_v2.js" as DB
518+import "../."
519+
520+Page {
521+ id: appendFeedPage
522+
523+ objectName: "appendfeedpage"
524+ title: i18n.tr("Add feeds")
525+ flickable: null
526+ visible: false
527+
528+ property bool isDirty: false // Need to clear all page content.
529+ property int selectedCount: 0
530+ property bool resultsReceived: false // Indicates that at least once results were received.
531+
532+ function reloadPageContent() {
533+ }
534+
535+ /* Clear model and model's depend data.
536+ * Currently only selectedCount.
537+ */
538+ function clearModelDependData() {
539+// searchResultsModel.clear()
540+// selectedCount = 0
541+ }
542+
543+ // ------------------------------------- XmlNetwork
544+
545+ property string feedTitle: ""
546+ property string feedDesc: ""
547+ property string feedUrl: ""
548+ property string feedLink: ""
549+ property var feedObj
550+
551+ XmlNetwork {
552+ id: xmlFeedApi
553+
554+ onLoadResult: {
555+ if (result.rss == undefined || result.rss == "") {
556+ // TODO alert that fail retriving feed data
557+ print("onLoadResult failed")
558+ }
559+ else {
560+// d.updateFeedInfo(d.currentFeed.id, d.currentFeed.link, result.rss.channel)
561+ var f = result.rss.channel
562+
563+ feedDesc = f.description == undefined ? "" : f.description["#text"] == undefined ? f.description : f.description["#text"]
564+ feedTitle = f.title == undefined ? "" : f.title["#text"] == undefined ? f.title : f.title["#text"]
565+// feedUrl = l
566+ feedLink = f.link == undefined ? "" : f.link["#text"] == undefined ? f.link : f.link["#text"]
567+ feedObj = {
568+ "url" : feedUrl,
569+ "title" : feedTitle,
570+ "description" : feedDesc,
571+ "link" : feedLink
572+ }
573+ }
574+
575+ }
576+ }
577+
578+ // ------------------------------------- XmlNetwork
579+
580+ Column {
581+ id: appendFeedColumn
582+
583+ anchors.top: parent.top
584+ anchors.topMargin: units.gu(2)
585+ width: parent.width
586+ spacing: units.gu(2)
587+
588+ TextField {
589+ objectName: "tfFeedUrl"
590+ id: tfFeedUrl
591+
592+ placeholderText: i18n.tr("Type a keyword or URL")
593+
594+ width: parent.width - units.gu(4)
595+ // height:units.gu(5)
596+ anchors {
597+ horizontalCenter: parent.horizontalCenter
598+ }
599+ primaryItem: Image {
600+ height: parent.height*0.5
601+ width: height
602+ anchors.verticalCenter: parent.verticalCenter
603+ // anchors.verticalCenterOffset: -units.gu(0.2)
604+ source: Qt.resolvedUrl("../icons_tmp/find.svg")
605+ smooth: true
606+
607+ MouseArea {
608+ anchors.fill: parent
609+ onClicked: {
610+ if (Qt.inputMethod.visible)
611+ tfFeedUrl.accapt()
612+ }
613+ }
614+ }
615+
616+ onAccepted: {
617+ accapt()
618+ }
619+
620+ function accapt() {
621+ Qt.inputMethod.hide()
622+ var userInput = text
623+
624+ if (userInput == "")
625+ return
626+
627+ // Very simple logic, URL if there are no spaces and contains dots.
628+ // But simple not means that it is wrong.
629+ var isUrlEntered = (userInput.indexOf(" ") === -1 && userInput.indexOf(".") !== -1)
630+
631+ if (isUrlEntered) {
632+ if (userInput.indexOf("http://") !== 0)
633+ {userInput = "http://" + userInput}
634+ feedUrl = userInput
635+ xmlFeedApi.loadFeed(userInput)
636+ }
637+// else xmlFeedApi.findFeeds(text)
638+ else {
639+ // TODO alert that user input invalid
640+ print("input invalid")
641+ }
642+ }
643+ }
644+
645+ ListItem.Header {
646+
647+ ListItem.ThinDivider { }
648+
649+ text: i18n.tr("Feed Title:")
650+
651+ ListItem.ThinDivider { anchors.bottom: parent.bottom }
652+ }
653+
654+ Label {
655+ anchors { left: parent.left;right: parent.right; margins: units.gu(2) }
656+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
657+ text: feedTitle == "" ? i18n.tr("No data") : feedTitle
658+ }
659+
660+ ListItem.Header {
661+
662+ ListItem.ThinDivider { }
663+
664+ text: i18n.tr("Feed Description:")
665+
666+ ListItem.ThinDivider { anchors.bottom: parent.bottom }
667+ }
668+
669+ Label {
670+ anchors { left: parent.left;right: parent.right; margins: units.gu(2) }
671+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
672+ text: feedDesc == "" ? i18n.tr("No data") : feedDesc
673+ }
674+ } // Column
675+
676+ Rectangle {
677+ id: fakePanel
678+
679+ color: "#fafafa"
680+ anchors {
681+ left: parent.left
682+ right: parent.right
683+ bottom: parent.bottom
684+ }
685+ height: units.gu(6)
686+ Item {
687+ anchors.fill: parent
688+
689+ Button {
690+ anchors {
691+ verticalCenter: parent.verticalCenter
692+ left: parent.left
693+ leftMargin: units.gu(1)
694+ }
695+ gradient: UbuntuColors.greyGradient
696+ action: Action {
697+ text: i18n.tr("Cancel")
698+
699+ onTriggered: {
700+ xmlFeedApi.abort()
701+ pageStack.pop()
702+ }
703+ }
704+ }
705+
706+ ActivityIndicator {
707+ id: checkRunning
708+
709+ visible: xmlFeedApi.inProgress
710+ running: xmlFeedApi.inProgress
711+
712+ anchors {
713+ verticalCenter: parent.verticalCenter
714+ right: nextBtn.left
715+ rightMargin: units.gu(1)
716+ }
717+ }
718+
719+ Button {
720+ id: nextBtn
721+ objectName: "nextButton"
722+ anchors {
723+ verticalCenter: parent.verticalCenter
724+ right: parent.right
725+ rightMargin: units.gu(1)
726+ }
727+
728+ enabled: !xmlFeedApi.inProgress && feedUrl != "" && feedTitle != ""
729+ action: Action {
730+ text: i18n.tr("Next")
731+
732+ onTriggered: {
733+ if (!nextBtn.enabled)
734+ return
735+
736+ var selectedFeeds = []
737+
738+ selectedFeeds.push(feedObj)
739+
740+ pageStack.push(chooseTopicPage, {"feedsToAdd" : selectedFeeds})
741+// pageStack.push(Qt.resolvedUrl("../pages/ChooseTopicPage.qml"), {"feedsToAdd" : selectedFeeds})
742+ }
743+ }
744+ } // Button
745+ }
746+ } // Rectangle fakePanel
747+
748+}
749
750=== added file 'shorts/qml/nongoogle/CMakeLists.txt'
751--- shorts/qml/nongoogle/CMakeLists.txt 1970-01-01 00:00:00 +0000
752+++ shorts/qml/nongoogle/CMakeLists.txt 2015-12-15 16:05:21 +0000
753@@ -0,0 +1,6 @@
754+file(GLOB NONGOOGLE_QML_JS_FILES *.qml *.js)
755+
756+# make the files visible in the qtcreator tree
757+add_custom_target(ubuntu-rssreader-app_nongoogle_QMlFiles ALL SOURCES ${NONGOOGLE_QML_JS_FILES})
758+
759+install(FILES ${NONGOOGLE_QML_JS_FILES} DESTINATION ${SHORTS_DIR}/nongoogle/)
760\ No newline at end of file
761
762=== added file 'shorts/qml/nongoogle/Positioner.qml'
763--- shorts/qml/nongoogle/Positioner.qml 1970-01-01 00:00:00 +0000
764+++ shorts/qml/nongoogle/Positioner.qml 2015-12-15 16:05:21 +0000
765@@ -0,0 +1,114 @@
766+/*
767+ * Copyright (C) 2014-2015 Canonical Ltd
768+ *
769+ * This file is part of Ubuntu Clock App
770+ *
771+ * Ubuntu Clock App is free software: you can redistribute it and/or modify
772+ * it under the terms of the GNU General Public License version 3 as
773+ * published by the Free Software Foundation.
774+ *
775+ * Ubuntu Clock App is distributed in the hope that it will be useful,
776+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
777+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
778+ * GNU General Public License for more details.
779+ *
780+ * You should have received a copy of the GNU General Public License
781+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
782+ */
783+
784+import QtQuick 2.4
785+import U1db 1.0 as U1db
786+import QtPositioning 5.2
787+import Ubuntu.Components 1.3
788+import Ubuntu.Components.Popups 1.3
789+//import "../components"
790+
791+Item {
792+ id: positioner
793+ objectName: "positioner"
794+
795+ anchors.fill: parent
796+
797+ // Property to keep track of app cold start status
798+ property string countryCode: ""
799+
800+ Component.onCompleted: {
801+ }
802+
803+ PositionSource {
804+ id: geoposition
805+
806+ // Property to store the time of the last GPS location update
807+ property var lastUpdate
808+
809+ readonly property real userLongitude: position.coordinate.longitude
810+
811+ readonly property real userLatitude: position.coordinate.latitude
812+
813+ active: true
814+ updateInterval: 1000
815+
816+ onSourceErrorChanged: {
817+ // Stop querying user location if location service is not available
818+ if (sourceError !== PositionSource.NoError) {
819+ console.log("[Source Error]: Location Service Error")
820+ geoposition.stop()
821+
822+ }
823+ }
824+
825+ onPositionChanged: {
826+ // Do not accept an invalid user location
827+ if(!position.longitudeValid || !position.latitudeValid) {
828+ return
829+ }
830+
831+ if(position.longitudeValid || position.latitudeValid) {
832+ print("current position: ", userLatitude, userLongitude)
833+ geoposition.stop()
834+ getCountryCode(userLatitude, userLongitude)
835+ }
836+
837+
838+ }
839+
840+ /* get country code from geonames.org
841+ // http://api.geonames.org/countryCode?lat=23&lng=113&username=krnekhelesh
842+ */
843+ function getCountryCode(lat, lng) {
844+
845+ var url = "http://api.geonames.org/countryCode?lat=" + lat + "&lng=" + lng + "&username=krnekhelesh&type=JSON"
846+
847+ var doc = new XMLHttpRequest()
848+
849+ doc.onreadystatechange = function() {
850+
851+ // print("positioner onreadystatechange: ", doc.readyState, doc.status, feedUrl)
852+ if (doc.readyState === XMLHttpRequest.DONE) {
853+
854+ var resObj
855+ if (doc.status == 200) {
856+ resObj = JSON.parse(doc.responseText)
857+ } else { // Error
858+ resObj = {"responseDetails" : doc.statusText,
859+ "responseStatus" : doc.status}
860+// resObj = ""
861+ }
862+
863+ countryCode = resObj.countryName
864+ print("countryCode", resObj)
865+
866+ if (countryCode == "China") {
867+ if (optionsKeeper.useGoogleSearch()) {
868+ PopupUtils.open(componentDialogNG, tabstabs)
869+ }
870+ }
871+ }
872+ }
873+
874+ doc.open("GET", url, true);
875+ doc.send();
876+ }
877+ } //PositionSource
878+
879+}
880
881=== added file 'shorts/qml/nongoogle/XmlNetwork.qml'
882--- shorts/qml/nongoogle/XmlNetwork.qml 1970-01-01 00:00:00 +0000
883+++ shorts/qml/nongoogle/XmlNetwork.qml 2015-12-15 16:05:21 +0000
884@@ -0,0 +1,84 @@
885+import QtQuick 2.4
886+
887+QtObject {
888+ id: rootObject
889+
890+ property bool inProgress: __doc != null
891+
892+ signal findResult(var result)
893+ signal loadResult(var result)
894+
895+ property var __doc: null
896+
897+ /* Load feed by URL.
898+ */
899+ function loadFeed(feedUrl, num) {
900+ abort(true)
901+
902+ if (num)
903+ num = Math.min(num, 100)
904+ else num = 50
905+
906+ __doc = new XMLHttpRequest()
907+ var doc = __doc
908+
909+ doc.onreadystatechange = function() {
910+
911+// print("xmlnetwork onreadystatechange: ", doc.readyState, doc.status, feedUrl)
912+ if (doc.readyState === XMLHttpRequest.DONE) {
913+
914+ var resObj
915+ if (doc.status == 200) {
916+// resObj = JSON.parse(doc.responseText)
917+ resObj = utilities.xmlToJson(doc.responseText)
918+ } else { // Error
919+ resObj = {"responseDetails" : doc.statusText,
920+ "responseStatus" : doc.status}
921+ }
922+
923+ __doc = null
924+ loadResult(resObj)
925+ }
926+ }
927+
928+
929+ /* Number of articles to download.
930+ */
931+// finalRequest += "&num=" + num
932+
933+ /* Add some optional params.
934+ * May be usable:
935+ * hl - host language, for example "hl=ru", default en.
936+ * num - number of entries, for example "num=50", default 4, maximum 100.
937+ * output - format of output, for example "output=json", may be xml, json_xml, json.
938+ */
939+// doc.open("GET", finalRequest, true);
940+ doc.open("GET", feedUrl, true);
941+ doc.send();
942+ }
943+
944+ /* Param "isAbortOnly" used to preserve
945+ * property "__doc" in not null state.
946+ * inProgress binded to it so we can avoid
947+ * additional recalculations.
948+ */
949+ function abort(isAbortOnly) {
950+ if (__doc != null) {
951+ __doc.abort()
952+ if (!isAbortOnly)
953+ __doc = null
954+ }
955+ }
956+
957+ /* Return true if some kind of errors detected.
958+ * TODO DEMO
959+ */
960+ function checkForErrors(result) {
961+ if (result.responseStatus == 200 || // HTTP OK
962+ result.responseStatus == 0) { // ABORTED
963+ return false
964+ }
965+
966+ return true
967+ }
968+} // QtObject
969
970=== added file 'shorts/qml/pages/PageSettings.qml'
971--- shorts/qml/pages/PageSettings.qml 1970-01-01 00:00:00 +0000
972+++ shorts/qml/pages/PageSettings.qml 2015-12-15 16:05:21 +0000
973@@ -0,0 +1,62 @@
974+import QtQuick 2.4
975+import Ubuntu.Components 1.3
976+import Ubuntu.Components.ListItems 1.3 as ListItem
977+import Ubuntu.Components.Popups 1.3
978+import "../components"
979+
980+Page {
981+ id: pageSettings
982+ title: i18n.tr("Settings")
983+ flickable: null
984+
985+ Column {
986+ anchors {
987+ top: parent.top; topMargin: units.gu(1)
988+ left: parent.left; leftMargin: units.gu(1)
989+ right: parent.right; rightMargin: units.gu(1)
990+ }
991+ height: childrenRect.height
992+ spacing: units.gu(0.8)
993+
994+ ///////////////////////////////////////////////////////////////////// Google RSS engine switch start here
995+ Label {
996+ anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
997+ horizontalAlignment: Text.AlignHCenter
998+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
999+ text: i18n.tr("For those who living in some special regions cannot access Google, the switch below can disable Google RSS engine, Shorts will directly get data from RSS sources.")
1000+ }
1001+
1002+ Item { width: 10; height: 1 } // just a separator
1003+
1004+ Item {
1005+ anchors { left: parent.left; right: parent.right; }
1006+ height: childrenRect.height
1007+
1008+ Label {
1009+ text: i18n.tr("Use Google Search: ")
1010+ }
1011+
1012+ Switch {
1013+ anchors.right: parent.right
1014+ checked: optionsKeeper.useGoogleSearch()
1015+
1016+ Component.onCompleted: {
1017+ if (optionsKeeper.useGoogleSearch() == undefined ) {
1018+ optionsKeeper.setUseGoogleSearch(true)
1019+ checked = true
1020+ }
1021+ }
1022+
1023+ onCheckedChanged: {
1024+ optionsKeeper.setUseGoogleSearch(checked)
1025+ }
1026+ }
1027+ }
1028+
1029+ ListItem.ThinDivider{}
1030+ ///////////////////////////////////////////////////////////////////// Google RSS engine switch end here
1031+
1032+
1033+ }// Column
1034+
1035+}
1036
1037=== modified file 'shorts/qml/shorts-app.qml'
1038--- shorts/qml/shorts-app.qml 2015-11-27 22:08:54 +0000
1039+++ shorts/qml/shorts-app.qml 2015-12-15 16:05:21 +0000
1040@@ -8,6 +8,8 @@
1041 import "./components"
1042 import "./utils/databasemodule_v2.js" as DB
1043
1044+import "./nongoogle"
1045+
1046 MainView {
1047 id: mainView
1048
1049@@ -119,7 +121,7 @@
1050 objectName: "pageStack"
1051
1052 property bool isListView: optionsKeeper.useListMode
1053- property var commonHeadActions: [refreshAction, changeModeAction, editTopicsAction, nightModeAction]
1054+ property var commonHeadActions: [refreshAction, changeModeAction, editTopicsAction, nightModeAction, actionSetting]
1055
1056 anchors.fill: parent
1057 focus: true
1058@@ -231,6 +233,16 @@
1059 }
1060 }
1061
1062+ Action {
1063+ id: actionSetting
1064+ objectName:"actionSetting"
1065+ text: i18n.tr("Settings")
1066+ iconName: "settings"
1067+ onTriggered: {
1068+ pageStack.push(Qt.resolvedUrl("./pages/PageSettings.qml"))
1069+ }
1070+ }
1071+
1072 /* -------------------------- Pages & Tabs ---------------------------- */
1073
1074 BottomEdgeTabs {
1075@@ -239,7 +251,7 @@
1076 objectName: "tabstabs"
1077 visible: false
1078
1079- bottomEdgePage: appendFeedPage
1080+ bottomEdgePage: optionsKeeper.useGoogleSearch() ? appendFeedPage : appendNGFeedPage
1081 bottomEdgeTitle: i18n.tr("Add feeds")
1082 bottomEdgeBackgroundColor: "#F5F5F5" // "#875864"
1083 bottomEdgeTipColor: "#5533b5e5"// "#E0E0E0" //"#9b616c"
1084@@ -379,6 +391,14 @@
1085 flickable: null
1086 visible: false
1087 }
1088+
1089+ AppendNGFeedPage {
1090+ id: appendNGFeedPage
1091+
1092+ title: i18n.tr("Add feeds")
1093+ flickable: null
1094+ visible: false
1095+ }
1096 // ******************************** Choose Topic Page ***********************///////////////
1097
1098 ChooseTopicPage {
1099@@ -436,6 +456,11 @@
1100 id: optionsKeeper
1101 }
1102
1103+ // Positioner to detect current position
1104+ Positioner {
1105+ id: positionDetector
1106+ }
1107+
1108 /* -------------------------- Components ---------------------------- */
1109
1110 Component {
1111@@ -534,6 +559,35 @@
1112 }
1113 } // Component
1114
1115+ //////////////////////////////////////////////////////// a dialog to ask user if she/he wants to turn off the google search
1116+ Component {
1117+ id: componentDialogNG
1118+
1119+ Dialog {
1120+ id: dialogNG
1121+ title: i18n.tr("Warning")
1122+ text: i18n.tr("Shorts detects that you're located in an area which blocks Google's IP.<br><br>"
1123+ + "We strongly reconmend you to turn off the Google search funtion."
1124+ + "Or you can do it in the settings page manually.")
1125+
1126+ Button {
1127+ text: i18n.tr("Yes, please.")
1128+ color: UbuntuColors.orange
1129+ objectName: "dialogNGButtonYes"
1130+ onClicked: {
1131+ optionsKeeper.setUseGoogleSearch(false)
1132+ PopupUtils.close(dialogNG)
1133+ }
1134+ }
1135+
1136+ Button {
1137+ text: i18n.tr("No, thanks.")
1138+ objectName: "dialogNGButtonNo"
1139+ onClicked: PopupUtils.close(dialogNG)
1140+ }
1141+ }
1142+ } // Component
1143+
1144 /* -------------------------- Connections ---------------------------- */
1145
1146 Connections {
1147
1148=== modified file 'shorts/shorts.pro'
1149--- shorts/shorts.pro 2015-09-16 08:52:25 +0000
1150+++ shorts/shorts.pro 2015-12-15 16:05:21 +0000
1151@@ -6,7 +6,8 @@
1152 QT += qml quick
1153
1154 SOURCES += main.cpp \
1155- CachingNetworkManagerFactory.cpp
1156+ CachingNetworkManagerFactory.cpp \
1157+ xml2json/utilities.cpp
1158
1159 RESOURCES += shorts.qrc
1160
1161@@ -41,12 +42,16 @@
1162 qml/pages/SwipeDelete.qml \
1163 qml/pages/TopicComponent.qml \
1164 qml/pages/TopicManagement.qml \
1165+ qml/pages/PageSettings.qml \
1166 qml/tabs/BaseTab.qml \
1167 qml/tabs/SavedTab.qml \
1168 qml/tabs/ShortsTab.qml \
1169 qml/tabs/TopicTab.qml \
1170 qml/shorts-app.qml \
1171- qml/content/SharePage.qml
1172+ qml/content/SharePage.qml \
1173+ qml/nongoogle/AppendNGFeedPage.qml \
1174+ qml/nongoogle/Positioner.qml \
1175+ qml/nongoogle/XmlNetwork.qml
1176
1177 #specify where the config files are installed to
1178 config_files.path = /.
1179@@ -59,5 +64,39 @@
1180 INSTALLS+=target
1181
1182 HEADERS += \
1183- CachingNetworkManagerFactory.h
1184+ CachingNetworkManagerFactory.h \
1185+ xml2json/utilities.h \
1186+ xml2json/rapidjson/error/en.h \
1187+ xml2json/rapidjson/error/error.h \
1188+ xml2json/rapidjson/internal/biginteger.h \
1189+ xml2json/rapidjson/internal/diyfp.h \
1190+ xml2json/rapidjson/internal/dtoa.h \
1191+ xml2json/rapidjson/internal/ieee754.h \
1192+ xml2json/rapidjson/internal/itoa.h \
1193+ xml2json/rapidjson/internal/meta.h \
1194+ xml2json/rapidjson/internal/pow10.h \
1195+ xml2json/rapidjson/internal/stack.h \
1196+ xml2json/rapidjson/internal/strfunc.h \
1197+ xml2json/rapidjson/internal/strtod.h \
1198+ xml2json/rapidjson/msinttypes/inttypes.h \
1199+ xml2json/rapidjson/msinttypes/stdint.h \
1200+ xml2json/rapidjson/allocators.h \
1201+ xml2json/rapidjson/document.h \
1202+ xml2json/rapidjson/encodedstream.h \
1203+ xml2json/rapidjson/encodings.h \
1204+ xml2json/rapidjson/filereadstream.h \
1205+ xml2json/rapidjson/filestream.h \
1206+ xml2json/rapidjson/filewritestream.h \
1207+ xml2json/rapidjson/memorybuffer.h \
1208+ xml2json/rapidjson/memorystream.h \
1209+ xml2json/rapidjson/prettywriter.h \
1210+ xml2json/rapidjson/rapidjson.h \
1211+ xml2json/rapidjson/reader.h \
1212+ xml2json/rapidjson/stringbuffer.h \
1213+ xml2json/rapidjson/writer.h \
1214+ xml2json/rapidxml/rapidxml.hpp \
1215+ xml2json/rapidxml/rapidxml_iterators.hpp \
1216+ xml2json/rapidxml/rapidxml_print.hpp \
1217+ xml2json/rapidxml/rapidxml_utils.hpp \
1218+ xml2json/xml2json.hpp
1219
1220
1221=== modified file 'shorts/shorts.qrc'
1222--- shorts/shorts.qrc 2015-09-16 08:52:25 +0000
1223+++ shorts/shorts.qrc 2015-12-15 16:05:21 +0000
1224@@ -32,6 +32,10 @@
1225 <file>qml/shorts-app.qml</file>
1226 <file>qml/content/SharePage.qml</file>
1227 <file>qml/components/DarkModeShader.qml</file>
1228+ <file>qml/nongoogle/XmlNetwork.qml</file>
1229+ <file>qml/nongoogle/AppendNGFeedPage.qml</file>
1230+ <file>qml/pages/PageSettings.qml</file>
1231+ <file>qml/nongoogle/Positioner.qml</file>
1232 </qresource>
1233 <qresource prefix="/img">
1234 <file>qml/icons/add.svg</file>
1235
1236=== added directory 'shorts/xml2json'
1237=== added directory 'shorts/xml2json/rapidjson'
1238=== added file 'shorts/xml2json/rapidjson/allocators.h'
1239--- shorts/xml2json/rapidjson/allocators.h 1970-01-01 00:00:00 +0000
1240+++ shorts/xml2json/rapidjson/allocators.h 2015-12-15 16:05:21 +0000
1241@@ -0,0 +1,245 @@
1242+// Copyright (C) 2011 Milo Yip
1243+//
1244+// Permission is hereby granted, free of charge, to any person obtaining a copy
1245+// of this software and associated documentation files (the "Software"), to deal
1246+// in the Software without restriction, including without limitation the rights
1247+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1248+// copies of the Software, and to permit persons to whom the Software is
1249+// furnished to do so, subject to the following conditions:
1250+//
1251+// The above copyright notice and this permission notice shall be included in
1252+// all copies or substantial portions of the Software.
1253+//
1254+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1255+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1256+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1257+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1258+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1259+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1260+// THE SOFTWARE.
1261+
1262+#ifndef RAPIDJSON_ALLOCATORS_H_
1263+#define RAPIDJSON_ALLOCATORS_H_
1264+
1265+#include "rapidjson.h"
1266+
1267+RAPIDJSON_NAMESPACE_BEGIN
1268+
1269+///////////////////////////////////////////////////////////////////////////////
1270+// Allocator
1271+
1272+/*! \class rapidjson::Allocator
1273+ \brief Concept for allocating, resizing and freeing memory block.
1274+
1275+ Note that Malloc() and Realloc() are non-static but Free() is static.
1276+
1277+ So if an allocator need to support Free(), it needs to put its pointer in
1278+ the header of memory block.
1279+
1280+\code
1281+concept Allocator {
1282+ static const bool kNeedFree; //!< Whether this allocator needs to call Free().
1283+
1284+ // Allocate a memory block.
1285+ // \param size of the memory block in bytes.
1286+ // \returns pointer to the memory block.
1287+ void* Malloc(size_t size);
1288+
1289+ // Resize a memory block.
1290+ // \param originalPtr The pointer to current memory block. Null pointer is permitted.
1291+ // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
1292+ // \param newSize the new size in bytes.
1293+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
1294+
1295+ // Free a memory block.
1296+ // \param pointer to the memory block. Null pointer is permitted.
1297+ static void Free(void *ptr);
1298+};
1299+\endcode
1300+*/
1301+
1302+///////////////////////////////////////////////////////////////////////////////
1303+// CrtAllocator
1304+
1305+//! C-runtime library allocator.
1306+/*! This class is just wrapper for standard C library memory routines.
1307+ \note implements Allocator concept
1308+*/
1309+class CrtAllocator {
1310+public:
1311+ static const bool kNeedFree = true;
1312+ void* Malloc(size_t size) { return std::malloc(size); }
1313+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); }
1314+ static void Free(void *ptr) { std::free(ptr); }
1315+};
1316+
1317+///////////////////////////////////////////////////////////////////////////////
1318+// MemoryPoolAllocator
1319+
1320+//! Default memory allocator used by the parser and DOM.
1321+/*! This allocator allocate memory blocks from pre-allocated memory chunks.
1322+
1323+ It does not free memory blocks. And Realloc() only allocate new memory.
1324+
1325+ The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
1326+
1327+ User may also supply a buffer as the first chunk.
1328+
1329+ If the user-buffer is full then additional chunks are allocated by BaseAllocator.
1330+
1331+ The user-buffer is not deallocated by this allocator.
1332+
1333+ \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
1334+ \note implements Allocator concept
1335+*/
1336+template <typename BaseAllocator = CrtAllocator>
1337+class MemoryPoolAllocator {
1338+public:
1339+ static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
1340+
1341+ //! Constructor with chunkSize.
1342+ /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
1343+ \param baseAllocator The allocator for allocating memory chunks.
1344+ */
1345+ MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
1346+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
1347+ {
1348+ }
1349+
1350+ //! Constructor with user-supplied buffer.
1351+ /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
1352+
1353+ The user buffer will not be deallocated when this allocator is destructed.
1354+
1355+ \param buffer User supplied buffer.
1356+ \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
1357+ \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
1358+ \param baseAllocator The allocator for allocating memory chunks.
1359+ */
1360+ MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
1361+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
1362+ {
1363+ RAPIDJSON_ASSERT(buffer != 0);
1364+ RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
1365+ chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
1366+ chunkHead_->capacity = size - sizeof(ChunkHeader);
1367+ chunkHead_->size = 0;
1368+ chunkHead_->next = 0;
1369+ }
1370+
1371+ //! Destructor.
1372+ /*! This deallocates all memory chunks, excluding the user-supplied buffer.
1373+ */
1374+ ~MemoryPoolAllocator() {
1375+ Clear();
1376+ RAPIDJSON_DELETE(ownBaseAllocator_);
1377+ }
1378+
1379+ //! Deallocates all memory chunks, excluding the user-supplied buffer.
1380+ void Clear() {
1381+ while(chunkHead_ != 0 && chunkHead_ != userBuffer_) {
1382+ ChunkHeader* next = chunkHead_->next;
1383+ baseAllocator_->Free(chunkHead_);
1384+ chunkHead_ = next;
1385+ }
1386+ }
1387+
1388+ //! Computes the total capacity of allocated memory chunks.
1389+ /*! \return total capacity in bytes.
1390+ */
1391+ size_t Capacity() const {
1392+ size_t capacity = 0;
1393+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
1394+ capacity += c->capacity;
1395+ return capacity;
1396+ }
1397+
1398+ //! Computes the memory blocks allocated.
1399+ /*! \return total used bytes.
1400+ */
1401+ size_t Size() const {
1402+ size_t size = 0;
1403+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
1404+ size += c->size;
1405+ return size;
1406+ }
1407+
1408+ //! Allocates a memory block. (concept Allocator)
1409+ void* Malloc(size_t size) {
1410+ size = RAPIDJSON_ALIGN(size);
1411+ if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
1412+ AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
1413+
1414+ void *buffer = reinterpret_cast<char *>(chunkHead_ + 1) + chunkHead_->size;
1415+ chunkHead_->size += size;
1416+ return buffer;
1417+ }
1418+
1419+ //! Resizes a memory block (concept Allocator)
1420+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
1421+ if (originalPtr == 0)
1422+ return Malloc(newSize);
1423+
1424+ // Do not shrink if new size is smaller than original
1425+ if (originalSize >= newSize)
1426+ return originalPtr;
1427+
1428+ // Simply expand it if it is the last allocation and there is sufficient space
1429+ if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) {
1430+ size_t increment = static_cast<size_t>(newSize - originalSize);
1431+ increment = RAPIDJSON_ALIGN(increment);
1432+ if (chunkHead_->size + increment <= chunkHead_->capacity) {
1433+ chunkHead_->size += increment;
1434+ return originalPtr;
1435+ }
1436+ }
1437+
1438+ // Realloc process: allocate and copy memory, do not free original buffer.
1439+ void* newBuffer = Malloc(newSize);
1440+ RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
1441+ return std::memcpy(newBuffer, originalPtr, originalSize);
1442+ }
1443+
1444+ //! Frees a memory block (concept Allocator)
1445+ static void Free(void *ptr) { (void)ptr; } // Do nothing
1446+
1447+private:
1448+ //! Copy constructor is not permitted.
1449+ MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
1450+ //! Copy assignment operator is not permitted.
1451+ MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
1452+
1453+ //! Creates a new chunk.
1454+ /*! \param capacity Capacity of the chunk in bytes.
1455+ */
1456+ void AddChunk(size_t capacity) {
1457+ if (!baseAllocator_)
1458+ ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
1459+ ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity));
1460+ chunk->capacity = capacity;
1461+ chunk->size = 0;
1462+ chunk->next = chunkHead_;
1463+ chunkHead_ = chunk;
1464+ }
1465+
1466+ static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
1467+
1468+ //! Chunk header for perpending to each chunk.
1469+ /*! Chunks are stored as a singly linked list.
1470+ */
1471+ struct ChunkHeader {
1472+ size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
1473+ size_t size; //!< Current size of allocated memory in bytes.
1474+ ChunkHeader *next; //!< Next chunk in the linked list.
1475+ };
1476+
1477+ ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
1478+ size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
1479+ void *userBuffer_; //!< User supplied buffer.
1480+ BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
1481+ BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
1482+};
1483+
1484+RAPIDJSON_NAMESPACE_END
1485+
1486+#endif // RAPIDJSON_ENCODINGS_H_
1487
1488=== added file 'shorts/xml2json/rapidjson/document.h'
1489--- shorts/xml2json/rapidjson/document.h 1970-01-01 00:00:00 +0000
1490+++ shorts/xml2json/rapidjson/document.h 2015-12-15 16:05:21 +0000
1491@@ -0,0 +1,1969 @@
1492+// Copyright (C) 2011 Milo Yip
1493+//
1494+// Permission is hereby granted, free of charge, to any person obtaining a copy
1495+// of this software and associated documentation files (the "Software"), to deal
1496+// in the Software without restriction, including without limitation the rights
1497+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1498+// copies of the Software, and to permit persons to whom the Software is
1499+// furnished to do so, subject to the following conditions:
1500+//
1501+// The above copyright notice and this permission notice shall be included in
1502+// all copies or substantial portions of the Software.
1503+//
1504+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1506+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1507+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1508+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1509+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1510+// THE SOFTWARE.
1511+
1512+#ifndef RAPIDJSON_DOCUMENT_H_
1513+#define RAPIDJSON_DOCUMENT_H_
1514+
1515+/*! \file document.h */
1516+
1517+#include "reader.h"
1518+#include "internal/meta.h"
1519+#include "internal/strfunc.h"
1520+#include <new> // placement new
1521+
1522+#ifdef _MSC_VER
1523+RAPIDJSON_DIAG_PUSH
1524+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
1525+#elif defined(__GNUC__)
1526+RAPIDJSON_DIAG_PUSH
1527+RAPIDJSON_DIAG_OFF(effc++)
1528+#endif
1529+
1530+///////////////////////////////////////////////////////////////////////////////
1531+// RAPIDJSON_HAS_STDSTRING
1532+
1533+#ifndef RAPIDJSON_HAS_STDSTRING
1534+#ifdef RAPIDJSON_DOXYGEN_RUNNING
1535+#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
1536+#else
1537+#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
1538+#endif
1539+/*! \def RAPIDJSON_HAS_STDSTRING
1540+ \ingroup RAPIDJSON_CONFIG
1541+ \brief Enable RapidJSON support for \c std::string
1542+
1543+ By defining this preprocessor symbol to \c 1, several convenience functions for using
1544+ \ref rapidjson::GenericValue with \c std::string are enabled, especially
1545+ for construction and comparison.
1546+
1547+ \hideinitializer
1548+*/
1549+#include <string>
1550+#endif // RAPIDJSON_HAS_STDSTRING
1551+
1552+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
1553+#include <iterator> // std::iterator, std::random_access_iterator_tag
1554+#endif
1555+
1556+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
1557+#include <utility> // std::move
1558+#endif
1559+
1560+RAPIDJSON_NAMESPACE_BEGIN
1561+
1562+// Forward declaration.
1563+template <typename Encoding, typename Allocator>
1564+class GenericValue;
1565+
1566+//! Name-value pair in a JSON object value.
1567+/*!
1568+ This class was internal to GenericValue. It used to be a inner struct.
1569+ But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
1570+ https://code.google.com/p/rapidjson/issues/detail?id=64
1571+*/
1572+template <typename Encoding, typename Allocator>
1573+struct GenericMember {
1574+ GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
1575+ GenericValue<Encoding, Allocator> value; //!< value of member.
1576+};
1577+
1578+///////////////////////////////////////////////////////////////////////////////
1579+// GenericMemberIterator
1580+
1581+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
1582+
1583+//! (Constant) member iterator for a JSON object value
1584+/*!
1585+ \tparam Const Is this a constant iterator?
1586+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
1587+ \tparam Allocator Allocator type for allocating memory of object, array and string.
1588+
1589+ This class implements a Random Access Iterator for GenericMember elements
1590+ of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
1591+
1592+ \note This iterator implementation is mainly intended to avoid implicit
1593+ conversions from iterator values to \c NULL,
1594+ e.g. from GenericValue::FindMember.
1595+
1596+ \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
1597+ pointer-based implementation, if your platform doesn't provide
1598+ the C++ <iterator> header.
1599+
1600+ \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
1601+ */
1602+template <bool Const, typename Encoding, typename Allocator>
1603+class GenericMemberIterator
1604+ : public std::iterator<std::random_access_iterator_tag
1605+ , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
1606+
1607+ friend class GenericValue<Encoding,Allocator>;
1608+ template <bool, typename, typename> friend class GenericMemberIterator;
1609+
1610+ typedef GenericMember<Encoding,Allocator> PlainType;
1611+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
1612+ typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
1613+
1614+public:
1615+ //! Iterator type itself
1616+ typedef GenericMemberIterator Iterator;
1617+ //! Constant iterator type
1618+ typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator;
1619+ //! Non-constant iterator type
1620+ typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
1621+
1622+ //! Pointer to (const) GenericMember
1623+ typedef typename BaseType::pointer Pointer;
1624+ //! Reference to (const) GenericMember
1625+ typedef typename BaseType::reference Reference;
1626+ //! Signed integer type (e.g. \c ptrdiff_t)
1627+ typedef typename BaseType::difference_type DifferenceType;
1628+
1629+ //! Default constructor (singular value)
1630+ /*! Creates an iterator pointing to no element.
1631+ \note All operations, except for comparisons, are undefined on such values.
1632+ */
1633+ GenericMemberIterator() : ptr_() {}
1634+
1635+ //! Iterator conversions to more const
1636+ /*!
1637+ \param it (Non-const) iterator to copy from
1638+
1639+ Allows the creation of an iterator from another GenericMemberIterator
1640+ that is "less const". Especially, creating a non-constant iterator
1641+ from a constant iterator are disabled:
1642+ \li const -> non-const (not ok)
1643+ \li const -> const (ok)
1644+ \li non-const -> const (ok)
1645+ \li non-const -> non-const (ok)
1646+
1647+ \note If the \c Const template parameter is already \c false, this
1648+ constructor effectively defines a regular copy-constructor.
1649+ Otherwise, the copy constructor is implicitly defined.
1650+ */
1651+ GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
1652+
1653+ //! @name stepping
1654+ //@{
1655+ Iterator& operator++(){ ++ptr_; return *this; }
1656+ Iterator& operator--(){ --ptr_; return *this; }
1657+ Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
1658+ Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
1659+ //@}
1660+
1661+ //! @name increment/decrement
1662+ //@{
1663+ Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
1664+ Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
1665+
1666+ Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
1667+ Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
1668+ //@}
1669+
1670+ //! @name relations
1671+ //@{
1672+ bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
1673+ bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
1674+ bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
1675+ bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
1676+ bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
1677+ bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
1678+ //@}
1679+
1680+ //! @name dereference
1681+ //@{
1682+ Reference operator*() const { return *ptr_; }
1683+ Pointer operator->() const { return ptr_; }
1684+ Reference operator[](DifferenceType n) const { return ptr_[n]; }
1685+ //@}
1686+
1687+ //! Distance
1688+ DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
1689+
1690+private:
1691+ //! Internal constructor from plain pointer
1692+ explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
1693+
1694+ Pointer ptr_; //!< raw pointer
1695+};
1696+
1697+#else // RAPIDJSON_NOMEMBERITERATORCLASS
1698+
1699+// class-based member iterator implementation disabled, use plain pointers
1700+
1701+template <bool Const, typename Encoding, typename Allocator>
1702+struct GenericMemberIterator;
1703+
1704+//! non-const GenericMemberIterator
1705+template <typename Encoding, typename Allocator>
1706+struct GenericMemberIterator<false,Encoding,Allocator> {
1707+ //! use plain pointer as iterator type
1708+ typedef GenericMember<Encoding,Allocator>* Iterator;
1709+};
1710+//! const GenericMemberIterator
1711+template <typename Encoding, typename Allocator>
1712+struct GenericMemberIterator<true,Encoding,Allocator> {
1713+ //! use plain const pointer as iterator type
1714+ typedef const GenericMember<Encoding,Allocator>* Iterator;
1715+};
1716+
1717+#endif // RAPIDJSON_NOMEMBERITERATORCLASS
1718+
1719+///////////////////////////////////////////////////////////////////////////////
1720+// GenericStringRef
1721+
1722+//! Reference to a constant string (not taking a copy)
1723+/*!
1724+ \tparam CharType character type of the string
1725+
1726+ This helper class is used to automatically infer constant string
1727+ references for string literals, especially from \c const \b (!)
1728+ character arrays.
1729+
1730+ The main use is for creating JSON string values without copying the
1731+ source string via an \ref Allocator. This requires that the referenced
1732+ string pointers have a sufficient lifetime, which exceeds the lifetime
1733+ of the associated GenericValue.
1734+
1735+ \b Example
1736+ \code
1737+ Value v("foo"); // ok, no need to copy & calculate length
1738+ const char foo[] = "foo";
1739+ v.SetString(foo); // ok
1740+
1741+ const char* bar = foo;
1742+ // Value x(bar); // not ok, can't rely on bar's lifetime
1743+ Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
1744+ Value y(StringRef(bar, 3)); // ok, explicitly pass length
1745+ \endcode
1746+
1747+ \see StringRef, GenericValue::SetString
1748+*/
1749+template<typename CharType>
1750+struct GenericStringRef {
1751+ typedef CharType Ch; //!< character type of the string
1752+
1753+ //! Create string reference from \c const character array
1754+ /*!
1755+ This constructor implicitly creates a constant string reference from
1756+ a \c const character array. It has better performance than
1757+ \ref StringRef(const CharType*) by inferring the string \ref length
1758+ from the array length, and also supports strings containing null
1759+ characters.
1760+
1761+ \tparam N length of the string, automatically inferred
1762+
1763+ \param str Constant character array, lifetime assumed to be longer
1764+ than the use of the string in e.g. a GenericValue
1765+
1766+ \post \ref s == str
1767+
1768+ \note Constant complexity.
1769+ \note There is a hidden, private overload to disallow references to
1770+ non-const character arrays to be created via this constructor.
1771+ By this, e.g. function-scope arrays used to be filled via
1772+ \c snprintf are excluded from consideration.
1773+ In such cases, the referenced string should be \b copied to the
1774+ GenericValue instead.
1775+ */
1776+ template<SizeType N>
1777+ GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
1778+ : s(str), length(N-1) {}
1779+
1780+ //! Explicitly create string reference from \c const character pointer
1781+ /*!
1782+ This constructor can be used to \b explicitly create a reference to
1783+ a constant string pointer.
1784+
1785+ \see StringRef(const CharType*)
1786+
1787+ \param str Constant character pointer, lifetime assumed to be longer
1788+ than the use of the string in e.g. a GenericValue
1789+
1790+ \post \ref s == str
1791+
1792+ \note There is a hidden, private overload to disallow references to
1793+ non-const character arrays to be created via this constructor.
1794+ By this, e.g. function-scope arrays used to be filled via
1795+ \c snprintf are excluded from consideration.
1796+ In such cases, the referenced string should be \b copied to the
1797+ GenericValue instead.
1798+ */
1799+ explicit GenericStringRef(const CharType* str)
1800+ : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
1801+
1802+ //! Create constant string reference from pointer and length
1803+ /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
1804+ \param len length of the string, excluding the trailing NULL terminator
1805+
1806+ \post \ref s == str && \ref length == len
1807+ \note Constant complexity.
1808+ */
1809+ GenericStringRef(const CharType* str, SizeType len)
1810+ : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
1811+
1812+ //! implicit conversion to plain CharType pointer
1813+ operator const Ch *() const { return s; }
1814+
1815+ const Ch* const s; //!< plain CharType pointer
1816+ const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
1817+
1818+private:
1819+ //! Disallow copy-assignment
1820+ GenericStringRef operator=(const GenericStringRef&);
1821+ //! Disallow construction from non-const array
1822+ template<SizeType N>
1823+ GenericStringRef(CharType (&str)[N]) /* = delete */;
1824+};
1825+
1826+//! Mark a character pointer as constant string
1827+/*! Mark a plain character pointer as a "string literal". This function
1828+ can be used to avoid copying a character string to be referenced as a
1829+ value in a JSON GenericValue object, if the string's lifetime is known
1830+ to be valid long enough.
1831+ \tparam CharType Character type of the string
1832+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
1833+ \return GenericStringRef string reference object
1834+ \relatesalso GenericStringRef
1835+
1836+ \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
1837+*/
1838+template<typename CharType>
1839+inline GenericStringRef<CharType> StringRef(const CharType* str) {
1840+ return GenericStringRef<CharType>(str, internal::StrLen(str));
1841+}
1842+
1843+//! Mark a character pointer as constant string
1844+/*! Mark a plain character pointer as a "string literal". This function
1845+ can be used to avoid copying a character string to be referenced as a
1846+ value in a JSON GenericValue object, if the string's lifetime is known
1847+ to be valid long enough.
1848+
1849+ This version has better performance with supplied length, and also
1850+ supports string containing null characters.
1851+
1852+ \tparam CharType character type of the string
1853+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
1854+ \param length The length of source string.
1855+ \return GenericStringRef string reference object
1856+ \relatesalso GenericStringRef
1857+*/
1858+template<typename CharType>
1859+inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
1860+ return GenericStringRef<CharType>(str, SizeType(length));
1861+}
1862+
1863+#if RAPIDJSON_HAS_STDSTRING
1864+//! Mark a string object as constant string
1865+/*! Mark a string object (e.g. \c std::string) as a "string literal".
1866+ This function can be used to avoid copying a string to be referenced as a
1867+ value in a JSON GenericValue object, if the string's lifetime is known
1868+ to be valid long enough.
1869+
1870+ \tparam CharType character type of the string
1871+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
1872+ \return GenericStringRef string reference object
1873+ \relatesalso GenericStringRef
1874+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
1875+*/
1876+template<typename CharType>
1877+inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
1878+ return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
1879+}
1880+#endif
1881+
1882+///////////////////////////////////////////////////////////////////////////////
1883+// GenericValue type traits
1884+namespace internal {
1885+
1886+template <typename T, typename Encoding = void, typename Allocator = void>
1887+struct IsGenericValueImpl : FalseType {};
1888+
1889+// select candidates according to nested encoding and allocator types
1890+template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
1891+ : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
1892+
1893+// helper to match arbitrary GenericValue instantiations, including derived classes
1894+template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
1895+
1896+} // namespace internal
1897+
1898+///////////////////////////////////////////////////////////////////////////////
1899+// GenericValue
1900+
1901+//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
1902+/*!
1903+ A JSON value can be one of 7 types. This class is a variant type supporting
1904+ these types.
1905+
1906+ Use the Value if UTF8 and default allocator
1907+
1908+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
1909+ \tparam Allocator Allocator type for allocating memory of object, array and string.
1910+*/
1911+template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
1912+class GenericValue {
1913+public:
1914+ //! Name-value pair in an object.
1915+ typedef GenericMember<Encoding, Allocator> Member;
1916+ typedef Encoding EncodingType; //!< Encoding type from template parameter.
1917+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
1918+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
1919+ typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
1920+ typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
1921+ typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
1922+ typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
1923+ typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
1924+
1925+ //!@name Constructors and destructor.
1926+ //@{
1927+
1928+ //! Default constructor creates a null value.
1929+ GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {}
1930+
1931+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
1932+ //! Move constructor in C++11
1933+ GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) {
1934+ rhs.flags_ = kNullFlag; // give up contents
1935+ }
1936+#endif
1937+
1938+private:
1939+ //! Copy constructor is not permitted.
1940+ GenericValue(const GenericValue& rhs);
1941+
1942+public:
1943+
1944+ //! Constructor with JSON value type.
1945+ /*! This creates a Value of specified type with default content.
1946+ \param type Type of the value.
1947+ \note Default content for number is zero.
1948+ */
1949+ explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
1950+ static const unsigned defaultFlags[7] = {
1951+ kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
1952+ kNumberAnyFlag
1953+ };
1954+ RAPIDJSON_ASSERT(type <= kNumberType);
1955+ flags_ = defaultFlags[type];
1956+
1957+ // Use ShortString to store empty string.
1958+ if (type == kStringType)
1959+ data_.ss.SetLength(0);
1960+ }
1961+
1962+ //! Explicit copy constructor (with allocator)
1963+ /*! Creates a copy of a Value by using the given Allocator
1964+ \tparam SourceAllocator allocator of \c rhs
1965+ \param rhs Value to copy from (read-only)
1966+ \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
1967+ \see CopyFrom()
1968+ */
1969+ template< typename SourceAllocator >
1970+ GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
1971+
1972+ //! Constructor for boolean value.
1973+ /*! \param b Boolean value
1974+ \note This constructor is limited to \em real boolean values and rejects
1975+ implicitly converted types like arbitrary pointers. Use an explicit cast
1976+ to \c bool, if you want to construct a boolean JSON value in such cases.
1977+ */
1978+#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
1979+ template <typename T>
1980+ explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT
1981+#else
1982+ explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
1983+#endif
1984+ : data_(), flags_(b ? kTrueFlag : kFalseFlag) {
1985+ // safe-guard against failing SFINAE
1986+ RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
1987+ }
1988+
1989+ //! Constructor for int value.
1990+ explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) {
1991+ data_.n.i64 = i;
1992+ if (i >= 0)
1993+ flags_ |= kUintFlag | kUint64Flag;
1994+ }
1995+
1996+ //! Constructor for unsigned value.
1997+ explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) {
1998+ data_.n.u64 = u;
1999+ if (!(u & 0x80000000))
2000+ flags_ |= kIntFlag | kInt64Flag;
2001+ }
2002+
2003+ //! Constructor for int64_t value.
2004+ explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) {
2005+ data_.n.i64 = i64;
2006+ if (i64 >= 0) {
2007+ flags_ |= kNumberUint64Flag;
2008+ if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
2009+ flags_ |= kUintFlag;
2010+ if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
2011+ flags_ |= kIntFlag;
2012+ }
2013+ else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
2014+ flags_ |= kIntFlag;
2015+ }
2016+
2017+ //! Constructor for uint64_t value.
2018+ explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
2019+ data_.n.u64 = u64;
2020+ if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
2021+ flags_ |= kInt64Flag;
2022+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
2023+ flags_ |= kUintFlag;
2024+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
2025+ flags_ |= kIntFlag;
2026+ }
2027+
2028+ //! Constructor for double value.
2029+ explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
2030+
2031+ //! Constructor for constant string (i.e. do not make a copy of string)
2032+ GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); }
2033+
2034+ //! Constructor for constant string (i.e. do not make a copy of string)
2035+ explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); }
2036+
2037+ //! Constructor for copy-string (i.e. do make a copy of string)
2038+ GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); }
2039+
2040+ //! Constructor for copy-string (i.e. do make a copy of string)
2041+ GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
2042+
2043+#if RAPIDJSON_HAS_STDSTRING
2044+ //! Constructor for copy-string from a string object (i.e. do make a copy of string)
2045+ /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
2046+ */
2047+ GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
2048+#endif
2049+
2050+ //! Destructor.
2051+ /*! Need to destruct elements of array, members of object, or copy-string.
2052+ */
2053+ ~GenericValue() {
2054+ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
2055+ switch(flags_) {
2056+ case kArrayFlag:
2057+ for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
2058+ v->~GenericValue();
2059+ Allocator::Free(data_.a.elements);
2060+ break;
2061+
2062+ case kObjectFlag:
2063+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
2064+ m->~Member();
2065+ Allocator::Free(data_.o.members);
2066+ break;
2067+
2068+ case kCopyStringFlag:
2069+ Allocator::Free(const_cast<Ch*>(data_.s.str));
2070+ break;
2071+
2072+ default:
2073+ break; // Do nothing for other types.
2074+ }
2075+ }
2076+ }
2077+
2078+ //@}
2079+
2080+ //!@name Assignment operators
2081+ //@{
2082+
2083+ //! Assignment with move semantics.
2084+ /*! \param rhs Source of the assignment. It will become a null value after assignment.
2085+ */
2086+ GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
2087+ RAPIDJSON_ASSERT(this != &rhs);
2088+ this->~GenericValue();
2089+ RawAssign(rhs);
2090+ return *this;
2091+ }
2092+
2093+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
2094+ //! Move assignment in C++11
2095+ GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
2096+ return *this = rhs.Move();
2097+ }
2098+#endif
2099+
2100+ //! Assignment of constant string reference (no copy)
2101+ /*! \param str Constant string reference to be assigned
2102+ \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
2103+ \see GenericStringRef, operator=(T)
2104+ */
2105+ GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
2106+ GenericValue s(str);
2107+ return *this = s;
2108+ }
2109+
2110+ //! Assignment with primitive types.
2111+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
2112+ \param value The value to be assigned.
2113+
2114+ \note The source type \c T explicitly disallows all pointer types,
2115+ especially (\c const) \ref Ch*. This helps avoiding implicitly
2116+ referencing character strings with insufficient lifetime, use
2117+ \ref SetString(const Ch*, Allocator&) (for copying) or
2118+ \ref StringRef() (to explicitly mark the pointer as constant) instead.
2119+ All other pointer types would implicitly convert to \c bool,
2120+ use \ref SetBool() instead.
2121+ */
2122+ template <typename T>
2123+ RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
2124+ operator=(T value) {
2125+ GenericValue v(value);
2126+ return *this = v;
2127+ }
2128+
2129+ //! Deep-copy assignment from Value
2130+ /*! Assigns a \b copy of the Value to the current Value object
2131+ \tparam SourceAllocator Allocator type of \c rhs
2132+ \param rhs Value to copy from (read-only)
2133+ \param allocator Allocator to use for copying
2134+ */
2135+ template <typename SourceAllocator>
2136+ GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
2137+ RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
2138+ this->~GenericValue();
2139+ new (this) GenericValue(rhs, allocator);
2140+ return *this;
2141+ }
2142+
2143+ //! Exchange the contents of this value with those of other.
2144+ /*!
2145+ \param other Another value.
2146+ \note Constant complexity.
2147+ */
2148+ GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
2149+ GenericValue temp;
2150+ temp.RawAssign(*this);
2151+ RawAssign(other);
2152+ other.RawAssign(temp);
2153+ return *this;
2154+ }
2155+
2156+ //! Prepare Value for move semantics
2157+ /*! \return *this */
2158+ GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
2159+ //@}
2160+
2161+ //!@name Equal-to and not-equal-to operators
2162+ //@{
2163+ //! Equal-to operator
2164+ /*!
2165+ \note If an object contains duplicated named member, comparing equality with any object is always \c false.
2166+ \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
2167+ */
2168+ template <typename SourceAllocator>
2169+ bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
2170+ typedef GenericValue<Encoding, SourceAllocator> RhsType;
2171+ if (GetType() != rhs.GetType())
2172+ return false;
2173+
2174+ switch (GetType()) {
2175+ case kObjectType: // Warning: O(n^2) inner-loop
2176+ if (data_.o.size != rhs.data_.o.size)
2177+ return false;
2178+ for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
2179+ typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
2180+ if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
2181+ return false;
2182+ }
2183+ return true;
2184+
2185+ case kArrayType:
2186+ if (data_.a.size != rhs.data_.a.size)
2187+ return false;
2188+ for (SizeType i = 0; i < data_.a.size; i++)
2189+ if ((*this)[i] != rhs[i])
2190+ return false;
2191+ return true;
2192+
2193+ case kStringType:
2194+ return StringEqual(rhs);
2195+
2196+ case kNumberType:
2197+ if (IsDouble() || rhs.IsDouble())
2198+ return GetDouble() == rhs.GetDouble(); // May convert one operand from integer to double.
2199+ else
2200+ return data_.n.u64 == rhs.data_.n.u64;
2201+
2202+ default: // kTrueType, kFalseType, kNullType
2203+ return true;
2204+ }
2205+ }
2206+
2207+ //! Equal-to operator with const C-string pointer
2208+ bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
2209+
2210+#if RAPIDJSON_HAS_STDSTRING
2211+ //! Equal-to operator with string object
2212+ /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
2213+ */
2214+ bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
2215+#endif
2216+
2217+ //! Equal-to operator with primitive types
2218+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
2219+ */
2220+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
2221+
2222+ //! Not-equal-to operator
2223+ /*! \return !(*this == rhs)
2224+ */
2225+ template <typename SourceAllocator>
2226+ bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
2227+
2228+ //! Not-equal-to operator with const C-string pointer
2229+ bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
2230+
2231+ //! Not-equal-to operator with arbitrary types
2232+ /*! \return !(*this == rhs)
2233+ */
2234+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
2235+
2236+ //! Equal-to operator with arbitrary types (symmetric version)
2237+ /*! \return (rhs == lhs)
2238+ */
2239+ template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
2240+
2241+ //! Not-Equal-to operator with arbitrary types (symmetric version)
2242+ /*! \return !(rhs == lhs)
2243+ */
2244+ template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
2245+ //@}
2246+
2247+ //!@name Type
2248+ //@{
2249+
2250+ Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); }
2251+ bool IsNull() const { return flags_ == kNullFlag; }
2252+ bool IsFalse() const { return flags_ == kFalseFlag; }
2253+ bool IsTrue() const { return flags_ == kTrueFlag; }
2254+ bool IsBool() const { return (flags_ & kBoolFlag) != 0; }
2255+ bool IsObject() const { return flags_ == kObjectFlag; }
2256+ bool IsArray() const { return flags_ == kArrayFlag; }
2257+ bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
2258+ bool IsInt() const { return (flags_ & kIntFlag) != 0; }
2259+ bool IsUint() const { return (flags_ & kUintFlag) != 0; }
2260+ bool IsInt64() const { return (flags_ & kInt64Flag) != 0; }
2261+ bool IsUint64() const { return (flags_ & kUint64Flag) != 0; }
2262+ bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
2263+ bool IsString() const { return (flags_ & kStringFlag) != 0; }
2264+
2265+ //@}
2266+
2267+ //!@name Null
2268+ //@{
2269+
2270+ GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
2271+
2272+ //@}
2273+
2274+ //!@name Bool
2275+ //@{
2276+
2277+ bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
2278+ //!< Set boolean value
2279+ /*! \post IsBool() == true */
2280+ GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
2281+
2282+ //@}
2283+
2284+ //!@name Object
2285+ //@{
2286+
2287+ //! Set this value as an empty object.
2288+ /*! \post IsObject() == true */
2289+ GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
2290+
2291+ //! Get the number of members in the object.
2292+ SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
2293+
2294+ //! Check whether the object is empty.
2295+ bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
2296+
2297+ //! Get a value from an object associated with the name.
2298+ /*! \pre IsObject() == true
2299+ \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
2300+ \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
2301+ Since 0.2, if the name is not correct, it will assert.
2302+ If user is unsure whether a member exists, user should use HasMember() first.
2303+ A better approach is to use FindMember().
2304+ \note Linear time complexity.
2305+ */
2306+ template <typename T>
2307+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
2308+ GenericValue n(StringRef(name));
2309+ return (*this)[n];
2310+ }
2311+ template <typename T>
2312+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
2313+
2314+ //! Get a value from an object associated with the name.
2315+ /*! \pre IsObject() == true
2316+ \tparam SourceAllocator Allocator of the \c name value
2317+
2318+ \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
2319+ And it can also handle strings with embedded null characters.
2320+
2321+ \note Linear time complexity.
2322+ */
2323+ template <typename SourceAllocator>
2324+ GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
2325+ MemberIterator member = FindMember(name);
2326+ if (member != MemberEnd())
2327+ return member->value;
2328+ else {
2329+ RAPIDJSON_ASSERT(false); // see above note
2330+ static GenericValue NullValue;
2331+ return NullValue;
2332+ }
2333+ }
2334+ template <typename SourceAllocator>
2335+ const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
2336+
2337+ //! Const member iterator
2338+ /*! \pre IsObject() == true */
2339+ ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
2340+ //! Const \em past-the-end member iterator
2341+ /*! \pre IsObject() == true */
2342+ ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); }
2343+ //! Member iterator
2344+ /*! \pre IsObject() == true */
2345+ MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); }
2346+ //! \em Past-the-end member iterator
2347+ /*! \pre IsObject() == true */
2348+ MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); }
2349+
2350+ //! Check whether a member exists in the object.
2351+ /*!
2352+ \param name Member name to be searched.
2353+ \pre IsObject() == true
2354+ \return Whether a member with that name exists.
2355+ \note It is better to use FindMember() directly if you need the obtain the value as well.
2356+ \note Linear time complexity.
2357+ */
2358+ bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
2359+
2360+ //! Check whether a member exists in the object with GenericValue name.
2361+ /*!
2362+ This version is faster because it does not need a StrLen(). It can also handle string with null character.
2363+ \param name Member name to be searched.
2364+ \pre IsObject() == true
2365+ \return Whether a member with that name exists.
2366+ \note It is better to use FindMember() directly if you need the obtain the value as well.
2367+ \note Linear time complexity.
2368+ */
2369+ template <typename SourceAllocator>
2370+ bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
2371+
2372+ //! Find member by name.
2373+ /*!
2374+ \param name Member name to be searched.
2375+ \pre IsObject() == true
2376+ \return Iterator to member, if it exists.
2377+ Otherwise returns \ref MemberEnd().
2378+
2379+ \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
2380+ the requested member doesn't exist. For consistency with e.g.
2381+ \c std::map, this has been changed to MemberEnd() now.
2382+ \note Linear time complexity.
2383+ */
2384+ MemberIterator FindMember(const Ch* name) {
2385+ GenericValue n(StringRef(name));
2386+ return FindMember(n);
2387+ }
2388+
2389+ ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
2390+
2391+ //! Find member by name.
2392+ /*!
2393+ This version is faster because it does not need a StrLen(). It can also handle string with null character.
2394+ \param name Member name to be searched.
2395+ \pre IsObject() == true
2396+ \return Iterator to member, if it exists.
2397+ Otherwise returns \ref MemberEnd().
2398+
2399+ \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
2400+ the requested member doesn't exist. For consistency with e.g.
2401+ \c std::map, this has been changed to MemberEnd() now.
2402+ \note Linear time complexity.
2403+ */
2404+ template <typename SourceAllocator>
2405+ MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
2406+ RAPIDJSON_ASSERT(IsObject());
2407+ RAPIDJSON_ASSERT(name.IsString());
2408+ MemberIterator member = MemberBegin();
2409+ for ( ; member != MemberEnd(); ++member)
2410+ if (name.StringEqual(member->name))
2411+ break;
2412+ return member;
2413+ }
2414+ template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
2415+
2416+ //! Add a member (name-value pair) to the object.
2417+ /*! \param name A string value as name of member.
2418+ \param value Value of any type.
2419+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
2420+ \return The value itself for fluent API.
2421+ \note The ownership of \c name and \c value will be transferred to this object on success.
2422+ \pre IsObject() && name.IsString()
2423+ \post name.IsNull() && value.IsNull()
2424+ \note Amortized Constant time complexity.
2425+ */
2426+ GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
2427+ RAPIDJSON_ASSERT(IsObject());
2428+ RAPIDJSON_ASSERT(name.IsString());
2429+
2430+ Object& o = data_.o;
2431+ if (o.size >= o.capacity) {
2432+ if (o.capacity == 0) {
2433+ o.capacity = kDefaultObjectCapacity;
2434+ o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)));
2435+ }
2436+ else {
2437+ SizeType oldCapacity = o.capacity;
2438+ o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
2439+ o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)));
2440+ }
2441+ }
2442+ o.members[o.size].name.RawAssign(name);
2443+ o.members[o.size].value.RawAssign(value);
2444+ o.size++;
2445+ return *this;
2446+ }
2447+
2448+ //! Add a constant string value as member (name-value pair) to the object.
2449+ /*! \param name A string value as name of member.
2450+ \param value constant string reference as value of member.
2451+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
2452+ \return The value itself for fluent API.
2453+ \pre IsObject()
2454+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
2455+ \note Amortized Constant time complexity.
2456+ */
2457+ GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
2458+ GenericValue v(value);
2459+ return AddMember(name, v, allocator);
2460+ }
2461+
2462+ //! Add any primitive value as member (name-value pair) to the object.
2463+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
2464+ \param name A string value as name of member.
2465+ \param value Value of primitive type \c T as value of member
2466+ \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
2467+ \return The value itself for fluent API.
2468+ \pre IsObject()
2469+
2470+ \note The source type \c T explicitly disallows all pointer types,
2471+ especially (\c const) \ref Ch*. This helps avoiding implicitly
2472+ referencing character strings with insufficient lifetime, use
2473+ \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
2474+ AddMember(StringRefType, StringRefType, Allocator&).
2475+ All other pointer types would implicitly convert to \c bool,
2476+ use an explicit cast instead, if needed.
2477+ \note Amortized Constant time complexity.
2478+ */
2479+ template <typename T>
2480+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
2481+ AddMember(GenericValue& name, T value, Allocator& allocator) {
2482+ GenericValue v(value);
2483+ return AddMember(name, v, allocator);
2484+ }
2485+
2486+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
2487+ GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
2488+ return AddMember(name, value, allocator);
2489+ }
2490+ GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
2491+ return AddMember(name, value, allocator);
2492+ }
2493+ GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
2494+ return AddMember(name, value, allocator);
2495+ }
2496+ GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
2497+ GenericValue n(name);
2498+ return AddMember(n, value, allocator);
2499+ }
2500+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
2501+
2502+
2503+ //! Add a member (name-value pair) to the object.
2504+ /*! \param name A constant string reference as name of member.
2505+ \param value Value of any type.
2506+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
2507+ \return The value itself for fluent API.
2508+ \note The ownership of \c value will be transferred to this object on success.
2509+ \pre IsObject()
2510+ \post value.IsNull()
2511+ \note Amortized Constant time complexity.
2512+ */
2513+ GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
2514+ GenericValue n(name);
2515+ return AddMember(n, value, allocator);
2516+ }
2517+
2518+ //! Add a constant string value as member (name-value pair) to the object.
2519+ /*! \param name A constant string reference as name of member.
2520+ \param value constant string reference as value of member.
2521+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
2522+ \return The value itself for fluent API.
2523+ \pre IsObject()
2524+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
2525+ \note Amortized Constant time complexity.
2526+ */
2527+ GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
2528+ GenericValue v(value);
2529+ return AddMember(name, v, allocator);
2530+ }
2531+
2532+ //! Add any primitive value as member (name-value pair) to the object.
2533+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
2534+ \param name A constant string reference as name of member.
2535+ \param value Value of primitive type \c T as value of member
2536+ \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
2537+ \return The value itself for fluent API.
2538+ \pre IsObject()
2539+
2540+ \note The source type \c T explicitly disallows all pointer types,
2541+ especially (\c const) \ref Ch*. This helps avoiding implicitly
2542+ referencing character strings with insufficient lifetime, use
2543+ \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
2544+ AddMember(StringRefType, StringRefType, Allocator&).
2545+ All other pointer types would implicitly convert to \c bool,
2546+ use an explicit cast instead, if needed.
2547+ \note Amortized Constant time complexity.
2548+ */
2549+ template <typename T>
2550+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
2551+ AddMember(StringRefType name, T value, Allocator& allocator) {
2552+ GenericValue n(name);
2553+ return AddMember(n, value, allocator);
2554+ }
2555+
2556+ //! Remove all members in the object.
2557+ /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
2558+ \note Linear time complexity.
2559+ */
2560+ void RemoveAllMembers() {
2561+ RAPIDJSON_ASSERT(IsObject());
2562+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
2563+ m->~Member();
2564+ data_.o.size = 0;
2565+ }
2566+
2567+ //! Remove a member in object by its name.
2568+ /*! \param name Name of member to be removed.
2569+ \return Whether the member existed.
2570+ \note This function may reorder the object members. Use \ref
2571+ EraseMember(ConstMemberIterator) if you need to preserve the
2572+ relative order of the remaining members.
2573+ \note Linear time complexity.
2574+ */
2575+ bool RemoveMember(const Ch* name) {
2576+ GenericValue n(StringRef(name));
2577+ return RemoveMember(n);
2578+ }
2579+
2580+ template <typename SourceAllocator>
2581+ bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
2582+ MemberIterator m = FindMember(name);
2583+ if (m != MemberEnd()) {
2584+ RemoveMember(m);
2585+ return true;
2586+ }
2587+ else
2588+ return false;
2589+ }
2590+
2591+ //! Remove a member in object by iterator.
2592+ /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
2593+ \return the new iterator after removal.
2594+ \note This function may reorder the object members. Use \ref
2595+ EraseMember(ConstMemberIterator) if you need to preserve the
2596+ relative order of the remaining members.
2597+ \note Constant time complexity.
2598+ */
2599+ MemberIterator RemoveMember(MemberIterator m) {
2600+ RAPIDJSON_ASSERT(IsObject());
2601+ RAPIDJSON_ASSERT(data_.o.size > 0);
2602+ RAPIDJSON_ASSERT(data_.o.members != 0);
2603+ RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
2604+
2605+ MemberIterator last(data_.o.members + (data_.o.size - 1));
2606+ if (data_.o.size > 1 && m != last) {
2607+ // Move the last one to this place
2608+ *m = *last;
2609+ }
2610+ else {
2611+ // Only one left, just destroy
2612+ m->~Member();
2613+ }
2614+ --data_.o.size;
2615+ return m;
2616+ }
2617+
2618+ //! Remove a member from an object by iterator.
2619+ /*! \param pos iterator to the member to remove
2620+ \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
2621+ \return Iterator following the removed element.
2622+ If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
2623+ \note This function preserves the relative order of the remaining object
2624+ members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
2625+ \note Linear time complexity.
2626+ */
2627+ MemberIterator EraseMember(ConstMemberIterator pos) {
2628+ return EraseMember(pos, pos +1);
2629+ }
2630+
2631+ //! Remove members in the range [first, last) from an object.
2632+ /*! \param first iterator to the first member to remove
2633+ \param last iterator following the last member to remove
2634+ \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
2635+ \return Iterator following the last removed element.
2636+ \note This function preserves the relative order of the remaining object
2637+ members.
2638+ \note Linear time complexity.
2639+ */
2640+ MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
2641+ RAPIDJSON_ASSERT(IsObject());
2642+ RAPIDJSON_ASSERT(data_.o.size > 0);
2643+ RAPIDJSON_ASSERT(data_.o.members != 0);
2644+ RAPIDJSON_ASSERT(first >= MemberBegin());
2645+ RAPIDJSON_ASSERT(first <= last);
2646+ RAPIDJSON_ASSERT(last <= MemberEnd());
2647+
2648+ MemberIterator pos = MemberBegin() + (first - MemberBegin());
2649+ for (MemberIterator itr = pos; itr != last; ++itr)
2650+ itr->~Member();
2651+ std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member));
2652+ data_.o.size -= (last - first);
2653+ return pos;
2654+ }
2655+
2656+ //@}
2657+
2658+ //!@name Array
2659+ //@{
2660+
2661+ //! Set this value as an empty array.
2662+ /*! \post IsArray == true */
2663+ GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
2664+
2665+ //! Get the number of elements in array.
2666+ SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
2667+
2668+ //! Get the capacity of array.
2669+ SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
2670+
2671+ //! Check whether the array is empty.
2672+ bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
2673+
2674+ //! Remove all elements in the array.
2675+ /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
2676+ \note Linear time complexity.
2677+ */
2678+ void Clear() {
2679+ RAPIDJSON_ASSERT(IsArray());
2680+ for (SizeType i = 0; i < data_.a.size; ++i)
2681+ data_.a.elements[i].~GenericValue();
2682+ data_.a.size = 0;
2683+ }
2684+
2685+ //! Get an element from array by index.
2686+ /*! \pre IsArray() == true
2687+ \param index Zero-based index of element.
2688+ \see operator[](T*)
2689+ */
2690+ GenericValue& operator[](SizeType index) {
2691+ RAPIDJSON_ASSERT(IsArray());
2692+ RAPIDJSON_ASSERT(index < data_.a.size);
2693+ return data_.a.elements[index];
2694+ }
2695+ const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
2696+
2697+ //! Element iterator
2698+ /*! \pre IsArray() == true */
2699+ ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
2700+ //! \em Past-the-end element iterator
2701+ /*! \pre IsArray() == true */
2702+ ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
2703+ //! Constant element iterator
2704+ /*! \pre IsArray() == true */
2705+ ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
2706+ //! Constant \em past-the-end element iterator
2707+ /*! \pre IsArray() == true */
2708+ ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
2709+
2710+ //! Request the array to have enough capacity to store elements.
2711+ /*! \param newCapacity The capacity that the array at least need to have.
2712+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
2713+ \return The value itself for fluent API.
2714+ \note Linear time complexity.
2715+ */
2716+ GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
2717+ RAPIDJSON_ASSERT(IsArray());
2718+ if (newCapacity > data_.a.capacity) {
2719+ data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
2720+ data_.a.capacity = newCapacity;
2721+ }
2722+ return *this;
2723+ }
2724+
2725+ //! Append a GenericValue at the end of the array.
2726+ /*! \param value Value to be appended.
2727+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
2728+ \pre IsArray() == true
2729+ \post value.IsNull() == true
2730+ \return The value itself for fluent API.
2731+ \note The ownership of \c value will be transferred to this array on success.
2732+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
2733+ \note Amortized constant time complexity.
2734+ */
2735+ GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
2736+ RAPIDJSON_ASSERT(IsArray());
2737+ if (data_.a.size >= data_.a.capacity)
2738+ Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
2739+ data_.a.elements[data_.a.size++].RawAssign(value);
2740+ return *this;
2741+ }
2742+
2743+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
2744+ GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
2745+ return PushBack(value, allocator);
2746+ }
2747+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
2748+
2749+ //! Append a constant string reference at the end of the array.
2750+ /*! \param value Constant string reference to be appended.
2751+ \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
2752+ \pre IsArray() == true
2753+ \return The value itself for fluent API.
2754+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
2755+ \note Amortized constant time complexity.
2756+ \see GenericStringRef
2757+ */
2758+ GenericValue& PushBack(StringRefType value, Allocator& allocator) {
2759+ return (*this).template PushBack<StringRefType>(value, allocator);
2760+ }
2761+
2762+ //! Append a primitive value at the end of the array.
2763+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
2764+ \param value Value of primitive type T to be appended.
2765+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
2766+ \pre IsArray() == true
2767+ \return The value itself for fluent API.
2768+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
2769+
2770+ \note The source type \c T explicitly disallows all pointer types,
2771+ especially (\c const) \ref Ch*. This helps avoiding implicitly
2772+ referencing character strings with insufficient lifetime, use
2773+ \ref PushBack(GenericValue&, Allocator&) or \ref
2774+ PushBack(StringRefType, Allocator&).
2775+ All other pointer types would implicitly convert to \c bool,
2776+ use an explicit cast instead, if needed.
2777+ \note Amortized constant time complexity.
2778+ */
2779+ template <typename T>
2780+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
2781+ PushBack(T value, Allocator& allocator) {
2782+ GenericValue v(value);
2783+ return PushBack(v, allocator);
2784+ }
2785+
2786+ //! Remove the last element in the array.
2787+ /*!
2788+ \note Constant time complexity.
2789+ */
2790+ GenericValue& PopBack() {
2791+ RAPIDJSON_ASSERT(IsArray());
2792+ RAPIDJSON_ASSERT(!Empty());
2793+ data_.a.elements[--data_.a.size].~GenericValue();
2794+ return *this;
2795+ }
2796+
2797+ //! Remove an element of array by iterator.
2798+ /*!
2799+ \param pos iterator to the element to remove
2800+ \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
2801+ \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
2802+ \note Linear time complexity.
2803+ */
2804+ ValueIterator Erase(ConstValueIterator pos) {
2805+ return Erase(pos, pos + 1);
2806+ }
2807+
2808+ //! Remove elements in the range [first, last) of the array.
2809+ /*!
2810+ \param first iterator to the first element to remove
2811+ \param last iterator following the last element to remove
2812+ \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
2813+ \return Iterator following the last removed element.
2814+ \note Linear time complexity.
2815+ */
2816+ ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
2817+ RAPIDJSON_ASSERT(IsArray());
2818+ RAPIDJSON_ASSERT(data_.a.size > 0);
2819+ RAPIDJSON_ASSERT(data_.a.elements != 0);
2820+ RAPIDJSON_ASSERT(first >= Begin());
2821+ RAPIDJSON_ASSERT(first <= last);
2822+ RAPIDJSON_ASSERT(last <= End());
2823+ ValueIterator pos = Begin() + (first - Begin());
2824+ for (ValueIterator itr = pos; itr != last; ++itr)
2825+ itr->~GenericValue();
2826+ std::memmove(pos, last, (End() - last) * sizeof(GenericValue));
2827+ data_.a.size -= (last - first);
2828+ return pos;
2829+ }
2830+
2831+ //@}
2832+
2833+ //!@name Number
2834+ //@{
2835+
2836+ int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; }
2837+ unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; }
2838+ int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
2839+ uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
2840+
2841+ double GetDouble() const {
2842+ RAPIDJSON_ASSERT(IsNumber());
2843+ if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
2844+ if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double
2845+ if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
2846+ if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision)
2847+ RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision)
2848+ }
2849+
2850+ GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
2851+ GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
2852+ GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
2853+ GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
2854+ GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
2855+
2856+ //@}
2857+
2858+ //!@name String
2859+ //@{
2860+
2861+ const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); }
2862+
2863+ //! Get the length of string.
2864+ /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
2865+ */
2866+ SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
2867+
2868+ //! Set this value as a string without copying source string.
2869+ /*! This version has better performance with supplied length, and also support string containing null character.
2870+ \param s source string pointer.
2871+ \param length The length of source string, excluding the trailing null terminator.
2872+ \return The value itself for fluent API.
2873+ \post IsString() == true && GetString() == s && GetStringLength() == length
2874+ \see SetString(StringRefType)
2875+ */
2876+ GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
2877+
2878+ //! Set this value as a string without copying source string.
2879+ /*! \param s source string reference
2880+ \return The value itself for fluent API.
2881+ \post IsString() == true && GetString() == s && GetStringLength() == s.length
2882+ */
2883+ GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
2884+
2885+ //! Set this value as a string by copying from source string.
2886+ /*! This version has better performance with supplied length, and also support string containing null character.
2887+ \param s source string.
2888+ \param length The length of source string, excluding the trailing null terminator.
2889+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
2890+ \return The value itself for fluent API.
2891+ \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
2892+ */
2893+ GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
2894+
2895+ //! Set this value as a string by copying from source string.
2896+ /*! \param s source string.
2897+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
2898+ \return The value itself for fluent API.
2899+ \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
2900+ */
2901+ GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
2902+
2903+#if RAPIDJSON_HAS_STDSTRING
2904+ //! Set this value as a string by copying from source string.
2905+ /*! \param s source string.
2906+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
2907+ \return The value itself for fluent API.
2908+ \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
2909+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
2910+ */
2911+ GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); }
2912+#endif
2913+
2914+ //@}
2915+
2916+ //! Generate events of this value to a Handler.
2917+ /*! This function adopts the GoF visitor pattern.
2918+ Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
2919+ It can also be used to deep clone this value via GenericDocument, which is also a Handler.
2920+ \tparam Handler type of handler.
2921+ \param handler An object implementing concept Handler.
2922+ */
2923+ template <typename Handler>
2924+ bool Accept(Handler& handler) const {
2925+ switch(GetType()) {
2926+ case kNullType: return handler.Null();
2927+ case kFalseType: return handler.Bool(false);
2928+ case kTrueType: return handler.Bool(true);
2929+
2930+ case kObjectType:
2931+ if (!handler.StartObject())
2932+ return false;
2933+ for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
2934+ RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
2935+ if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0))
2936+ return false;
2937+ if (!m->value.Accept(handler))
2938+ return false;
2939+ }
2940+ return handler.EndObject(data_.o.size);
2941+
2942+ case kArrayType:
2943+ if (!handler.StartArray())
2944+ return false;
2945+ for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
2946+ if (!v->Accept(handler))
2947+ return false;
2948+ return handler.EndArray(data_.a.size);
2949+
2950+ case kStringType:
2951+ return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
2952+
2953+ case kNumberType:
2954+ if (IsInt()) return handler.Int(data_.n.i.i);
2955+ else if (IsUint()) return handler.Uint(data_.n.u.u);
2956+ else if (IsInt64()) return handler.Int64(data_.n.i64);
2957+ else if (IsUint64()) return handler.Uint64(data_.n.u64);
2958+ else return handler.Double(data_.n.d);
2959+
2960+ default:
2961+ RAPIDJSON_ASSERT(false);
2962+ }
2963+ return false;
2964+ }
2965+
2966+private:
2967+ template <typename, typename> friend class GenericValue;
2968+ template <typename, typename, typename> friend class GenericDocument;
2969+
2970+ enum {
2971+ kBoolFlag = 0x100,
2972+ kNumberFlag = 0x200,
2973+ kIntFlag = 0x400,
2974+ kUintFlag = 0x800,
2975+ kInt64Flag = 0x1000,
2976+ kUint64Flag = 0x2000,
2977+ kDoubleFlag = 0x4000,
2978+ kStringFlag = 0x100000,
2979+ kCopyFlag = 0x200000,
2980+ kInlineStrFlag = 0x400000,
2981+
2982+ // Initial flags of different types.
2983+ kNullFlag = kNullType,
2984+ kTrueFlag = kTrueType | kBoolFlag,
2985+ kFalseFlag = kFalseType | kBoolFlag,
2986+ kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
2987+ kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
2988+ kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
2989+ kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
2990+ kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
2991+ kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
2992+ kConstStringFlag = kStringType | kStringFlag,
2993+ kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
2994+ kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
2995+ kObjectFlag = kObjectType,
2996+ kArrayFlag = kArrayType,
2997+
2998+ kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler
2999+ };
3000+
3001+ static const SizeType kDefaultArrayCapacity = 16;
3002+ static const SizeType kDefaultObjectCapacity = 16;
3003+
3004+ struct String {
3005+ const Ch* str;
3006+ SizeType length;
3007+ unsigned hashcode; //!< reserved
3008+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
3009+
3010+ // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
3011+ // (excluding the terminating zero) and store a value to determine the length of the contained
3012+ // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
3013+ // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
3014+ // the string terminator as well. For getting the string length back from that value just use
3015+ // "MaxSize - str[LenPos]".
3016+ // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode
3017+ // inline (for `UTF8`-encoded strings).
3018+ struct ShortString {
3019+ enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
3020+ Ch str[MaxChars];
3021+
3022+ inline static bool Usable(SizeType len) { return (MaxSize >= len); }
3023+ inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); }
3024+ inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); }
3025+ }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
3026+
3027+ // By using proper binary layout, retrieval of different integer types do not need conversions.
3028+ union Number {
3029+#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
3030+ struct I {
3031+ int i;
3032+ char padding[4];
3033+ }i;
3034+ struct U {
3035+ unsigned u;
3036+ char padding2[4];
3037+ }u;
3038+#else
3039+ struct I {
3040+ char padding[4];
3041+ int i;
3042+ }i;
3043+ struct U {
3044+ char padding2[4];
3045+ unsigned u;
3046+ }u;
3047+#endif
3048+ int64_t i64;
3049+ uint64_t u64;
3050+ double d;
3051+ }; // 8 bytes
3052+
3053+ struct Object {
3054+ Member* members;
3055+ SizeType size;
3056+ SizeType capacity;
3057+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
3058+
3059+ struct Array {
3060+ GenericValue* elements;
3061+ SizeType size;
3062+ SizeType capacity;
3063+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
3064+
3065+ union Data {
3066+ String s;
3067+ ShortString ss;
3068+ Number n;
3069+ Object o;
3070+ Array a;
3071+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
3072+
3073+ // Initialize this value as array with initial data, without calling destructor.
3074+ void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
3075+ flags_ = kArrayFlag;
3076+ data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
3077+ std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
3078+ data_.a.size = data_.a.capacity = count;
3079+ }
3080+
3081+ //! Initialize this value as object with initial data, without calling destructor.
3082+ void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
3083+ flags_ = kObjectFlag;
3084+ data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
3085+ std::memcpy(data_.o.members, members, count * sizeof(Member));
3086+ data_.o.size = data_.o.capacity = count;
3087+ }
3088+
3089+ //! Initialize this value as constant string, without calling destructor.
3090+ void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
3091+ flags_ = kConstStringFlag;
3092+ data_.s.str = s;
3093+ data_.s.length = s.length;
3094+ }
3095+
3096+ //! Initialize this value as copy string with initial data, without calling destructor.
3097+ void SetStringRaw(StringRefType s, Allocator& allocator) {
3098+ Ch* str = NULL;
3099+ if(ShortString::Usable(s.length)) {
3100+ flags_ = kShortStringFlag;
3101+ data_.ss.SetLength(s.length);
3102+ str = data_.ss.str;
3103+ } else {
3104+ flags_ = kCopyStringFlag;
3105+ data_.s.length = s.length;
3106+ str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
3107+ data_.s.str = str;
3108+ }
3109+ std::memcpy(str, s, s.length * sizeof(Ch));
3110+ str[s.length] = '\0';
3111+ }
3112+
3113+ //! Assignment without calling destructor
3114+ void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
3115+ data_ = rhs.data_;
3116+ flags_ = rhs.flags_;
3117+ rhs.flags_ = kNullFlag;
3118+ }
3119+
3120+ template <typename SourceAllocator>
3121+ bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
3122+ RAPIDJSON_ASSERT(IsString());
3123+ RAPIDJSON_ASSERT(rhs.IsString());
3124+
3125+ const SizeType len1 = GetStringLength();
3126+ const SizeType len2 = rhs.GetStringLength();
3127+ if(len1 != len2) { return false; }
3128+
3129+ const Ch* const str1 = GetString();
3130+ const Ch* const str2 = rhs.GetString();
3131+ if(str1 == str2) { return true; } // fast path for constant string
3132+
3133+ return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
3134+ }
3135+
3136+ Data data_;
3137+ unsigned flags_;
3138+};
3139+
3140+//! GenericValue with UTF8 encoding
3141+typedef GenericValue<UTF8<> > Value;
3142+
3143+///////////////////////////////////////////////////////////////////////////////
3144+// GenericDocument
3145+
3146+//! A document for parsing JSON text as DOM.
3147+/*!
3148+ \note implements Handler concept
3149+ \tparam Encoding Encoding for both parsing and string storage.
3150+ \tparam Allocator Allocator for allocating memory for the DOM
3151+ \tparam StackAllocator Allocator for allocating memory for stack during parsing.
3152+ \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
3153+*/
3154+template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
3155+class GenericDocument : public GenericValue<Encoding, Allocator> {
3156+public:
3157+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
3158+ typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
3159+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
3160+
3161+ //! Constructor
3162+ /*! \param allocator Optional allocator for allocating memory.
3163+ \param stackCapacity Optional initial capacity of stack in bytes.
3164+ \param stackAllocator Optional allocator for allocating memory for stack.
3165+ */
3166+ GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
3167+ allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
3168+ {
3169+ if (!allocator_)
3170+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
3171+ }
3172+
3173+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
3174+ //! Move constructor in C++11
3175+ GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
3176+ : ValueType(std::move(rhs)),
3177+ allocator_(rhs.allocator_),
3178+ ownAllocator_(rhs.ownAllocator_),
3179+ stack_(std::move(rhs.stack_)),
3180+ parseResult_(rhs.parseResult_)
3181+ {
3182+ rhs.allocator_ = 0;
3183+ rhs.ownAllocator_ = 0;
3184+ rhs.parseResult_ = ParseResult();
3185+ }
3186+#endif
3187+
3188+ ~GenericDocument() {
3189+ Destroy();
3190+ }
3191+
3192+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
3193+ //! Move assignment in C++11
3194+ GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
3195+ {
3196+ // The cast to ValueType is necessary here, because otherwise it would
3197+ // attempt to call GenericValue's templated assignment operator.
3198+ ValueType::operator=(std::forward<ValueType>(rhs));
3199+
3200+ // Calling the destructor here would prematurely call stack_'s destructor
3201+ Destroy();
3202+
3203+ allocator_ = rhs.allocator_;
3204+ ownAllocator_ = rhs.ownAllocator_;
3205+ stack_ = std::move(rhs.stack_);
3206+ parseResult_ = rhs.parseResult_;
3207+
3208+ rhs.allocator_ = 0;
3209+ rhs.ownAllocator_ = 0;
3210+ rhs.parseResult_ = ParseResult();
3211+
3212+ return *this;
3213+ }
3214+#endif
3215+
3216+ //!@name Parse from stream
3217+ //!@{
3218+
3219+ //! Parse JSON text from an input stream (with Encoding conversion)
3220+ /*! \tparam parseFlags Combination of \ref ParseFlag.
3221+ \tparam SourceEncoding Encoding of input stream
3222+ \tparam InputStream Type of input stream, implementing Stream concept
3223+ \param is Input stream to be parsed.
3224+ \return The document itself for fluent API.
3225+ */
3226+ template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
3227+ GenericDocument& ParseStream(InputStream& is) {
3228+ ValueType::SetNull(); // Remove existing root if exist
3229+ GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
3230+ ClearStackOnExit scope(*this);
3231+ parseResult_ = reader.template Parse<parseFlags>(is, *this);
3232+ if (parseResult_) {
3233+ RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
3234+ this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
3235+ }
3236+ return *this;
3237+ }
3238+
3239+ //! Parse JSON text from an input stream
3240+ /*! \tparam parseFlags Combination of \ref ParseFlag.
3241+ \tparam InputStream Type of input stream, implementing Stream concept
3242+ \param is Input stream to be parsed.
3243+ \return The document itself for fluent API.
3244+ */
3245+ template <unsigned parseFlags, typename InputStream>
3246+ GenericDocument& ParseStream(InputStream& is) {
3247+ return ParseStream<parseFlags,Encoding,InputStream>(is);
3248+ }
3249+
3250+ //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
3251+ /*! \tparam InputStream Type of input stream, implementing Stream concept
3252+ \param is Input stream to be parsed.
3253+ \return The document itself for fluent API.
3254+ */
3255+ template <typename InputStream>
3256+ GenericDocument& ParseStream(InputStream& is) {
3257+ return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
3258+ }
3259+ //!@}
3260+
3261+ //!@name Parse in-place from mutable string
3262+ //!@{
3263+
3264+ //! Parse JSON text from a mutable string (with Encoding conversion)
3265+ /*! \tparam parseFlags Combination of \ref ParseFlag.
3266+ \tparam SourceEncoding Transcoding from input Encoding
3267+ \param str Mutable zero-terminated string to be parsed.
3268+ \return The document itself for fluent API.
3269+ */
3270+ template <unsigned parseFlags, typename SourceEncoding>
3271+ GenericDocument& ParseInsitu(Ch* str) {
3272+ GenericInsituStringStream<Encoding> s(str);
3273+ return ParseStream<parseFlags | kParseInsituFlag, SourceEncoding>(s);
3274+ }
3275+
3276+ //! Parse JSON text from a mutable string
3277+ /*! \tparam parseFlags Combination of \ref ParseFlag.
3278+ \param str Mutable zero-terminated string to be parsed.
3279+ \return The document itself for fluent API.
3280+ */
3281+ template <unsigned parseFlags>
3282+ GenericDocument& ParseInsitu(Ch* str) {
3283+ return ParseInsitu<parseFlags, Encoding>(str);
3284+ }
3285+
3286+ //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
3287+ /*! \param str Mutable zero-terminated string to be parsed.
3288+ \return The document itself for fluent API.
3289+ */
3290+ GenericDocument& ParseInsitu(Ch* str) {
3291+ return ParseInsitu<kParseDefaultFlags, Encoding>(str);
3292+ }
3293+ //!@}
3294+
3295+ //!@name Parse from read-only string
3296+ //!@{
3297+
3298+ //! Parse JSON text from a read-only string (with Encoding conversion)
3299+ /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
3300+ \tparam SourceEncoding Transcoding from input Encoding
3301+ \param str Read-only zero-terminated string to be parsed.
3302+ */
3303+ template <unsigned parseFlags, typename SourceEncoding>
3304+ GenericDocument& Parse(const Ch* str) {
3305+ RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
3306+ GenericStringStream<SourceEncoding> s(str);
3307+ return ParseStream<parseFlags, SourceEncoding>(s);
3308+ }
3309+
3310+ //! Parse JSON text from a read-only string
3311+ /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
3312+ \param str Read-only zero-terminated string to be parsed.
3313+ */
3314+ template <unsigned parseFlags>
3315+ GenericDocument& Parse(const Ch* str) {
3316+ return Parse<parseFlags, Encoding>(str);
3317+ }
3318+
3319+ //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
3320+ /*! \param str Read-only zero-terminated string to be parsed.
3321+ */
3322+ GenericDocument& Parse(const Ch* str) {
3323+ return Parse<kParseDefaultFlags>(str);
3324+ }
3325+ //!@}
3326+
3327+ //!@name Handling parse errors
3328+ //!@{
3329+
3330+ //! Whether a parse error has occured in the last parsing.
3331+ bool HasParseError() const { return parseResult_.IsError(); }
3332+
3333+ //! Get the \ref ParseErrorCode of last parsing.
3334+ ParseErrorCode GetParseError() const { return parseResult_.Code(); }
3335+
3336+ //! Get the position of last parsing error in input, 0 otherwise.
3337+ size_t GetErrorOffset() const { return parseResult_.Offset(); }
3338+
3339+ //!@}
3340+
3341+ //! Get the allocator of this document.
3342+ Allocator& GetAllocator() { return *allocator_; }
3343+
3344+ //! Get the capacity of stack in bytes.
3345+ size_t GetStackCapacity() const { return stack_.GetCapacity(); }
3346+
3347+private:
3348+ // clear stack on any exit from ParseStream, e.g. due to exception
3349+ struct ClearStackOnExit {
3350+ explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
3351+ ~ClearStackOnExit() { d_.ClearStack(); }
3352+ private:
3353+ ClearStackOnExit(const ClearStackOnExit&);
3354+ ClearStackOnExit& operator=(const ClearStackOnExit&);
3355+ GenericDocument& d_;
3356+ };
3357+
3358+ // callers of the following private Handler functions
3359+ template <typename,typename,typename> friend class GenericReader; // for parsing
3360+ template <typename, typename> friend class GenericValue; // for deep copying
3361+
3362+ // Implementation of Handler
3363+ bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
3364+ bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
3365+ bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
3366+ bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
3367+ bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
3368+ bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
3369+ bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
3370+
3371+ bool String(const Ch* str, SizeType length, bool copy) {
3372+ if (copy)
3373+ new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
3374+ else
3375+ new (stack_.template Push<ValueType>()) ValueType(str, length);
3376+ return true;
3377+ }
3378+
3379+ bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
3380+
3381+ bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
3382+
3383+ bool EndObject(SizeType memberCount) {
3384+ typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
3385+ stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
3386+ return true;
3387+ }
3388+
3389+ bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
3390+
3391+ bool EndArray(SizeType elementCount) {
3392+ ValueType* elements = stack_.template Pop<ValueType>(elementCount);
3393+ stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
3394+ return true;
3395+ }
3396+
3397+private:
3398+ //! Prohibit copying
3399+ GenericDocument(const GenericDocument&);
3400+ //! Prohibit assignment
3401+ GenericDocument& operator=(const GenericDocument&);
3402+
3403+ void ClearStack() {
3404+ if (Allocator::kNeedFree)
3405+ while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
3406+ (stack_.template Pop<ValueType>(1))->~ValueType();
3407+ else
3408+ stack_.Clear();
3409+ stack_.ShrinkToFit();
3410+ }
3411+
3412+ void Destroy() {
3413+ RAPIDJSON_DELETE(ownAllocator_);
3414+ }
3415+
3416+ static const size_t kDefaultStackCapacity = 1024;
3417+ Allocator* allocator_;
3418+ Allocator* ownAllocator_;
3419+ internal::Stack<StackAllocator> stack_;
3420+ ParseResult parseResult_;
3421+};
3422+
3423+//! GenericDocument with UTF8 encoding
3424+typedef GenericDocument<UTF8<> > Document;
3425+
3426+// defined here due to the dependency on GenericDocument
3427+template <typename Encoding, typename Allocator>
3428+template <typename SourceAllocator>
3429+inline
3430+GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
3431+{
3432+ switch (rhs.GetType()) {
3433+ case kObjectType:
3434+ case kArrayType: { // perform deep copy via SAX Handler
3435+ GenericDocument<Encoding,Allocator> d(&allocator);
3436+ rhs.Accept(d);
3437+ RawAssign(*d.stack_.template Pop<GenericValue>(1));
3438+ }
3439+ break;
3440+ case kStringType:
3441+ if (rhs.flags_ == kConstStringFlag) {
3442+ flags_ = rhs.flags_;
3443+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
3444+ } else {
3445+ SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
3446+ }
3447+ break;
3448+ default: // kNumberType, kTrueType, kFalseType, kNullType
3449+ flags_ = rhs.flags_;
3450+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
3451+ }
3452+}
3453+
3454+RAPIDJSON_NAMESPACE_END
3455+
3456+#if defined(_MSC_VER) || defined(__GNUC__)
3457+RAPIDJSON_DIAG_POP
3458+#endif
3459+
3460+#endif // RAPIDJSON_DOCUMENT_H_
3461
3462=== added file 'shorts/xml2json/rapidjson/encodedstream.h'
3463--- shorts/xml2json/rapidjson/encodedstream.h 1970-01-01 00:00:00 +0000
3464+++ shorts/xml2json/rapidjson/encodedstream.h 2015-12-15 16:05:21 +0000
3465@@ -0,0 +1,290 @@
3466+// Copyright (C) 2011 Milo Yip
3467+//
3468+// Permission is hereby granted, free of charge, to any person obtaining a copy
3469+// of this software and associated documentation files (the "Software"), to deal
3470+// in the Software without restriction, including without limitation the rights
3471+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3472+// copies of the Software, and to permit persons to whom the Software is
3473+// furnished to do so, subject to the following conditions:
3474+//
3475+// The above copyright notice and this permission notice shall be included in
3476+// all copies or substantial portions of the Software.
3477+//
3478+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3479+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3480+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3481+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3482+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3483+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
3484+// THE SOFTWARE.
3485+
3486+#ifndef RAPIDJSON_ENCODEDSTREAM_H_
3487+#define RAPIDJSON_ENCODEDSTREAM_H_
3488+
3489+#include "rapidjson.h"
3490+
3491+#ifdef __GNUC__
3492+RAPIDJSON_DIAG_PUSH
3493+RAPIDJSON_DIAG_OFF(effc++)
3494+#endif
3495+
3496+RAPIDJSON_NAMESPACE_BEGIN
3497+
3498+//! Input byte stream wrapper with a statically bound encoding.
3499+/*!
3500+ \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
3501+ \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
3502+*/
3503+template <typename Encoding, typename InputByteStream>
3504+class EncodedInputStream {
3505+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
3506+public:
3507+ typedef typename Encoding::Ch Ch;
3508+
3509+ EncodedInputStream(InputByteStream& is) : is_(is) {
3510+ current_ = Encoding::TakeBOM(is_);
3511+ }
3512+
3513+ Ch Peek() const { return current_; }
3514+ Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
3515+ size_t Tell() const { return is_.Tell(); }
3516+
3517+ // Not implemented
3518+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
3519+ void Flush() { RAPIDJSON_ASSERT(false); }
3520+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
3521+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
3522+
3523+private:
3524+ EncodedInputStream(const EncodedInputStream&);
3525+ EncodedInputStream& operator=(const EncodedInputStream&);
3526+
3527+ InputByteStream& is_;
3528+ Ch current_;
3529+};
3530+
3531+//! Output byte stream wrapper with statically bound encoding.
3532+/*!
3533+ \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
3534+ \tparam InputByteStream Type of input byte stream. For example, FileWriteStream.
3535+*/
3536+template <typename Encoding, typename OutputByteStream>
3537+class EncodedOutputStream {
3538+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
3539+public:
3540+ typedef typename Encoding::Ch Ch;
3541+
3542+ EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
3543+ if (putBOM)
3544+ Encoding::PutBOM(os_);
3545+ }
3546+
3547+ void Put(Ch c) { Encoding::Put(os_, c); }
3548+ void Flush() { os_.Flush(); }
3549+
3550+ // Not implemented
3551+ Ch Peek() const { RAPIDJSON_ASSERT(false); }
3552+ Ch Take() { RAPIDJSON_ASSERT(false); }
3553+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
3554+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
3555+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
3556+
3557+private:
3558+ EncodedOutputStream(const EncodedOutputStream&);
3559+ EncodedOutputStream& operator=(const EncodedOutputStream&);
3560+
3561+ OutputByteStream& os_;
3562+};
3563+
3564+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
3565+
3566+//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
3567+/*!
3568+ \tparam CharType Type of character for reading.
3569+ \tparam InputByteStream type of input byte stream to be wrapped.
3570+*/
3571+template <typename CharType, typename InputByteStream>
3572+class AutoUTFInputStream {
3573+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
3574+public:
3575+ typedef CharType Ch;
3576+
3577+ //! Constructor.
3578+ /*!
3579+ \param is input stream to be wrapped.
3580+ \param type UTF encoding type if it is not detected from the stream.
3581+ */
3582+ AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
3583+ DetectType();
3584+ static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
3585+ takeFunc_ = f[type_];
3586+ current_ = takeFunc_(*is_);
3587+ }
3588+
3589+ UTFType GetType() const { return type_; }
3590+ bool HasBOM() const { return hasBOM_; }
3591+
3592+ Ch Peek() const { return current_; }
3593+ Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
3594+ size_t Tell() const { return is_->Tell(); }
3595+
3596+ // Not implemented
3597+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
3598+ void Flush() { RAPIDJSON_ASSERT(false); }
3599+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
3600+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
3601+
3602+private:
3603+ AutoUTFInputStream(const AutoUTFInputStream&);
3604+ AutoUTFInputStream& operator=(const AutoUTFInputStream&);
3605+
3606+ // Detect encoding type with BOM or RFC 4627
3607+ void DetectType() {
3608+ // BOM (Byte Order Mark):
3609+ // 00 00 FE FF UTF-32BE
3610+ // FF FE 00 00 UTF-32LE
3611+ // FE FF UTF-16BE
3612+ // FF FE UTF-16LE
3613+ // EF BB BF UTF-8
3614+
3615+ const unsigned char* c = (const unsigned char *)is_->Peek4();
3616+ if (!c)
3617+ return;
3618+
3619+ unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
3620+ hasBOM_ = false;
3621+ if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
3622+ else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
3623+ else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
3624+ else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
3625+ else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
3626+
3627+ // RFC 4627: Section 3
3628+ // "Since the first two characters of a JSON text will always be ASCII
3629+ // characters [RFC0020], it is possible to determine whether an octet
3630+ // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
3631+ // at the pattern of nulls in the first four octets."
3632+ // 00 00 00 xx UTF-32BE
3633+ // 00 xx 00 xx UTF-16BE
3634+ // xx 00 00 00 UTF-32LE
3635+ // xx 00 xx 00 UTF-16LE
3636+ // xx xx xx xx UTF-8
3637+
3638+ if (!hasBOM_) {
3639+ unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
3640+ switch (pattern) {
3641+ case 0x08: type_ = kUTF32BE; break;
3642+ case 0x0A: type_ = kUTF16BE; break;
3643+ case 0x01: type_ = kUTF32LE; break;
3644+ case 0x05: type_ = kUTF16LE; break;
3645+ case 0x0F: type_ = kUTF8; break;
3646+ default: break; // Use type defined by user.
3647+ }
3648+ }
3649+
3650+ // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
3651+ switch (type_) {
3652+ case kUTF8:
3653+ // Do nothing
3654+ break;
3655+ case kUTF16LE:
3656+ case kUTF16BE:
3657+ RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
3658+ break;
3659+ case kUTF32LE:
3660+ case kUTF32BE:
3661+ RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
3662+ break;
3663+ default:
3664+ RAPIDJSON_ASSERT(false); // Invalid type
3665+ }
3666+ }
3667+
3668+ typedef Ch (*TakeFunc)(InputByteStream& is);
3669+ InputByteStream* is_;
3670+ UTFType type_;
3671+ Ch current_;
3672+ TakeFunc takeFunc_;
3673+ bool hasBOM_;
3674+};
3675+
3676+//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
3677+/*!
3678+ \tparam CharType Type of character for writing.
3679+ \tparam InputByteStream type of output byte stream to be wrapped.
3680+*/
3681+template <typename CharType, typename OutputByteStream>
3682+class AutoUTFOutputStream {
3683+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
3684+public:
3685+ typedef CharType Ch;
3686+
3687+ //! Constructor.
3688+ /*!
3689+ \param os output stream to be wrapped.
3690+ \param type UTF encoding type.
3691+ \param putBOM Whether to write BOM at the beginning of the stream.
3692+ */
3693+ AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
3694+ // RUntime check whether the size of character type is sufficient. It only perform checks with assertion.
3695+ switch (type_) {
3696+ case kUTF16LE:
3697+ case kUTF16BE:
3698+ RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
3699+ break;
3700+ case kUTF32LE:
3701+ case kUTF32BE:
3702+ RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
3703+ break;
3704+ case kUTF8:
3705+ // Do nothing
3706+ break;
3707+ default:
3708+ RAPIDJSON_ASSERT(false); // Invalid UTFType
3709+ }
3710+
3711+ static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
3712+ putFunc_ = f[type_];
3713+
3714+ if (putBOM)
3715+ PutBOM();
3716+ }
3717+
3718+ UTFType GetType() const { return type_; }
3719+
3720+ void Put(Ch c) { putFunc_(*os_, c); }
3721+ void Flush() { os_->Flush(); }
3722+
3723+ // Not implemented
3724+ Ch Peek() const { RAPIDJSON_ASSERT(false); }
3725+ Ch Take() { RAPIDJSON_ASSERT(false); }
3726+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
3727+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
3728+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
3729+
3730+private:
3731+ AutoUTFOutputStream(const AutoUTFOutputStream&);
3732+ AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
3733+
3734+ void PutBOM() {
3735+ typedef void (*PutBOMFunc)(OutputByteStream&);
3736+ static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
3737+ f[type_](*os_);
3738+ }
3739+
3740+ typedef void (*PutFunc)(OutputByteStream&, Ch);
3741+
3742+ OutputByteStream* os_;
3743+ UTFType type_;
3744+ PutFunc putFunc_;
3745+};
3746+
3747+#undef RAPIDJSON_ENCODINGS_FUNC
3748+
3749+RAPIDJSON_NAMESPACE_END
3750+
3751+#ifdef __GNUC__
3752+RAPIDJSON_DIAG_POP
3753+#endif
3754+
3755+#endif // RAPIDJSON_FILESTREAM_H_
3756
3757=== added file 'shorts/xml2json/rapidjson/encodings.h'
3758--- shorts/xml2json/rapidjson/encodings.h 1970-01-01 00:00:00 +0000
3759+++ shorts/xml2json/rapidjson/encodings.h 2015-12-15 16:05:21 +0000
3760@@ -0,0 +1,630 @@
3761+// Copyright (C) 2011 Milo Yip
3762+//
3763+// Permission is hereby granted, free of charge, to any person obtaining a copy
3764+// of this software and associated documentation files (the "Software"), to deal
3765+// in the Software without restriction, including without limitation the rights
3766+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3767+// copies of the Software, and to permit persons to whom the Software is
3768+// furnished to do so, subject to the following conditions:
3769+//
3770+// The above copyright notice and this permission notice shall be included in
3771+// all copies or substantial portions of the Software.
3772+//
3773+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3774+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3775+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3776+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3777+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3778+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
3779+// THE SOFTWARE.
3780+
3781+#ifndef RAPIDJSON_ENCODINGS_H_
3782+#define RAPIDJSON_ENCODINGS_H_
3783+
3784+#include "rapidjson.h"
3785+
3786+#ifdef _MSC_VER
3787+RAPIDJSON_DIAG_PUSH
3788+RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
3789+RAPIDJSON_DIAG_OFF(4702) // unreachable code
3790+#elif defined(__GNUC__)
3791+RAPIDJSON_DIAG_PUSH
3792+RAPIDJSON_DIAG_OFF(effc++)
3793+#endif
3794+
3795+RAPIDJSON_NAMESPACE_BEGIN
3796+
3797+///////////////////////////////////////////////////////////////////////////////
3798+// Encoding
3799+
3800+/*! \class rapidjson::Encoding
3801+ \brief Concept for encoding of Unicode characters.
3802+
3803+\code
3804+concept Encoding {
3805+ typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
3806+
3807+ enum { supportUnicode = 1 }; // or 0 if not supporting unicode
3808+
3809+ //! \brief Encode a Unicode codepoint to an output stream.
3810+ //! \param os Output stream.
3811+ //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
3812+ template<typename OutputStream>
3813+ static void Encode(OutputStream& os, unsigned codepoint);
3814+
3815+ //! \brief Decode a Unicode codepoint from an input stream.
3816+ //! \param is Input stream.
3817+ //! \param codepoint Output of the unicode codepoint.
3818+ //! \return true if a valid codepoint can be decoded from the stream.
3819+ template <typename InputStream>
3820+ static bool Decode(InputStream& is, unsigned* codepoint);
3821+
3822+ //! \brief Validate one Unicode codepoint from an encoded stream.
3823+ //! \param is Input stream to obtain codepoint.
3824+ //! \param os Output for copying one codepoint.
3825+ //! \return true if it is valid.
3826+ //! \note This function just validating and copying the codepoint without actually decode it.
3827+ template <typename InputStream, typename OutputStream>
3828+ static bool Validate(InputStream& is, OutputStream& os);
3829+
3830+ // The following functions are deal with byte streams.
3831+
3832+ //! Take a character from input byte stream, skip BOM if exist.
3833+ template <typename InputByteStream>
3834+ static CharType TakeBOM(InputByteStream& is);
3835+
3836+ //! Take a character from input byte stream.
3837+ template <typename InputByteStream>
3838+ static Ch Take(InputByteStream& is);
3839+
3840+ //! Put BOM to output byte stream.
3841+ template <typename OutputByteStream>
3842+ static void PutBOM(OutputByteStream& os);
3843+
3844+ //! Put a character to output byte stream.
3845+ template <typename OutputByteStream>
3846+ static void Put(OutputByteStream& os, Ch c);
3847+};
3848+\endcode
3849+*/
3850+
3851+///////////////////////////////////////////////////////////////////////////////
3852+// UTF8
3853+
3854+//! UTF-8 encoding.
3855+/*! http://en.wikipedia.org/wiki/UTF-8
3856+ http://tools.ietf.org/html/rfc3629
3857+ \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
3858+ \note implements Encoding concept
3859+*/
3860+template<typename CharType = char>
3861+struct UTF8 {
3862+ typedef CharType Ch;
3863+
3864+ enum { supportUnicode = 1 };
3865+
3866+ template<typename OutputStream>
3867+ static void Encode(OutputStream& os, unsigned codepoint) {
3868+ if (codepoint <= 0x7F)
3869+ os.Put(static_cast<Ch>(codepoint & 0xFF));
3870+ else if (codepoint <= 0x7FF) {
3871+ os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
3872+ os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
3873+ }
3874+ else if (codepoint <= 0xFFFF) {
3875+ os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
3876+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
3877+ os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
3878+ }
3879+ else {
3880+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
3881+ os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
3882+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
3883+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
3884+ os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
3885+ }
3886+ }
3887+
3888+ template <typename InputStream>
3889+ static bool Decode(InputStream& is, unsigned* codepoint) {
3890+#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu)
3891+#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
3892+#define TAIL() COPY(); TRANS(0x70)
3893+ Ch c = is.Take();
3894+ if (!(c & 0x80)) {
3895+ *codepoint = (unsigned char)c;
3896+ return true;
3897+ }
3898+
3899+ unsigned char type = GetRange((unsigned char)c);
3900+ *codepoint = (0xFF >> type) & (unsigned char)c;
3901+ bool result = true;
3902+ switch (type) {
3903+ case 2: TAIL(); return result;
3904+ case 3: TAIL(); TAIL(); return result;
3905+ case 4: COPY(); TRANS(0x50); TAIL(); return result;
3906+ case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
3907+ case 6: TAIL(); TAIL(); TAIL(); return result;
3908+ case 10: COPY(); TRANS(0x20); TAIL(); return result;
3909+ case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
3910+ default: return false;
3911+ }
3912+#undef COPY
3913+#undef TRANS
3914+#undef TAIL
3915+ }
3916+
3917+ template <typename InputStream, typename OutputStream>
3918+ static bool Validate(InputStream& is, OutputStream& os) {
3919+#define COPY() os.Put(c = is.Take())
3920+#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
3921+#define TAIL() COPY(); TRANS(0x70)
3922+ Ch c;
3923+ COPY();
3924+ if (!(c & 0x80))
3925+ return true;
3926+
3927+ bool result = true;
3928+ switch (GetRange((unsigned char)c)) {
3929+ case 2: TAIL(); return result;
3930+ case 3: TAIL(); TAIL(); return result;
3931+ case 4: COPY(); TRANS(0x50); TAIL(); return result;
3932+ case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
3933+ case 6: TAIL(); TAIL(); TAIL(); return result;
3934+ case 10: COPY(); TRANS(0x20); TAIL(); return result;
3935+ case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
3936+ default: return false;
3937+ }
3938+#undef COPY
3939+#undef TRANS
3940+#undef TAIL
3941+ }
3942+
3943+ static unsigned char GetRange(unsigned char c) {
3944+ // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
3945+ // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
3946+ static const unsigned char type[] = {
3947+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3948+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3949+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3950+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3951+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
3952+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
3953+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
3954+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
3955+ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3956+ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
3957+ };
3958+ return type[c];
3959+ }
3960+
3961+ template <typename InputByteStream>
3962+ static CharType TakeBOM(InputByteStream& is) {
3963+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
3964+ Ch c = Take(is);
3965+ if ((unsigned char)c != 0xEFu) return c;
3966+ c = is.Take();
3967+ if ((unsigned char)c != 0xBBu) return c;
3968+ c = is.Take();
3969+ if ((unsigned char)c != 0xBFu) return c;
3970+ c = is.Take();
3971+ return c;
3972+ }
3973+
3974+ template <typename InputByteStream>
3975+ static Ch Take(InputByteStream& is) {
3976+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
3977+ return is.Take();
3978+ }
3979+
3980+ template <typename OutputByteStream>
3981+ static void PutBOM(OutputByteStream& os) {
3982+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
3983+ os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu);
3984+ }
3985+
3986+ template <typename OutputByteStream>
3987+ static void Put(OutputByteStream& os, Ch c) {
3988+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
3989+ os.Put(static_cast<typename OutputByteStream::Ch>(c));
3990+ }
3991+};
3992+
3993+///////////////////////////////////////////////////////////////////////////////
3994+// UTF16
3995+
3996+//! UTF-16 encoding.
3997+/*! http://en.wikipedia.org/wiki/UTF-16
3998+ http://tools.ietf.org/html/rfc2781
3999+ \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
4000+ \note implements Encoding concept
4001+
4002+ \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
4003+ For streaming, use UTF16LE and UTF16BE, which handle endianness.
4004+*/
4005+template<typename CharType = wchar_t>
4006+struct UTF16 {
4007+ typedef CharType Ch;
4008+ RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
4009+
4010+ enum { supportUnicode = 1 };
4011+
4012+ template<typename OutputStream>
4013+ static void Encode(OutputStream& os, unsigned codepoint) {
4014+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
4015+ if (codepoint <= 0xFFFF) {
4016+ RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
4017+ os.Put(static_cast<typename OutputStream::Ch>(codepoint));
4018+ }
4019+ else {
4020+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
4021+ unsigned v = codepoint - 0x10000;
4022+ os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
4023+ os.Put((v & 0x3FF) | 0xDC00);
4024+ }
4025+ }
4026+
4027+ template <typename InputStream>
4028+ static bool Decode(InputStream& is, unsigned* codepoint) {
4029+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
4030+ Ch c = is.Take();
4031+ if (c < 0xD800 || c > 0xDFFF) {
4032+ *codepoint = c;
4033+ return true;
4034+ }
4035+ else if (c <= 0xDBFF) {
4036+ *codepoint = (c & 0x3FF) << 10;
4037+ c = is.Take();
4038+ *codepoint |= (c & 0x3FF);
4039+ *codepoint += 0x10000;
4040+ return c >= 0xDC00 && c <= 0xDFFF;
4041+ }
4042+ return false;
4043+ }
4044+
4045+ template <typename InputStream, typename OutputStream>
4046+ static bool Validate(InputStream& is, OutputStream& os) {
4047+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
4048+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
4049+ Ch c;
4050+ os.Put(c = is.Take());
4051+ if (c < 0xD800 || c > 0xDFFF)
4052+ return true;
4053+ else if (c <= 0xDBFF) {
4054+ os.Put(c = is.Take());
4055+ return c >= 0xDC00 && c <= 0xDFFF;
4056+ }
4057+ return false;
4058+ }
4059+};
4060+
4061+//! UTF-16 little endian encoding.
4062+template<typename CharType = wchar_t>
4063+struct UTF16LE : UTF16<CharType> {
4064+ template <typename InputByteStream>
4065+ static CharType TakeBOM(InputByteStream& is) {
4066+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
4067+ CharType c = Take(is);
4068+ return (unsigned short)c == 0xFEFFu ? Take(is) : c;
4069+ }
4070+
4071+ template <typename InputByteStream>
4072+ static CharType Take(InputByteStream& is) {
4073+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
4074+ CharType c = (unsigned char)is.Take();
4075+ c |= (unsigned char)is.Take() << 8;
4076+ return c;
4077+ }
4078+
4079+ template <typename OutputByteStream>
4080+ static void PutBOM(OutputByteStream& os) {
4081+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
4082+ os.Put(0xFFu); os.Put(0xFEu);
4083+ }
4084+
4085+ template <typename OutputByteStream>
4086+ static void Put(OutputByteStream& os, CharType c) {
4087+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
4088+ os.Put(c & 0xFFu);
4089+ os.Put((c >> 8) & 0xFFu);
4090+ }
4091+};
4092+
4093+//! UTF-16 big endian encoding.
4094+template<typename CharType = wchar_t>
4095+struct UTF16BE : UTF16<CharType> {
4096+ template <typename InputByteStream>
4097+ static CharType TakeBOM(InputByteStream& is) {
4098+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
4099+ CharType c = Take(is);
4100+ return (unsigned short)c == 0xFEFFu ? Take(is) : c;
4101+ }
4102+
4103+ template <typename InputByteStream>
4104+ static CharType Take(InputByteStream& is) {
4105+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
4106+ CharType c = (unsigned char)is.Take() << 8;
4107+ c |= (unsigned char)is.Take();
4108+ return c;
4109+ }
4110+
4111+ template <typename OutputByteStream>
4112+ static void PutBOM(OutputByteStream& os) {
4113+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
4114+ os.Put(0xFEu); os.Put(0xFFu);
4115+ }
4116+
4117+ template <typename OutputByteStream>
4118+ static void Put(OutputByteStream& os, CharType c) {
4119+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
4120+ os.Put((c >> 8) & 0xFFu);
4121+ os.Put(c & 0xFFu);
4122+ }
4123+};
4124+
4125+///////////////////////////////////////////////////////////////////////////////
4126+// UTF32
4127+
4128+//! UTF-32 encoding.
4129+/*! http://en.wikipedia.org/wiki/UTF-32
4130+ \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
4131+ \note implements Encoding concept
4132+
4133+ \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
4134+ For streaming, use UTF32LE and UTF32BE, which handle endianness.
4135+*/
4136+template<typename CharType = unsigned>
4137+struct UTF32 {
4138+ typedef CharType Ch;
4139+ RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
4140+
4141+ enum { supportUnicode = 1 };
4142+
4143+ template<typename OutputStream>
4144+ static void Encode(OutputStream& os, unsigned codepoint) {
4145+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
4146+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
4147+ os.Put(codepoint);
4148+ }
4149+
4150+ template <typename InputStream>
4151+ static bool Decode(InputStream& is, unsigned* codepoint) {
4152+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
4153+ Ch c = is.Take();
4154+ *codepoint = c;
4155+ return c <= 0x10FFFF;
4156+ }
4157+
4158+ template <typename InputStream, typename OutputStream>
4159+ static bool Validate(InputStream& is, OutputStream& os) {
4160+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
4161+ Ch c;
4162+ os.Put(c = is.Take());
4163+ return c <= 0x10FFFF;
4164+ }
4165+};
4166+
4167+//! UTF-32 little endian enocoding.
4168+template<typename CharType = unsigned>
4169+struct UTF32LE : UTF32<CharType> {
4170+ template <typename InputByteStream>
4171+ static CharType TakeBOM(InputByteStream& is) {
4172+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
4173+ CharType c = Take(is);
4174+ return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
4175+ }
4176+
4177+ template <typename InputByteStream>
4178+ static CharType Take(InputByteStream& is) {
4179+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
4180+ CharType c = (unsigned char)is.Take();
4181+ c |= (unsigned char)is.Take() << 8;
4182+ c |= (unsigned char)is.Take() << 16;
4183+ c |= (unsigned char)is.Take() << 24;
4184+ return c;
4185+ }
4186+
4187+ template <typename OutputByteStream>
4188+ static void PutBOM(OutputByteStream& os) {
4189+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
4190+ os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u);
4191+ }
4192+
4193+ template <typename OutputByteStream>
4194+ static void Put(OutputByteStream& os, CharType c) {
4195+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
4196+ os.Put(c & 0xFFu);
4197+ os.Put((c >> 8) & 0xFFu);
4198+ os.Put((c >> 16) & 0xFFu);
4199+ os.Put((c >> 24) & 0xFFu);
4200+ }
4201+};
4202+
4203+//! UTF-32 big endian encoding.
4204+template<typename CharType = unsigned>
4205+struct UTF32BE : UTF32<CharType> {
4206+ template <typename InputByteStream>
4207+ static CharType TakeBOM(InputByteStream& is) {
4208+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
4209+ CharType c = Take(is);
4210+ return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
4211+ }
4212+
4213+ template <typename InputByteStream>
4214+ static CharType Take(InputByteStream& is) {
4215+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
4216+ CharType c = (unsigned char)is.Take() << 24;
4217+ c |= (unsigned char)is.Take() << 16;
4218+ c |= (unsigned char)is.Take() << 8;
4219+ c |= (unsigned char)is.Take();
4220+ return c;
4221+ }
4222+
4223+ template <typename OutputByteStream>
4224+ static void PutBOM(OutputByteStream& os) {
4225+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
4226+ os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu);
4227+ }
4228+
4229+ template <typename OutputByteStream>
4230+ static void Put(OutputByteStream& os, CharType c) {
4231+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
4232+ os.Put((c >> 24) & 0xFFu);
4233+ os.Put((c >> 16) & 0xFFu);
4234+ os.Put((c >> 8) & 0xFFu);
4235+ os.Put(c & 0xFFu);
4236+ }
4237+};
4238+
4239+///////////////////////////////////////////////////////////////////////////////
4240+// ASCII
4241+
4242+//! ASCII encoding.
4243+/*! http://en.wikipedia.org/wiki/ASCII
4244+ \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
4245+ \note implements Encoding concept
4246+*/
4247+template<typename CharType = char>
4248+struct ASCII {
4249+ typedef CharType Ch;
4250+
4251+ enum { supportUnicode = 0 };
4252+
4253+ template<typename OutputStream>
4254+ static void Encode(OutputStream& os, unsigned codepoint) {
4255+ RAPIDJSON_ASSERT(codepoint <= 0x7F);
4256+ os.Put(static_cast<Ch>(codepoint & 0xFF));
4257+ }
4258+
4259+ template <typename InputStream>
4260+ static bool Decode(InputStream& is, unsigned* codepoint) {
4261+ unsigned char c = static_cast<unsigned char>(is.Take());
4262+ *codepoint = c;
4263+ return c <= 0X7F;
4264+ }
4265+
4266+ template <typename InputStream, typename OutputStream>
4267+ static bool Validate(InputStream& is, OutputStream& os) {
4268+ unsigned char c = is.Take();
4269+ os.Put(c);
4270+ return c <= 0x7F;
4271+ }
4272+
4273+ template <typename InputByteStream>
4274+ static CharType TakeBOM(InputByteStream& is) {
4275+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
4276+ Ch c = Take(is);
4277+ return c;
4278+ }
4279+
4280+ template <typename InputByteStream>
4281+ static Ch Take(InputByteStream& is) {
4282+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
4283+ return is.Take();
4284+ }
4285+
4286+ template <typename OutputByteStream>
4287+ static void PutBOM(OutputByteStream& os) {
4288+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
4289+ (void)os;
4290+ }
4291+
4292+ template <typename OutputByteStream>
4293+ static void Put(OutputByteStream& os, Ch c) {
4294+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
4295+ os.Put(static_cast<typename OutputByteStream::Ch>(c));
4296+ }
4297+};
4298+
4299+///////////////////////////////////////////////////////////////////////////////
4300+// AutoUTF
4301+
4302+//! Runtime-specified UTF encoding type of a stream.
4303+enum UTFType {
4304+ kUTF8 = 0, //!< UTF-8.
4305+ kUTF16LE = 1, //!< UTF-16 little endian.
4306+ kUTF16BE = 2, //!< UTF-16 big endian.
4307+ kUTF32LE = 3, //!< UTF-32 little endian.
4308+ kUTF32BE = 4 //!< UTF-32 big endian.
4309+};
4310+
4311+//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
4312+/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
4313+*/
4314+template<typename CharType>
4315+struct AutoUTF {
4316+ typedef CharType Ch;
4317+
4318+ enum { supportUnicode = 1 };
4319+
4320+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
4321+
4322+ template<typename OutputStream>
4323+ RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
4324+ typedef void (*EncodeFunc)(OutputStream&, unsigned);
4325+ static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
4326+ (*f[os.GetType()])(os, codepoint);
4327+ }
4328+
4329+ template <typename InputStream>
4330+ RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
4331+ typedef bool (*DecodeFunc)(InputStream&, unsigned*);
4332+ static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
4333+ return (*f[is.GetType()])(is, codepoint);
4334+ }
4335+
4336+ template <typename InputStream, typename OutputStream>
4337+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
4338+ typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
4339+ static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
4340+ return (*f[is.GetType()])(is, os);
4341+ }
4342+
4343+#undef RAPIDJSON_ENCODINGS_FUNC
4344+};
4345+
4346+///////////////////////////////////////////////////////////////////////////////
4347+// Transcoder
4348+
4349+//! Encoding conversion.
4350+template<typename SourceEncoding, typename TargetEncoding>
4351+struct Transcoder {
4352+ //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
4353+ template<typename InputStream, typename OutputStream>
4354+ RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
4355+ unsigned codepoint;
4356+ if (!SourceEncoding::Decode(is, &codepoint))
4357+ return false;
4358+ TargetEncoding::Encode(os, codepoint);
4359+ return true;
4360+ }
4361+
4362+ //! Validate one Unicode codepoint from an encoded stream.
4363+ template<typename InputStream, typename OutputStream>
4364+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
4365+ return Transcode(is, os); // Since source/target encoding is different, must transcode.
4366+ }
4367+};
4368+
4369+//! Specialization of Transcoder with same source and target encoding.
4370+template<typename Encoding>
4371+struct Transcoder<Encoding, Encoding> {
4372+ template<typename InputStream, typename OutputStream>
4373+ RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
4374+ os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
4375+ return true;
4376+ }
4377+
4378+ template<typename InputStream, typename OutputStream>
4379+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
4380+ return Encoding::Validate(is, os); // source/target encoding are the same
4381+ }
4382+};
4383+
4384+RAPIDJSON_NAMESPACE_END
4385+
4386+#if defined(__GNUC__) || defined(_MSV_VER)
4387+RAPIDJSON_DIAG_POP
4388+#endif
4389+
4390+#endif // RAPIDJSON_ENCODINGS_H_
4391
4392=== added directory 'shorts/xml2json/rapidjson/error'
4393=== added file 'shorts/xml2json/rapidjson/error/en.h'
4394--- shorts/xml2json/rapidjson/error/en.h 1970-01-01 00:00:00 +0000
4395+++ shorts/xml2json/rapidjson/error/en.h 2015-12-15 16:05:21 +0000
4396@@ -0,0 +1,71 @@
4397+// Copyright (C) 2011 Milo Yip
4398+//
4399+// Permission is hereby granted, free of charge, to any person obtaining a copy
4400+// of this software and associated documentation files (the "Software"), to deal
4401+// in the Software without restriction, including without limitation the rights
4402+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4403+// copies of the Software, and to permit persons to whom the Software is
4404+// furnished to do so, subject to the following conditions:
4405+//
4406+// The above copyright notice and this permission notice shall be included in
4407+// all copies or substantial portions of the Software.
4408+//
4409+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4410+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4411+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4412+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4413+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4414+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4415+// THE SOFTWARE.
4416+
4417+#ifndef RAPIDJSON_ERROR_EN_H__
4418+#define RAPIDJSON_ERROR_EN_H__
4419+
4420+#include "error.h"
4421+
4422+RAPIDJSON_NAMESPACE_BEGIN
4423+
4424+//! Maps error code of parsing into error message.
4425+/*!
4426+ \ingroup RAPIDJSON_ERRORS
4427+ \param parseErrorCode Error code obtained in parsing.
4428+ \return the error message.
4429+ \note User can make a copy of this function for localization.
4430+ Using switch-case is safer for future modification of error codes.
4431+*/
4432+inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
4433+ switch (parseErrorCode) {
4434+ case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
4435+
4436+ case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
4437+ case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values.");
4438+
4439+ case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
4440+
4441+ case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
4442+ case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
4443+ case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
4444+
4445+ case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
4446+
4447+ case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
4448+ case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
4449+ case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
4450+ case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
4451+ case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
4452+
4453+ case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
4454+ case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
4455+ case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
4456+
4457+ case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
4458+ case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
4459+
4460+ default:
4461+ return RAPIDJSON_ERROR_STRING("Unknown error.");
4462+ }
4463+}
4464+
4465+RAPIDJSON_NAMESPACE_END
4466+
4467+#endif // RAPIDJSON_ERROR_EN_H__
4468
4469=== added file 'shorts/xml2json/rapidjson/error/error.h'
4470--- shorts/xml2json/rapidjson/error/error.h 1970-01-01 00:00:00 +0000
4471+++ shorts/xml2json/rapidjson/error/error.h 2015-12-15 16:05:21 +0000
4472@@ -0,0 +1,150 @@
4473+// Copyright (C) 2011 Milo Yip
4474+//
4475+// Permission is hereby granted, free of charge, to any person obtaining a copy
4476+// of this software and associated documentation files (the "Software"), to deal
4477+// in the Software without restriction, including without limitation the rights
4478+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4479+// copies of the Software, and to permit persons to whom the Software is
4480+// furnished to do so, subject to the following conditions:
4481+//
4482+// The above copyright notice and this permission notice shall be included in
4483+// all copies or substantial portions of the Software.
4484+//
4485+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4486+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4487+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4488+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4489+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4490+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4491+// THE SOFTWARE.
4492+
4493+#ifndef RAPIDJSON_ERROR_ERROR_H__
4494+#define RAPIDJSON_ERROR_ERROR_H__
4495+
4496+/*! \file error.h */
4497+
4498+/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
4499+
4500+///////////////////////////////////////////////////////////////////////////////
4501+// RAPIDJSON_ERROR_CHARTYPE
4502+
4503+//! Character type of error messages.
4504+/*! \ingroup RAPIDJSON_ERRORS
4505+ The default character type is \c char.
4506+ On Windows, user can define this macro as \c TCHAR for supporting both
4507+ unicode/non-unicode settings.
4508+*/
4509+#ifndef RAPIDJSON_ERROR_CHARTYPE
4510+#define RAPIDJSON_ERROR_CHARTYPE char
4511+#endif
4512+
4513+///////////////////////////////////////////////////////////////////////////////
4514+// RAPIDJSON_ERROR_STRING
4515+
4516+//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
4517+/*! \ingroup RAPIDJSON_ERRORS
4518+ By default this conversion macro does nothing.
4519+ On Windows, user can define this macro as \c _T(x) for supporting both
4520+ unicode/non-unicode settings.
4521+*/
4522+#ifndef RAPIDJSON_ERROR_STRING
4523+#define RAPIDJSON_ERROR_STRING(x) x
4524+#endif
4525+
4526+RAPIDJSON_NAMESPACE_BEGIN
4527+
4528+///////////////////////////////////////////////////////////////////////////////
4529+// ParseErrorCode
4530+
4531+//! Error code of parsing.
4532+/*! \ingroup RAPIDJSON_ERRORS
4533+ \see GenericReader::Parse, GenericReader::GetParseErrorCode
4534+*/
4535+enum ParseErrorCode {
4536+ kParseErrorNone = 0, //!< No error.
4537+
4538+ kParseErrorDocumentEmpty, //!< The document is empty.
4539+ kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values.
4540+
4541+ kParseErrorValueInvalid, //!< Invalid value.
4542+
4543+ kParseErrorObjectMissName, //!< Missing a name for object member.
4544+ kParseErrorObjectMissColon, //!< Missing a colon after a name of object member.
4545+ kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member.
4546+
4547+ kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element.
4548+
4549+ kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string.
4550+ kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid.
4551+ kParseErrorStringEscapeInvalid, //!< Invalid escape character in string.
4552+ kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string.
4553+ kParseErrorStringInvalidEncoding, //!< Invalid encoding in string.
4554+
4555+ kParseErrorNumberTooBig, //!< Number too big to be stored in double.
4556+ kParseErrorNumberMissFraction, //!< Miss fraction part in number.
4557+ kParseErrorNumberMissExponent, //!< Miss exponent in number.
4558+
4559+ kParseErrorTermination, //!< Parsing was terminated.
4560+ kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
4561+};
4562+
4563+//! Result of parsing (wraps ParseErrorCode)
4564+/*!
4565+ \ingroup RAPIDJSON_ERRORS
4566+ \code
4567+ Document doc;
4568+ ParseResult ok = doc.Parse("[42]");
4569+ if (!ok) {
4570+ fprintf(stderr, "JSON parse error: %s (%u)",
4571+ GetParseError_En(ok.Code()), ok.Offset());
4572+ exit(EXIT_FAILURE);
4573+ }
4574+ \endcode
4575+ \see GenericReader::Parse, GenericDocument::Parse
4576+*/
4577+struct ParseResult {
4578+
4579+ //! Default constructor, no error.
4580+ ParseResult() : code_(kParseErrorNone), offset_(0) {}
4581+ //! Constructor to set an error.
4582+ ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
4583+
4584+ //! Get the error code.
4585+ ParseErrorCode Code() const { return code_; }
4586+ //! Get the error offset, if \ref IsError(), 0 otherwise.
4587+ size_t Offset() const { return offset_; }
4588+
4589+ //! Conversion to \c bool, returns \c true, iff !\ref IsError().
4590+ operator bool() const { return !IsError(); }
4591+ //! Whether the result is an error.
4592+ bool IsError() const { return code_ != kParseErrorNone; }
4593+
4594+ bool operator==(const ParseResult& that) const { return code_ == that.code_; }
4595+ bool operator==(ParseErrorCode code) const { return code_ == code; }
4596+ friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
4597+
4598+ //! Reset error code.
4599+ void Clear() { Set(kParseErrorNone); }
4600+ //! Update error code and offset.
4601+ void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
4602+
4603+private:
4604+ ParseErrorCode code_;
4605+ size_t offset_;
4606+};
4607+
4608+//! Function pointer type of GetParseError().
4609+/*! \ingroup RAPIDJSON_ERRORS
4610+
4611+ This is the prototype for \c GetParseError_X(), where \c X is a locale.
4612+ User can dynamically change locale in runtime, e.g.:
4613+\code
4614+ GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
4615+ const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
4616+\endcode
4617+*/
4618+typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
4619+
4620+RAPIDJSON_NAMESPACE_END
4621+
4622+#endif // RAPIDJSON_ERROR_ERROR_H__
4623
4624=== added file 'shorts/xml2json/rapidjson/filereadstream.h'
4625--- shorts/xml2json/rapidjson/filereadstream.h 1970-01-01 00:00:00 +0000
4626+++ shorts/xml2json/rapidjson/filereadstream.h 2015-12-15 16:05:21 +0000
4627@@ -0,0 +1,94 @@
4628+// Copyright (C) 2011 Milo Yip
4629+//
4630+// Permission is hereby granted, free of charge, to any person obtaining a copy
4631+// of this software and associated documentation files (the "Software"), to deal
4632+// in the Software without restriction, including without limitation the rights
4633+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4634+// copies of the Software, and to permit persons to whom the Software is
4635+// furnished to do so, subject to the following conditions:
4636+//
4637+// The above copyright notice and this permission notice shall be included in
4638+// all copies or substantial portions of the Software.
4639+//
4640+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4641+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4642+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4643+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4644+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4645+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4646+// THE SOFTWARE.
4647+
4648+#ifndef RAPIDJSON_FILEREADSTREAM_H_
4649+#define RAPIDJSON_FILEREADSTREAM_H_
4650+
4651+#include "rapidjson.h"
4652+#include <cstdio>
4653+
4654+RAPIDJSON_NAMESPACE_BEGIN
4655+
4656+//! File byte stream for input using fread().
4657+/*!
4658+ \note implements Stream concept
4659+*/
4660+class FileReadStream {
4661+public:
4662+ typedef char Ch; //!< Character type (byte).
4663+
4664+ //! Constructor.
4665+ /*!
4666+ \param fp File pointer opened for read.
4667+ \param buffer user-supplied buffer.
4668+ \param bufferSize size of buffer in bytes. Must >=4 bytes.
4669+ */
4670+ FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
4671+ RAPIDJSON_ASSERT(fp_ != 0);
4672+ RAPIDJSON_ASSERT(bufferSize >= 4);
4673+ Read();
4674+ }
4675+
4676+ Ch Peek() const { return *current_; }
4677+ Ch Take() { Ch c = *current_; Read(); return c; }
4678+ size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
4679+
4680+ // Not implemented
4681+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
4682+ void Flush() { RAPIDJSON_ASSERT(false); }
4683+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
4684+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
4685+
4686+ // For encoding detection only.
4687+ const Ch* Peek4() const {
4688+ return (current_ + 4 <= bufferLast_) ? current_ : 0;
4689+ }
4690+
4691+private:
4692+ void Read() {
4693+ if (current_ < bufferLast_)
4694+ ++current_;
4695+ else if (!eof_) {
4696+ count_ += readCount_;
4697+ readCount_ = fread(buffer_, 1, bufferSize_, fp_);
4698+ bufferLast_ = buffer_ + readCount_ - 1;
4699+ current_ = buffer_;
4700+
4701+ if (readCount_ < bufferSize_) {
4702+ buffer_[readCount_] = '\0';
4703+ ++bufferLast_;
4704+ eof_ = true;
4705+ }
4706+ }
4707+ }
4708+
4709+ std::FILE* fp_;
4710+ Ch *buffer_;
4711+ size_t bufferSize_;
4712+ Ch *bufferLast_;
4713+ Ch *current_;
4714+ size_t readCount_;
4715+ size_t count_; //!< Number of characters read
4716+ bool eof_;
4717+};
4718+
4719+RAPIDJSON_NAMESPACE_END
4720+
4721+#endif // RAPIDJSON_FILESTREAM_H_
4722
4723=== added file 'shorts/xml2json/rapidjson/filestream.h'
4724--- shorts/xml2json/rapidjson/filestream.h 1970-01-01 00:00:00 +0000
4725+++ shorts/xml2json/rapidjson/filestream.h 2015-12-15 16:05:21 +0000
4726@@ -0,0 +1,73 @@
4727+// Copyright (C) 2011 Milo Yip
4728+//
4729+// Permission is hereby granted, free of charge, to any person obtaining a copy
4730+// of this software and associated documentation files (the "Software"), to deal
4731+// in the Software without restriction, including without limitation the rights
4732+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4733+// copies of the Software, and to permit persons to whom the Software is
4734+// furnished to do so, subject to the following conditions:
4735+//
4736+// The above copyright notice and this permission notice shall be included in
4737+// all copies or substantial portions of the Software.
4738+//
4739+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4740+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4741+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4742+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4743+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4744+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4745+// THE SOFTWARE.
4746+
4747+#ifndef RAPIDJSON_FILESTREAM_H_
4748+#define RAPIDJSON_FILESTREAM_H_
4749+
4750+#include "rapidjson.h"
4751+#include <cstdio>
4752+
4753+RAPIDJSON_NAMESPACE_BEGIN
4754+
4755+//! (Deprecated) Wrapper of C file stream for input or output.
4756+/*!
4757+ This simple wrapper does not check the validity of the stream.
4758+ \note implements Stream concept
4759+ \note deprecated: This was only for basic testing in version 0.1, it is found that the performance is very low by using fgetc(). Use FileReadStream instead.
4760+*/
4761+class FileStream {
4762+public:
4763+ typedef char Ch; //!< Character type. Only support char.
4764+
4765+ FileStream(std::FILE* fp) : fp_(fp), current_('\0'), count_(0) { Read(); }
4766+ char Peek() const { return current_; }
4767+ char Take() { char c = current_; Read(); return c; }
4768+ size_t Tell() const { return count_; }
4769+ void Put(char c) { fputc(c, fp_); }
4770+ void Flush() { fflush(fp_); }
4771+
4772+ // Not implemented
4773+ char* PutBegin() { return 0; }
4774+ size_t PutEnd(char*) { return 0; }
4775+
4776+private:
4777+ // Prohibit copy constructor & assignment operator.
4778+ FileStream(const FileStream&);
4779+ FileStream& operator=(const FileStream&);
4780+
4781+ void Read() {
4782+ RAPIDJSON_ASSERT(fp_ != 0);
4783+ int c = fgetc(fp_);
4784+ if (c != EOF) {
4785+ current_ = (char)c;
4786+ count_++;
4787+ }
4788+ else if (current_ != '\0')
4789+ current_ = '\0';
4790+ }
4791+
4792+ std::FILE* fp_;
4793+ char current_;
4794+ size_t count_;
4795+};
4796+
4797+RAPIDJSON_NAMESPACE_END
4798+
4799+#endif // RAPIDJSON_FILESTREAM_H_
4800
4801=== added file 'shorts/xml2json/rapidjson/filewritestream.h'
4802--- shorts/xml2json/rapidjson/filewritestream.h 1970-01-01 00:00:00 +0000
4803+++ shorts/xml2json/rapidjson/filewritestream.h 2015-12-15 16:05:21 +0000
4804@@ -0,0 +1,97 @@
4805+// Copyright (C) 2011 Milo Yip
4806+//
4807+// Permission is hereby granted, free of charge, to any person obtaining a copy
4808+// of this software and associated documentation files (the "Software"), to deal
4809+// in the Software without restriction, including without limitation the rights
4810+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4811+// copies of the Software, and to permit persons to whom the Software is
4812+// furnished to do so, subject to the following conditions:
4813+//
4814+// The above copyright notice and this permission notice shall be included in
4815+// all copies or substantial portions of the Software.
4816+//
4817+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4818+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4819+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4820+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4821+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4822+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4823+// THE SOFTWARE.
4824+
4825+#ifndef RAPIDJSON_FILEWRITESTREAM_H_
4826+#define RAPIDJSON_FILEWRITESTREAM_H_
4827+
4828+#include "rapidjson.h"
4829+#include <cstdio>
4830+
4831+RAPIDJSON_NAMESPACE_BEGIN
4832+
4833+//! Wrapper of C file stream for input using fread().
4834+/*!
4835+ \note implements Stream concept
4836+*/
4837+class FileWriteStream {
4838+public:
4839+ typedef char Ch; //!< Character type. Only support char.
4840+
4841+ FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
4842+ RAPIDJSON_ASSERT(fp_ != 0);
4843+ }
4844+
4845+ void Put(char c) {
4846+ if (current_ >= bufferEnd_)
4847+ Flush();
4848+
4849+ *current_++ = c;
4850+ }
4851+
4852+ void PutN(char c, size_t n) {
4853+ size_t avail = static_cast<size_t>(bufferEnd_ - current_);
4854+ while (n > avail) {
4855+ std::memset(current_, c, avail);
4856+ current_ += avail;
4857+ Flush();
4858+ n -= avail;
4859+ avail = static_cast<size_t>(bufferEnd_ - current_);
4860+ }
4861+
4862+ if (n > 0) {
4863+ std::memset(current_, c, n);
4864+ current_ += n;
4865+ }
4866+ }
4867+
4868+ void Flush() {
4869+ if (current_ != buffer_) {
4870+ fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
4871+ current_ = buffer_;
4872+ }
4873+ }
4874+
4875+ // Not implemented
4876+ char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
4877+ char Take() { RAPIDJSON_ASSERT(false); return 0; }
4878+ size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
4879+ char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
4880+ size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
4881+
4882+private:
4883+ // Prohibit copy constructor & assignment operator.
4884+ FileWriteStream(const FileWriteStream&);
4885+ FileWriteStream& operator=(const FileWriteStream&);
4886+
4887+ std::FILE* fp_;
4888+ char *buffer_;
4889+ char *bufferEnd_;
4890+ char *current_;
4891+};
4892+
4893+//! Implement specialized version of PutN() with memset() for better performance.
4894+template<>
4895+inline void PutN(FileWriteStream& stream, char c, size_t n) {
4896+ stream.PutN(c, n);
4897+}
4898+
4899+RAPIDJSON_NAMESPACE_END
4900+
4901+#endif // RAPIDJSON_FILESTREAM_H_
4902
4903=== added directory 'shorts/xml2json/rapidjson/internal'
4904=== added file 'shorts/xml2json/rapidjson/internal/biginteger.h'
4905--- shorts/xml2json/rapidjson/internal/biginteger.h 1970-01-01 00:00:00 +0000
4906+++ shorts/xml2json/rapidjson/internal/biginteger.h 2015-12-15 16:05:21 +0000
4907@@ -0,0 +1,294 @@
4908+// Copyright (C) 2011 Milo Yip
4909+//
4910+// Permission is hereby granted, free of charge, to any person obtaining a copy
4911+// of this software and associated documentation files (the "Software"), to deal
4912+// in the Software without restriction, including without limitation the rights
4913+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4914+// copies of the Software, and to permit persons to whom the Software is
4915+// furnished to do so, subject to the following conditions:
4916+//
4917+// The above copyright notice and this permission notice shall be included in
4918+// all copies or substantial portions of the Software.
4919+//
4920+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4921+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4922+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4923+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4924+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4925+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4926+// THE SOFTWARE.
4927+
4928+#ifndef RAPIDJSON_BIGINTEGER_H_
4929+#define RAPIDJSON_BIGINTEGER_H_
4930+
4931+#include "../rapidjson.h"
4932+
4933+#if defined(_MSC_VER) && defined(_M_AMD64)
4934+#include <intrin.h> // for _umul128
4935+#endif
4936+
4937+RAPIDJSON_NAMESPACE_BEGIN
4938+namespace internal {
4939+
4940+class BigInteger {
4941+public:
4942+ typedef uint64_t Type;
4943+
4944+ BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
4945+ std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
4946+ }
4947+
4948+ explicit BigInteger(uint64_t u) : count_(1) {
4949+ digits_[0] = u;
4950+ }
4951+
4952+ BigInteger(const char* decimals, size_t length) : count_(1) {
4953+ RAPIDJSON_ASSERT(length > 0);
4954+ digits_[0] = 0;
4955+ size_t i = 0;
4956+ const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
4957+ while (length >= kMaxDigitPerIteration) {
4958+ AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
4959+ length -= kMaxDigitPerIteration;
4960+ i += kMaxDigitPerIteration;
4961+ }
4962+
4963+ if (length > 0)
4964+ AppendDecimal64(decimals + i, decimals + i + length);
4965+ }
4966+
4967+ BigInteger& operator=(uint64_t u) {
4968+ digits_[0] = u;
4969+ count_ = 1;
4970+ return *this;
4971+ }
4972+
4973+ BigInteger& operator+=(uint64_t u) {
4974+ Type backup = digits_[0];
4975+ digits_[0] += u;
4976+ for (size_t i = 0; i < count_ - 1; i++) {
4977+ if (digits_[i] >= backup)
4978+ return *this; // no carry
4979+ backup = digits_[i + 1];
4980+ digits_[i + 1] += 1;
4981+ }
4982+
4983+ // Last carry
4984+ if (digits_[count_ - 1] < backup)
4985+ PushBack(1);
4986+
4987+ return *this;
4988+ }
4989+
4990+ BigInteger& operator*=(uint64_t u) {
4991+ if (u == 0) return *this = 0;
4992+ if (u == 1) return *this;
4993+ if (*this == 1) return *this = u;
4994+
4995+ uint64_t k = 0;
4996+ for (size_t i = 0; i < count_; i++) {
4997+ uint64_t hi;
4998+ digits_[i] = MulAdd64(digits_[i], u, k, &hi);
4999+ k = hi;
5000+ }
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches