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
=== modified file 'shorts.apparmor'
--- shorts.apparmor 2015-10-24 07:06:24 +0000
+++ shorts.apparmor 2015-12-15 16:05:21 +0000
@@ -1,7 +1,9 @@
1{1{
2 "policy_groups": [2 "policy_groups": [
3 "networking",3 "networking",
4 "content_exchange_source"4 "content_exchange_source",
5 "content_exchange",
6 "location"
5 ],7 ],
6 "policy_version": 1.38 "policy_version": 1.3
7}9}
810
=== modified file 'shorts/CMakeLists.txt'
--- shorts/CMakeLists.txt 2015-08-11 12:07:22 +0000
+++ shorts/CMakeLists.txt 2015-12-15 16:05:21 +0000
@@ -5,6 +5,7 @@
5 main.cpp5 main.cpp
6 CachingNetworkManagerFactory.cpp6 CachingNetworkManagerFactory.cpp
7 shorts.qrc7 shorts.qrc
8 xml2json/utilities.cpp
89
9 )10 )
1011
1112
=== modified file 'shorts/main.cpp'
--- shorts/main.cpp 2015-07-19 14:29:20 +0000
+++ shorts/main.cpp 2015-12-15 16:05:21 +0000
@@ -1,8 +1,9 @@
1#include <QGuiApplication>1#include <QGuiApplication>
2#include <QQmlApplicationEngine>2#include <QQmlApplicationEngine>
3#include <QQuickView>3#include <QtQuick>
44
5#include "CachingNetworkManagerFactory.h"5#include "CachingNetworkManagerFactory.h"
6#include "xml2json/utilities.h"
67
7int main(int argc, char *argv[])8int main(int argc, char *argv[])
8{9{
@@ -16,6 +17,9 @@
16 CachingNetworkManagerFactory *managerFactory = new CachingNetworkManagerFactory();17 CachingNetworkManagerFactory *managerFactory = new CachingNetworkManagerFactory();
17 view.engine()->setNetworkAccessManagerFactory(managerFactory);18 view.engine()->setNetworkAccessManagerFactory(managerFactory);
1819
20 Utilities *utilities = new Utilities();
21 view.engine()->rootContext()->setContextProperty("utilities", utilities);
22
19 view.setSource(QUrl(QStringLiteral("qrc:///qml/shorts-app.qml")));23 view.setSource(QUrl(QStringLiteral("qrc:///qml/shorts-app.qml")));
20// view.setSource(QUrl("./share/qml/shorts-app.qml"));24// view.setSource(QUrl("./share/qml/shorts-app.qml"));
21 view.setResizeMode(QQuickView::SizeRootObjectToView);25 view.setResizeMode(QQuickView::SizeRootObjectToView);
2226
=== modified file 'shorts/po/com.ubuntu.shorts.pot'
--- shorts/po/com.ubuntu.shorts.pot 2015-12-01 17:03:50 +0000
+++ shorts/po/com.ubuntu.shorts.pot 2015-12-15 16:05:21 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: \n"9"Project-Id-Version: \n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2015-12-01 17:27+0800\n"11"POT-Creation-Date: 2015-12-03 17:59+0800\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -42,11 +42,41 @@
42msgid "Large"42msgid "Large"
43msgstr ""43msgstr ""
4444
45#: ../qml/pages/AppendFeedPage.qml:31 ../qml/shorts-app.qml:24345#: ../qml/nongoogle/AppendNGFeedPage.qml:30 ../qml/pages/AppendFeedPage.qml:31
46#: ../qml/shorts-app.qml:37846#: ../qml/shorts-app.qml:255 ../qml/shorts-app.qml:390
47#: ../qml/shorts-app.qml:398
47msgid "Add feeds"48msgid "Add feeds"
48msgstr ""49msgstr ""
4950
51#: ../qml/nongoogle/AppendNGFeedPage.qml:105
52#: ../qml/pages/AppendFeedPage.qml:137
53msgid "Type a keyword or URL"
54msgstr ""
55
56#: ../qml/nongoogle/AppendNGFeedPage.qml:162
57msgid "Feed Title:"
58msgstr ""
59
60#: ../qml/nongoogle/AppendNGFeedPage.qml:170
61#: ../qml/nongoogle/AppendNGFeedPage.qml:185
62msgid "No data"
63msgstr ""
64
65#: ../qml/nongoogle/AppendNGFeedPage.qml:177
66msgid "Feed Description:"
67msgstr ""
68
69#: ../qml/nongoogle/AppendNGFeedPage.qml:210
70#: ../qml/pages/AppendFeedPage.qml:243 ../qml/pages/CreateTopicPage.qml:38
71#: ../qml/pages/TopicManagement.qml:239 ../qml/shorts-app.qml:481
72msgid "Cancel"
73msgstr ""
74
75#: ../qml/nongoogle/AppendNGFeedPage.qml:243
76#: ../qml/pages/AppendFeedPage.qml:276
77msgid "Next"
78msgstr ""
79
50#: ../qml/pages/AppendFeedPage.qml:6980#: ../qml/pages/AppendFeedPage.qml:69
51msgid "Failed to perform a feed search by keyword"81msgid "Failed to perform a feed search by keyword"
52msgstr ""82msgstr ""
@@ -59,23 +89,10 @@
59msgid "Failed to perform a feed search by URL"89msgid "Failed to perform a feed search by URL"
60msgstr ""90msgstr ""
6191
62#: ../qml/pages/AppendFeedPage.qml:137
63msgid "Type a keyword or URL"
64msgstr ""
65
66#: ../qml/pages/AppendFeedPage.qml:18592#: ../qml/pages/AppendFeedPage.qml:185
67msgid "Search results"93msgid "Search results"
68msgstr ""94msgstr ""
6995
70#: ../qml/pages/AppendFeedPage.qml:243 ../qml/pages/CreateTopicPage.qml:38
71#: ../qml/pages/TopicManagement.qml:239 ../qml/shorts-app.qml:456
72msgid "Cancel"
73msgstr ""
74
75#: ../qml/pages/AppendFeedPage.qml:276
76msgid "Next"
77msgstr ""
78
79#: ../qml/pages/AppendFeedPage.qml:305 ../qml/pages/CreateTopicPage.qml:18196#: ../qml/pages/AppendFeedPage.qml:305 ../qml/pages/CreateTopicPage.qml:181
80msgid "No feeds"97msgid "No feeds"
81msgstr ""98msgstr ""
@@ -118,6 +135,7 @@
118135
119#: ../qml/pages/ChooseTopicPage.qml:109 ../qml/pages/ChooseTopicPage.qml:122136#: ../qml/pages/ChooseTopicPage.qml:109 ../qml/pages/ChooseTopicPage.qml:122
120#: ../qml/pages/CreateTopicPage.qml:66 ../qml/pages/CreateTopicPage.qml:78137#: ../qml/pages/CreateTopicPage.qml:66 ../qml/pages/CreateTopicPage.qml:78
138#: ../qml/shorts-app.qml:568
121msgid "Warning"139msgid "Warning"
122msgstr ""140msgstr ""
123141
@@ -161,7 +179,15 @@
161msgid "Topic: "179msgid "Topic: "
162msgstr ""180msgstr ""
163181
164#: ../qml/pages/TopicManagement.qml:13 ../qml/shorts-app.qml:217182#: ../qml/pages/PageSettings.qml:9 ../qml/shorts-app.qml:239
183msgid "Settings"
184msgstr ""
185
186#: ../qml/pages/PageSettings.qml:21
187msgid "Use Google Search: "
188msgstr ""
189
190#: ../qml/pages/TopicManagement.qml:13 ../qml/shorts-app.qml:219
165msgid "Edit topics"191msgid "Edit topics"
166msgstr ""192msgstr ""
167193
@@ -173,74 +199,88 @@
173msgid "Add Feed"199msgid "Add Feed"
174msgstr ""200msgstr ""
175201
176#: ../qml/shorts-app.qml:184202#: ../qml/shorts-app.qml:186
177msgid "Refresh"203msgid "Refresh"
178msgstr ""204msgstr ""
179205
180#: ../qml/shorts-app.qml:191206#: ../qml/shorts-app.qml:193
181msgid "Grid View"207msgid "Grid View"
182msgstr ""208msgstr ""
183209
184#: ../qml/shorts-app.qml:191210#: ../qml/shorts-app.qml:193
185msgid "List view"211msgid "List view"
186msgstr ""212msgstr ""
187213
188#: ../qml/shorts-app.qml:227214#: ../qml/shorts-app.qml:229
189msgid "Disable night mode"215msgid "Disable night mode"
190msgstr ""216msgstr ""
191217
192#: ../qml/shorts-app.qml:227218#: ../qml/shorts-app.qml:229
193msgid "Enable night mode"219msgid "Enable night mode"
194msgstr ""220msgstr ""
195221
196#: ../qml/shorts-app.qml:309222#: ../qml/shorts-app.qml:321
197msgid "Saved"223msgid "Saved"
198msgstr ""224msgstr ""
199225
200#: ../qml/shorts-app.qml:317 shorts.desktop.in.in.h:1226#: ../qml/shorts-app.qml:329 shorts.desktop.in.in.h:1
201msgid "Shorts"227msgid "Shorts"
202msgstr ""228msgstr ""
203229
204#: ../qml/shorts-app.qml:448230#: ../qml/shorts-app.qml:473
205msgid "Checking for new articles"231msgid "Checking for new articles"
206msgstr ""232msgstr ""
207233
208#: ../qml/shorts-app.qml:472234#: ../qml/shorts-app.qml:497
209msgid "Perhaps some of the channels have not been updated."235msgid "Perhaps some of the channels have not been updated."
210msgstr ""236msgstr ""
211237
212#: ../qml/shorts-app.qml:473238#: ../qml/shorts-app.qml:498
213msgid "Errors occurred during the update"239msgid "Errors occurred during the update"
214msgstr ""240msgstr ""
215241
216#: ../qml/shorts-app.qml:491242#: ../qml/shorts-app.qml:516
217msgid "+ Add feeds"243msgid "+ Add feeds"
218msgstr ""244msgstr ""
219245
220#: ../qml/shorts-app.qml:503246#: ../qml/shorts-app.qml:528
221msgid "Add online accounts"247msgid "Add online accounts"
222msgstr ""248msgstr ""
223249
224#: ../qml/shorts-app.qml:506250#: ../qml/shorts-app.qml:531
225msgid "Online accounts are not available for now"251msgid "Online accounts are not available for now"
226msgstr ""252msgstr ""
227253
228#: ../qml/shorts-app.qml:507 ../qml/shorts-app.qml:516254#: ../qml/shorts-app.qml:532 ../qml/shorts-app.qml:541
229msgid "We are sorry"255msgid "We are sorry"
230msgstr ""256msgstr ""
231257
232#: ../qml/shorts-app.qml:512258#: ../qml/shorts-app.qml:537
233msgid "Import subscriptions"259msgid "Import subscriptions"
234msgstr ""260msgstr ""
235261
236#: ../qml/shorts-app.qml:515262#: ../qml/shorts-app.qml:540
237msgid "Importing subscriptions is not available for now"263msgid "Importing subscriptions is not available for now"
238msgstr ""264msgstr ""
239265
240#: ../qml/shorts-app.qml:530266#: ../qml/shorts-app.qml:555
241msgid "Ok"267msgid "Ok"
242msgstr ""268msgstr ""
243269
270#: ../qml/shorts-app.qml:569
271msgid ""
272"Shorts detects that you're located in an area which blocks Google's IP."
273"<br><br>"
274msgstr ""
275
276#: ../qml/shorts-app.qml:574
277msgid "Yes, please."
278msgstr ""
279
280#: ../qml/shorts-app.qml:584
281msgid "No, thanks."
282msgstr ""
283
244#: ../qml/tabs/BaseTab.qml:153284#: ../qml/tabs/BaseTab.qml:153
245msgid "There are no articles to show"285msgid "There are no articles to show"
246msgstr ""286msgstr ""
247287
=== modified file 'shorts/qml/CMakeLists.txt'
--- shorts/qml/CMakeLists.txt 2015-07-17 14:42:42 +0000
+++ shorts/qml/CMakeLists.txt 2015-12-15 16:05:21 +0000
@@ -19,3 +19,4 @@
19add_subdirectory(pages)19add_subdirectory(pages)
20add_subdirectory(tabs)20add_subdirectory(tabs)
21add_subdirectory(utils)21add_subdirectory(utils)
22add_subdirectory(nongoogle)
2223
=== modified file 'shorts/qml/components/NetworkManager.qml'
--- shorts/qml/components/NetworkManager.qml 2015-10-24 07:06:24 +0000
+++ shorts/qml/components/NetworkManager.qml 2015-12-15 16:05:21 +0000
@@ -9,6 +9,9 @@
9import "../utils/imgSeparator.js" as ImageUtils9import "../utils/imgSeparator.js" as ImageUtils
10import "../utils/dateutils.js" as DateUtils10import "../utils/dateutils.js" as DateUtils
1111
12// below import for non-google usage
13import "../nongoogle"
14
12Item {15Item {
13 id: networkManagerRoot16 id: networkManagerRoot
1417
@@ -18,11 +21,21 @@
18 property string operationStatus: "success"21 property string operationStatus: "success"
1922
20 function updateFeeds(feedsArray, topicId) {23 function updateFeeds(feedsArray, topicId) {
21 d.updateFeeds(feedsArray, topicId)24 if (optionsKeeper.useGoogleSearch()) {
25 d.updateFeeds(feedsArray, topicId)
26 }
27 else {
28 dNG.updateFeeds(feedsArray, topicId)
29 }
22 }30 }
2331
24 function cancelDownload() {32 function cancelDownload() {
25 d.cancelDownload()33 if (optionsKeeper.useGoogleSearch()) {
34 d.cancelDownload()
35 }
36 else {
37 dNG.cancelDownload()
38 }
26 }39 }
2740
28 /* All private method are inside QtObject.41 /* All private method are inside QtObject.
@@ -129,4 +142,133 @@
129 }142 }
130 } // GFA143 } // GFA
131 } // QtObject144 } // QtObject
145
146 ////////////////////////////////////////// add a new object to refresh non-google feeds
147 QtObject {
148 id: dNG
149
150 property var feedList: [] // Feed list to update.
151 property var currentFeed // Current downloading feed.
152 property int tagId: 0 // Tag to update.
153
154 /* Method updates feeds one by another.
155 * Input: array of objects, each should include
156 * source, link and id (of feed in DB) properties.
157 */
158 function updateFeeds(feedsArray, topicId) {
159 tagId = topicId || 0
160
161 downloadStarted(tagId)
162
163 feedList = feedsArray
164 operationStatus = "success"
165 updateNextFeed()
166 }
167
168 // For inner usage only.
169 function updateNextFeed() {
170 if (feedList.length == 0) {
171 downloadFinished(tagId)
172 return
173 }
174
175 currentFeed = feedList.shift()
176 nonGoogleFeedApi.loadFeed(currentFeed.source)
177 }
178
179 function cancelDownload() {
180 feedList = []
181 operationStatus = "abort"
182 nonGoogleFeedApi.abort()
183 }
184
185 function updateFeedInfo(feedId, feedLink, responseData) {
186 var entries = responseData.item
187 var f = responseData
188
189 var fde = f.description == undefined ? "" : f.description["#text"] == undefined ? f.description : f.description["#text"]
190 var fti = f.title == undefined ? "" : f.title["#text"] == undefined ? f.title : f.title["#text"]
191
192 DB.updateFeedByXml(feedId, feedLink, fde, fti)
193 console.log(" -------- UPDATE INFO -------- ")
194 // console.log(f.title, f.link, f.feedUrl, f.description)
195
196 console.time("addArticlesEx")
197
198 var newArticles = []
199 var maxLength = entries.length > 50 ? 50 : entries.length
200 for (var i = 0; i < maxLength; i++) {
201 var e = entries[i]
202
203 // print("article detail: ", JSON.stringify(e))
204 // Grab image from for article.
205 // var articleImage = ImageUtils.grabArticleImage(e)
206 // e.content = clearFromBadTags(e.content)
207
208 var ti = e.title == undefined ? "" : e.title["#text"] == undefined ? e.title : e.title["#text"]
209 var li = e.link == undefined ? "" : e.link["#text"] == undefined ? e.link : e.link["#text"]
210 var au = e.author == undefined ? "" : e.author["#text"] == undefined ? e.author : e.author["#text"]
211 var creator = e.creator == undefined ? "" : e.creator["#text"] == undefined ? e.creator : e.creator["#text"]
212 var de = e.description == undefined ? "" : e.description["#text"] == undefined ? e.description : e.description["#text"]
213 var pu = e.pubDate == undefined ? "" : e.pubDate["#text"] == undefined ? e.pubDate : e.pubDate["#text"]
214 var co = e.content == undefined ? "" : e.content["#text"] == undefined ? e.content : e.content["#text"]
215 var articleImage = utilities.htmlGetImg(de)
216 if (articleImage.length == 0) { articleImage = utilities.htmlGetImg(co) }
217 else {
218 print("articleImage: ", articleImage[0])
219 }
220 // print("date parse 0: ", pu, DateUtils.parseDate(pu))
221 // print("date parse 1: ", DateUtils.formatRelativeTime(i18n, DateUtils.parseDate(pu)))
222
223 var temp =
224 {
225 "title": ti,
226 "content": co == "" ? de : co,
227 "link": li,
228 "author": creator == "" ? au : creator,
229 "description": de,
230 "pubDate": DateUtils.parseDate(pu),
231 "guid": Qt.md5(li + pu),
232 "image" : articleImage.length > 0 ? articleImage[0] : "",
233 "media_groups" : ""
234 }
235
236 newArticles.push(temp)
237 }
238// print("new article length: ", newArticles.length)
239
240 // /* Add new articles to DB and restore 'read' status of some of them.
241 // */
242 // DB.addArticles(articleModel, feedId, articleProperties);
243
244 /* Add new articles to DB and restore 'read' status of some of them. */
245 try {
246 DB.addArticlesEx(newArticles, feedId)
247 } catch (e) {
248 console.log("Exception:", JSON.stringify(e))
249 }
250
251 console.timeEnd("addArticlesEx")
252 }
253
254 function clearFromBadTags(content) {
255 /* Remove non empty too. Useless anyway.
256 */
257 content = content.replace(/alt=".*?"/g, "")
258 content = content.replace(/title=".*?"/g, "")
259 return content
260 }
261
262 property var nonGoogleFeedApi: XmlNetwork {
263 onLoadResult: {
264 if (result.rss == undefined || result.rss == "") {
265// console.log("XML NETWORK GFA:", JSON.stringify(result))
266 if (operationStatus == "success")
267 operationStatus = "withErrors"
268 } else dNG.updateFeedInfo(dNG.currentFeed.id, dNG.currentFeed.link, result.rss.channel)
269
270 dNG.updateNextFeed()
271 }
272 } // GFA
273 } // QtObject
132}274}
133275
=== modified file 'shorts/qml/components/OptionsKeeper.qml'
--- shorts/qml/components/OptionsKeeper.qml 2015-10-10 11:24:04 +0000
+++ shorts/qml/components/OptionsKeeper.qml 2015-12-15 16:05:21 +0000
@@ -14,6 +14,11 @@
14 fontSize = getFontSize()14 fontSize = getFontSize()
15 useDarkTheme = getUseDarkTheme()15 useDarkTheme = getUseDarkTheme()
16 useListMode = getUseListMode()16 useListMode = getUseListMode()
17
18
19 if (useGoogleSearch() == undefined ) {
20 setUseGoogleSearch(true)
21 }
17 }22 }
1823
19 onFontSizeChanged: setFontSize(fontSize)24 onFontSizeChanged: setFontSize(fontSize)
@@ -64,6 +69,17 @@
64 return settingsDocument.contents.dbLastUpdate69 return settingsDocument.contents.dbLastUpdate
65 }70 }
6671
72 /////////////////////////////////////////////////////// below two functions are get/set "useGoogleSearch" value
73 function useGoogleSearch() {
74 return settingsDocument.contents.useGoogleSearch
75 }
76
77 function setUseGoogleSearch(value) {
78 var cont = settingsDocument.contents
79 cont.useGoogleSearch = value
80 settingsDocument.contents = cont
81 }
82
67 U1db.Database {83 U1db.Database {
68 id: settingsDataBase84 id: settingsDataBase
69 path: "ShortsOptions"85 path: "ShortsOptions"
@@ -75,6 +91,8 @@
75 docId: 'settingsDocument'91 docId: 'settingsDocument'
76 create: true92 create: true
77 defaults: { "useDarkTheme" : false, "fontSize" : 1,93 defaults: { "useDarkTheme" : false, "fontSize" : 1,
78 "useListMode" : false, "dbVersion" : 1.2}94 "useListMode" : false, "dbVersion" : 1.2,
95 "useGoogleSearch" : true
96 }
79 }97 }
80} // Item98} // Item
8199
=== added directory 'shorts/qml/nongoogle'
=== added file 'shorts/qml/nongoogle/AppendNGFeedPage.qml'
--- shorts/qml/nongoogle/AppendNGFeedPage.qml 1970-01-01 00:00:00 +0000
+++ shorts/qml/nongoogle/AppendNGFeedPage.qml 2015-12-15 16:05:21 +0000
@@ -0,0 +1,254 @@
1/*
2 * Copyright (C) 2013, 2014
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.4
18import QtQuick.XmlListModel 2.0
19import Ubuntu.Components 1.3
20import Ubuntu.Components.ListItems 1.3 as ListItem
21import Ubuntu.Components.Popups 1.3
22
23import "../utils/databasemodule_v2.js" as DB
24import "../."
25
26Page {
27 id: appendFeedPage
28
29 objectName: "appendfeedpage"
30 title: i18n.tr("Add feeds")
31 flickable: null
32 visible: false
33
34 property bool isDirty: false // Need to clear all page content.
35 property int selectedCount: 0
36 property bool resultsReceived: false // Indicates that at least once results were received.
37
38 function reloadPageContent() {
39 }
40
41 /* Clear model and model's depend data.
42 * Currently only selectedCount.
43 */
44 function clearModelDependData() {
45// searchResultsModel.clear()
46// selectedCount = 0
47 }
48
49 // ------------------------------------- XmlNetwork
50
51 property string feedTitle: ""
52 property string feedDesc: ""
53 property string feedUrl: ""
54 property string feedLink: ""
55 property var feedObj
56
57 XmlNetwork {
58 id: xmlFeedApi
59
60 onLoadResult: {
61 if (result.rss == undefined || result.rss == "") {
62 // TODO alert that fail retriving feed data
63 print("onLoadResult failed")
64 }
65 else {
66// d.updateFeedInfo(d.currentFeed.id, d.currentFeed.link, result.rss.channel)
67 var f = result.rss.channel
68
69 feedDesc = f.description == undefined ? "" : f.description["#text"] == undefined ? f.description : f.description["#text"]
70 feedTitle = f.title == undefined ? "" : f.title["#text"] == undefined ? f.title : f.title["#text"]
71// feedUrl = l
72 feedLink = f.link == undefined ? "" : f.link["#text"] == undefined ? f.link : f.link["#text"]
73 feedObj = {
74 "url" : feedUrl,
75 "title" : feedTitle,
76 "description" : feedDesc,
77 "link" : feedLink
78 }
79 }
80
81 }
82 }
83
84 // ------------------------------------- XmlNetwork
85
86 Column {
87 id: appendFeedColumn
88
89 anchors.top: parent.top
90 anchors.topMargin: units.gu(2)
91 width: parent.width
92 spacing: units.gu(2)
93
94 TextField {
95 objectName: "tfFeedUrl"
96 id: tfFeedUrl
97
98 placeholderText: i18n.tr("Type a keyword or URL")
99
100 width: parent.width - units.gu(4)
101 // height:units.gu(5)
102 anchors {
103 horizontalCenter: parent.horizontalCenter
104 }
105 primaryItem: Image {
106 height: parent.height*0.5
107 width: height
108 anchors.verticalCenter: parent.verticalCenter
109 // anchors.verticalCenterOffset: -units.gu(0.2)
110 source: Qt.resolvedUrl("../icons_tmp/find.svg")
111 smooth: true
112
113 MouseArea {
114 anchors.fill: parent
115 onClicked: {
116 if (Qt.inputMethod.visible)
117 tfFeedUrl.accapt()
118 }
119 }
120 }
121
122 onAccepted: {
123 accapt()
124 }
125
126 function accapt() {
127 Qt.inputMethod.hide()
128 var userInput = text
129
130 if (userInput == "")
131 return
132
133 // Very simple logic, URL if there are no spaces and contains dots.
134 // But simple not means that it is wrong.
135 var isUrlEntered = (userInput.indexOf(" ") === -1 && userInput.indexOf(".") !== -1)
136
137 if (isUrlEntered) {
138 if (userInput.indexOf("http://") !== 0)
139 {userInput = "http://" + userInput}
140 feedUrl = userInput
141 xmlFeedApi.loadFeed(userInput)
142 }
143// else xmlFeedApi.findFeeds(text)
144 else {
145 // TODO alert that user input invalid
146 print("input invalid")
147 }
148 }
149 }
150
151 ListItem.Header {
152
153 ListItem.ThinDivider { }
154
155 text: i18n.tr("Feed Title:")
156
157 ListItem.ThinDivider { anchors.bottom: parent.bottom }
158 }
159
160 Label {
161 anchors { left: parent.left;right: parent.right; margins: units.gu(2) }
162 wrapMode: Text.WrapAtWordBoundaryOrAnywhere
163 text: feedTitle == "" ? i18n.tr("No data") : feedTitle
164 }
165
166 ListItem.Header {
167
168 ListItem.ThinDivider { }
169
170 text: i18n.tr("Feed Description:")
171
172 ListItem.ThinDivider { anchors.bottom: parent.bottom }
173 }
174
175 Label {
176 anchors { left: parent.left;right: parent.right; margins: units.gu(2) }
177 wrapMode: Text.WrapAtWordBoundaryOrAnywhere
178 text: feedDesc == "" ? i18n.tr("No data") : feedDesc
179 }
180 } // Column
181
182 Rectangle {
183 id: fakePanel
184
185 color: "#fafafa"
186 anchors {
187 left: parent.left
188 right: parent.right
189 bottom: parent.bottom
190 }
191 height: units.gu(6)
192 Item {
193 anchors.fill: parent
194
195 Button {
196 anchors {
197 verticalCenter: parent.verticalCenter
198 left: parent.left
199 leftMargin: units.gu(1)
200 }
201 gradient: UbuntuColors.greyGradient
202 action: Action {
203 text: i18n.tr("Cancel")
204
205 onTriggered: {
206 xmlFeedApi.abort()
207 pageStack.pop()
208 }
209 }
210 }
211
212 ActivityIndicator {
213 id: checkRunning
214
215 visible: xmlFeedApi.inProgress
216 running: xmlFeedApi.inProgress
217
218 anchors {
219 verticalCenter: parent.verticalCenter
220 right: nextBtn.left
221 rightMargin: units.gu(1)
222 }
223 }
224
225 Button {
226 id: nextBtn
227 objectName: "nextButton"
228 anchors {
229 verticalCenter: parent.verticalCenter
230 right: parent.right
231 rightMargin: units.gu(1)
232 }
233
234 enabled: !xmlFeedApi.inProgress && feedUrl != "" && feedTitle != ""
235 action: Action {
236 text: i18n.tr("Next")
237
238 onTriggered: {
239 if (!nextBtn.enabled)
240 return
241
242 var selectedFeeds = []
243
244 selectedFeeds.push(feedObj)
245
246 pageStack.push(chooseTopicPage, {"feedsToAdd" : selectedFeeds})
247// pageStack.push(Qt.resolvedUrl("../pages/ChooseTopicPage.qml"), {"feedsToAdd" : selectedFeeds})
248 }
249 }
250 } // Button
251 }
252 } // Rectangle fakePanel
253
254}
0255
=== added file 'shorts/qml/nongoogle/CMakeLists.txt'
--- shorts/qml/nongoogle/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ shorts/qml/nongoogle/CMakeLists.txt 2015-12-15 16:05:21 +0000
@@ -0,0 +1,6 @@
1file(GLOB NONGOOGLE_QML_JS_FILES *.qml *.js)
2
3# make the files visible in the qtcreator tree
4add_custom_target(ubuntu-rssreader-app_nongoogle_QMlFiles ALL SOURCES ${NONGOOGLE_QML_JS_FILES})
5
6install(FILES ${NONGOOGLE_QML_JS_FILES} DESTINATION ${SHORTS_DIR}/nongoogle/)
0\ No newline at end of file7\ No newline at end of file
18
=== added file 'shorts/qml/nongoogle/Positioner.qml'
--- shorts/qml/nongoogle/Positioner.qml 1970-01-01 00:00:00 +0000
+++ shorts/qml/nongoogle/Positioner.qml 2015-12-15 16:05:21 +0000
@@ -0,0 +1,114 @@
1/*
2 * Copyright (C) 2014-2015 Canonical Ltd
3 *
4 * This file is part of Ubuntu Clock App
5 *
6 * Ubuntu Clock App is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * Ubuntu Clock App is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.4
20import U1db 1.0 as U1db
21import QtPositioning 5.2
22import Ubuntu.Components 1.3
23import Ubuntu.Components.Popups 1.3
24//import "../components"
25
26Item {
27 id: positioner
28 objectName: "positioner"
29
30 anchors.fill: parent
31
32 // Property to keep track of app cold start status
33 property string countryCode: ""
34
35 Component.onCompleted: {
36 }
37
38 PositionSource {
39 id: geoposition
40
41 // Property to store the time of the last GPS location update
42 property var lastUpdate
43
44 readonly property real userLongitude: position.coordinate.longitude
45
46 readonly property real userLatitude: position.coordinate.latitude
47
48 active: true
49 updateInterval: 1000
50
51 onSourceErrorChanged: {
52 // Stop querying user location if location service is not available
53 if (sourceError !== PositionSource.NoError) {
54 console.log("[Source Error]: Location Service Error")
55 geoposition.stop()
56
57 }
58 }
59
60 onPositionChanged: {
61 // Do not accept an invalid user location
62 if(!position.longitudeValid || !position.latitudeValid) {
63 return
64 }
65
66 if(position.longitudeValid || position.latitudeValid) {
67 print("current position: ", userLatitude, userLongitude)
68 geoposition.stop()
69 getCountryCode(userLatitude, userLongitude)
70 }
71
72
73 }
74
75 /* get country code from geonames.org
76 // http://api.geonames.org/countryCode?lat=23&lng=113&username=krnekhelesh
77 */
78 function getCountryCode(lat, lng) {
79
80 var url = "http://api.geonames.org/countryCode?lat=" + lat + "&lng=" + lng + "&username=krnekhelesh&type=JSON"
81
82 var doc = new XMLHttpRequest()
83
84 doc.onreadystatechange = function() {
85
86 // print("positioner onreadystatechange: ", doc.readyState, doc.status, feedUrl)
87 if (doc.readyState === XMLHttpRequest.DONE) {
88
89 var resObj
90 if (doc.status == 200) {
91 resObj = JSON.parse(doc.responseText)
92 } else { // Error
93 resObj = {"responseDetails" : doc.statusText,
94 "responseStatus" : doc.status}
95// resObj = ""
96 }
97
98 countryCode = resObj.countryName
99 print("countryCode", resObj)
100
101 if (countryCode == "China") {
102 if (optionsKeeper.useGoogleSearch()) {
103 PopupUtils.open(componentDialogNG, tabstabs)
104 }
105 }
106 }
107 }
108
109 doc.open("GET", url, true);
110 doc.send();
111 }
112 } //PositionSource
113
114}
0115
=== added file 'shorts/qml/nongoogle/XmlNetwork.qml'
--- shorts/qml/nongoogle/XmlNetwork.qml 1970-01-01 00:00:00 +0000
+++ shorts/qml/nongoogle/XmlNetwork.qml 2015-12-15 16:05:21 +0000
@@ -0,0 +1,84 @@
1import QtQuick 2.4
2
3QtObject {
4 id: rootObject
5
6 property bool inProgress: __doc != null
7
8 signal findResult(var result)
9 signal loadResult(var result)
10
11 property var __doc: null
12
13 /* Load feed by URL.
14 */
15 function loadFeed(feedUrl, num) {
16 abort(true)
17
18 if (num)
19 num = Math.min(num, 100)
20 else num = 50
21
22 __doc = new XMLHttpRequest()
23 var doc = __doc
24
25 doc.onreadystatechange = function() {
26
27// print("xmlnetwork onreadystatechange: ", doc.readyState, doc.status, feedUrl)
28 if (doc.readyState === XMLHttpRequest.DONE) {
29
30 var resObj
31 if (doc.status == 200) {
32// resObj = JSON.parse(doc.responseText)
33 resObj = utilities.xmlToJson(doc.responseText)
34 } else { // Error
35 resObj = {"responseDetails" : doc.statusText,
36 "responseStatus" : doc.status}
37 }
38
39 __doc = null
40 loadResult(resObj)
41 }
42 }
43
44
45 /* Number of articles to download.
46 */
47// finalRequest += "&num=" + num
48
49 /* Add some optional params.
50 * May be usable:
51 * hl - host language, for example "hl=ru", default en.
52 * num - number of entries, for example "num=50", default 4, maximum 100.
53 * output - format of output, for example "output=json", may be xml, json_xml, json.
54 */
55// doc.open("GET", finalRequest, true);
56 doc.open("GET", feedUrl, true);
57 doc.send();
58 }
59
60 /* Param "isAbortOnly" used to preserve
61 * property "__doc" in not null state.
62 * inProgress binded to it so we can avoid
63 * additional recalculations.
64 */
65 function abort(isAbortOnly) {
66 if (__doc != null) {
67 __doc.abort()
68 if (!isAbortOnly)
69 __doc = null
70 }
71 }
72
73 /* Return true if some kind of errors detected.
74 * TODO DEMO
75 */
76 function checkForErrors(result) {
77 if (result.responseStatus == 200 || // HTTP OK
78 result.responseStatus == 0) { // ABORTED
79 return false
80 }
81
82 return true
83 }
84} // QtObject
085
=== added file 'shorts/qml/pages/PageSettings.qml'
--- shorts/qml/pages/PageSettings.qml 1970-01-01 00:00:00 +0000
+++ shorts/qml/pages/PageSettings.qml 2015-12-15 16:05:21 +0000
@@ -0,0 +1,62 @@
1import QtQuick 2.4
2import Ubuntu.Components 1.3
3import Ubuntu.Components.ListItems 1.3 as ListItem
4import Ubuntu.Components.Popups 1.3
5import "../components"
6
7Page {
8 id: pageSettings
9 title: i18n.tr("Settings")
10 flickable: null
11
12 Column {
13 anchors {
14 top: parent.top; topMargin: units.gu(1)
15 left: parent.left; leftMargin: units.gu(1)
16 right: parent.right; rightMargin: units.gu(1)
17 }
18 height: childrenRect.height
19 spacing: units.gu(0.8)
20
21 ///////////////////////////////////////////////////////////////////// Google RSS engine switch start here
22 Label {
23 anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
24 horizontalAlignment: Text.AlignHCenter
25 wrapMode: Text.WrapAtWordBoundaryOrAnywhere
26 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.")
27 }
28
29 Item { width: 10; height: 1 } // just a separator
30
31 Item {
32 anchors { left: parent.left; right: parent.right; }
33 height: childrenRect.height
34
35 Label {
36 text: i18n.tr("Use Google Search: ")
37 }
38
39 Switch {
40 anchors.right: parent.right
41 checked: optionsKeeper.useGoogleSearch()
42
43 Component.onCompleted: {
44 if (optionsKeeper.useGoogleSearch() == undefined ) {
45 optionsKeeper.setUseGoogleSearch(true)
46 checked = true
47 }
48 }
49
50 onCheckedChanged: {
51 optionsKeeper.setUseGoogleSearch(checked)
52 }
53 }
54 }
55
56 ListItem.ThinDivider{}
57 ///////////////////////////////////////////////////////////////////// Google RSS engine switch end here
58
59
60 }// Column
61
62}
063
=== modified file 'shorts/qml/shorts-app.qml'
--- shorts/qml/shorts-app.qml 2015-11-27 22:08:54 +0000
+++ shorts/qml/shorts-app.qml 2015-12-15 16:05:21 +0000
@@ -8,6 +8,8 @@
8import "./components"8import "./components"
9import "./utils/databasemodule_v2.js" as DB9import "./utils/databasemodule_v2.js" as DB
1010
11import "./nongoogle"
12
11MainView {13MainView {
12 id: mainView14 id: mainView
1315
@@ -119,7 +121,7 @@
119 objectName: "pageStack"121 objectName: "pageStack"
120122
121 property bool isListView: optionsKeeper.useListMode123 property bool isListView: optionsKeeper.useListMode
122 property var commonHeadActions: [refreshAction, changeModeAction, editTopicsAction, nightModeAction]124 property var commonHeadActions: [refreshAction, changeModeAction, editTopicsAction, nightModeAction, actionSetting]
123125
124 anchors.fill: parent126 anchors.fill: parent
125 focus: true127 focus: true
@@ -231,6 +233,16 @@
231 }233 }
232 }234 }
233235
236 Action {
237 id: actionSetting
238 objectName:"actionSetting"
239 text: i18n.tr("Settings")
240 iconName: "settings"
241 onTriggered: {
242 pageStack.push(Qt.resolvedUrl("./pages/PageSettings.qml"))
243 }
244 }
245
234 /* -------------------------- Pages & Tabs ---------------------------- */246 /* -------------------------- Pages & Tabs ---------------------------- */
235247
236 BottomEdgeTabs {248 BottomEdgeTabs {
@@ -239,7 +251,7 @@
239 objectName: "tabstabs"251 objectName: "tabstabs"
240 visible: false252 visible: false
241253
242 bottomEdgePage: appendFeedPage254 bottomEdgePage: optionsKeeper.useGoogleSearch() ? appendFeedPage : appendNGFeedPage
243 bottomEdgeTitle: i18n.tr("Add feeds")255 bottomEdgeTitle: i18n.tr("Add feeds")
244 bottomEdgeBackgroundColor: "#F5F5F5" // "#875864"256 bottomEdgeBackgroundColor: "#F5F5F5" // "#875864"
245 bottomEdgeTipColor: "#5533b5e5"// "#E0E0E0" //"#9b616c"257 bottomEdgeTipColor: "#5533b5e5"// "#E0E0E0" //"#9b616c"
@@ -379,6 +391,14 @@
379 flickable: null391 flickable: null
380 visible: false392 visible: false
381 }393 }
394
395 AppendNGFeedPage {
396 id: appendNGFeedPage
397
398 title: i18n.tr("Add feeds")
399 flickable: null
400 visible: false
401 }
382 // ******************************** Choose Topic Page ***********************///////////////402 // ******************************** Choose Topic Page ***********************///////////////
383403
384 ChooseTopicPage {404 ChooseTopicPage {
@@ -436,6 +456,11 @@
436 id: optionsKeeper456 id: optionsKeeper
437 }457 }
438458
459 // Positioner to detect current position
460 Positioner {
461 id: positionDetector
462 }
463
439 /* -------------------------- Components ---------------------------- */464 /* -------------------------- Components ---------------------------- */
440465
441 Component {466 Component {
@@ -534,6 +559,35 @@
534 }559 }
535 } // Component560 } // Component
536561
562 //////////////////////////////////////////////////////// a dialog to ask user if she/he wants to turn off the google search
563 Component {
564 id: componentDialogNG
565
566 Dialog {
567 id: dialogNG
568 title: i18n.tr("Warning")
569 text: i18n.tr("Shorts detects that you're located in an area which blocks Google's IP.<br><br>"
570 + "We strongly reconmend you to turn off the Google search funtion."
571 + "Or you can do it in the settings page manually.")
572
573 Button {
574 text: i18n.tr("Yes, please.")
575 color: UbuntuColors.orange
576 objectName: "dialogNGButtonYes"
577 onClicked: {
578 optionsKeeper.setUseGoogleSearch(false)
579 PopupUtils.close(dialogNG)
580 }
581 }
582
583 Button {
584 text: i18n.tr("No, thanks.")
585 objectName: "dialogNGButtonNo"
586 onClicked: PopupUtils.close(dialogNG)
587 }
588 }
589 } // Component
590
537 /* -------------------------- Connections ---------------------------- */591 /* -------------------------- Connections ---------------------------- */
538592
539 Connections {593 Connections {
540594
=== modified file 'shorts/shorts.pro'
--- shorts/shorts.pro 2015-09-16 08:52:25 +0000
+++ shorts/shorts.pro 2015-12-15 16:05:21 +0000
@@ -6,7 +6,8 @@
6QT += qml quick6QT += qml quick
77
8SOURCES += main.cpp \8SOURCES += main.cpp \
9 CachingNetworkManagerFactory.cpp9 CachingNetworkManagerFactory.cpp \
10 xml2json/utilities.cpp
1011
11RESOURCES += shorts.qrc12RESOURCES += shorts.qrc
1213
@@ -41,12 +42,16 @@
41 qml/pages/SwipeDelete.qml \42 qml/pages/SwipeDelete.qml \
42 qml/pages/TopicComponent.qml \43 qml/pages/TopicComponent.qml \
43 qml/pages/TopicManagement.qml \44 qml/pages/TopicManagement.qml \
45 qml/pages/PageSettings.qml \
44 qml/tabs/BaseTab.qml \46 qml/tabs/BaseTab.qml \
45 qml/tabs/SavedTab.qml \47 qml/tabs/SavedTab.qml \
46 qml/tabs/ShortsTab.qml \48 qml/tabs/ShortsTab.qml \
47 qml/tabs/TopicTab.qml \49 qml/tabs/TopicTab.qml \
48 qml/shorts-app.qml \50 qml/shorts-app.qml \
49 qml/content/SharePage.qml51 qml/content/SharePage.qml \
52 qml/nongoogle/AppendNGFeedPage.qml \
53 qml/nongoogle/Positioner.qml \
54 qml/nongoogle/XmlNetwork.qml
5055
51#specify where the config files are installed to56#specify where the config files are installed to
52config_files.path = /.57config_files.path = /.
@@ -59,5 +64,39 @@
59INSTALLS+=target64INSTALLS+=target
6065
61HEADERS += \66HEADERS += \
62 CachingNetworkManagerFactory.h67 CachingNetworkManagerFactory.h \
68 xml2json/utilities.h \
69 xml2json/rapidjson/error/en.h \
70 xml2json/rapidjson/error/error.h \
71 xml2json/rapidjson/internal/biginteger.h \
72 xml2json/rapidjson/internal/diyfp.h \
73 xml2json/rapidjson/internal/dtoa.h \
74 xml2json/rapidjson/internal/ieee754.h \
75 xml2json/rapidjson/internal/itoa.h \
76 xml2json/rapidjson/internal/meta.h \
77 xml2json/rapidjson/internal/pow10.h \
78 xml2json/rapidjson/internal/stack.h \
79 xml2json/rapidjson/internal/strfunc.h \
80 xml2json/rapidjson/internal/strtod.h \
81 xml2json/rapidjson/msinttypes/inttypes.h \
82 xml2json/rapidjson/msinttypes/stdint.h \
83 xml2json/rapidjson/allocators.h \
84 xml2json/rapidjson/document.h \
85 xml2json/rapidjson/encodedstream.h \
86 xml2json/rapidjson/encodings.h \
87 xml2json/rapidjson/filereadstream.h \
88 xml2json/rapidjson/filestream.h \
89 xml2json/rapidjson/filewritestream.h \
90 xml2json/rapidjson/memorybuffer.h \
91 xml2json/rapidjson/memorystream.h \
92 xml2json/rapidjson/prettywriter.h \
93 xml2json/rapidjson/rapidjson.h \
94 xml2json/rapidjson/reader.h \
95 xml2json/rapidjson/stringbuffer.h \
96 xml2json/rapidjson/writer.h \
97 xml2json/rapidxml/rapidxml.hpp \
98 xml2json/rapidxml/rapidxml_iterators.hpp \
99 xml2json/rapidxml/rapidxml_print.hpp \
100 xml2json/rapidxml/rapidxml_utils.hpp \
101 xml2json/xml2json.hpp
63102
64103
=== modified file 'shorts/shorts.qrc'
--- shorts/shorts.qrc 2015-09-16 08:52:25 +0000
+++ shorts/shorts.qrc 2015-12-15 16:05:21 +0000
@@ -32,6 +32,10 @@
32 <file>qml/shorts-app.qml</file>32 <file>qml/shorts-app.qml</file>
33 <file>qml/content/SharePage.qml</file>33 <file>qml/content/SharePage.qml</file>
34 <file>qml/components/DarkModeShader.qml</file>34 <file>qml/components/DarkModeShader.qml</file>
35 <file>qml/nongoogle/XmlNetwork.qml</file>
36 <file>qml/nongoogle/AppendNGFeedPage.qml</file>
37 <file>qml/pages/PageSettings.qml</file>
38 <file>qml/nongoogle/Positioner.qml</file>
35 </qresource>39 </qresource>
36 <qresource prefix="/img">40 <qresource prefix="/img">
37 <file>qml/icons/add.svg</file>41 <file>qml/icons/add.svg</file>
3842
=== added directory 'shorts/xml2json'
=== added directory 'shorts/xml2json/rapidjson'
=== added file 'shorts/xml2json/rapidjson/allocators.h'
--- shorts/xml2json/rapidjson/allocators.h 1970-01-01 00:00:00 +0000
+++ shorts/xml2json/rapidjson/allocators.h 2015-12-15 16:05:21 +0000
@@ -0,0 +1,245 @@
1// Copyright (C) 2011 Milo Yip
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#ifndef RAPIDJSON_ALLOCATORS_H_
22#define RAPIDJSON_ALLOCATORS_H_
23
24#include "rapidjson.h"
25
26RAPIDJSON_NAMESPACE_BEGIN
27
28///////////////////////////////////////////////////////////////////////////////
29// Allocator
30
31/*! \class rapidjson::Allocator
32 \brief Concept for allocating, resizing and freeing memory block.
33
34 Note that Malloc() and Realloc() are non-static but Free() is static.
35
36 So if an allocator need to support Free(), it needs to put its pointer in
37 the header of memory block.
38
39\code
40concept Allocator {
41 static const bool kNeedFree; //!< Whether this allocator needs to call Free().
42
43 // Allocate a memory block.
44 // \param size of the memory block in bytes.
45 // \returns pointer to the memory block.
46 void* Malloc(size_t size);
47
48 // Resize a memory block.
49 // \param originalPtr The pointer to current memory block. Null pointer is permitted.
50 // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
51 // \param newSize the new size in bytes.
52 void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
53
54 // Free a memory block.
55 // \param pointer to the memory block. Null pointer is permitted.
56 static void Free(void *ptr);
57};
58\endcode
59*/
60
61///////////////////////////////////////////////////////////////////////////////
62// CrtAllocator
63
64//! C-runtime library allocator.
65/*! This class is just wrapper for standard C library memory routines.
66 \note implements Allocator concept
67*/
68class CrtAllocator {
69public:
70 static const bool kNeedFree = true;
71 void* Malloc(size_t size) { return std::malloc(size); }
72 void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); }
73 static void Free(void *ptr) { std::free(ptr); }
74};
75
76///////////////////////////////////////////////////////////////////////////////
77// MemoryPoolAllocator
78
79//! Default memory allocator used by the parser and DOM.
80/*! This allocator allocate memory blocks from pre-allocated memory chunks.
81
82 It does not free memory blocks. And Realloc() only allocate new memory.
83
84 The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
85
86 User may also supply a buffer as the first chunk.
87
88 If the user-buffer is full then additional chunks are allocated by BaseAllocator.
89
90 The user-buffer is not deallocated by this allocator.
91
92 \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
93 \note implements Allocator concept
94*/
95template <typename BaseAllocator = CrtAllocator>
96class MemoryPoolAllocator {
97public:
98 static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
99
100 //! Constructor with chunkSize.
101 /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
102 \param baseAllocator The allocator for allocating memory chunks.
103 */
104 MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
105 chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
106 {
107 }
108
109 //! Constructor with user-supplied buffer.
110 /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
111
112 The user buffer will not be deallocated when this allocator is destructed.
113
114 \param buffer User supplied buffer.
115 \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
116 \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
117 \param baseAllocator The allocator for allocating memory chunks.
118 */
119 MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
120 chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
121 {
122 RAPIDJSON_ASSERT(buffer != 0);
123 RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
124 chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
125 chunkHead_->capacity = size - sizeof(ChunkHeader);
126 chunkHead_->size = 0;
127 chunkHead_->next = 0;
128 }
129
130 //! Destructor.
131 /*! This deallocates all memory chunks, excluding the user-supplied buffer.
132 */
133 ~MemoryPoolAllocator() {
134 Clear();
135 RAPIDJSON_DELETE(ownBaseAllocator_);
136 }
137
138 //! Deallocates all memory chunks, excluding the user-supplied buffer.
139 void Clear() {
140 while(chunkHead_ != 0 && chunkHead_ != userBuffer_) {
141 ChunkHeader* next = chunkHead_->next;
142 baseAllocator_->Free(chunkHead_);
143 chunkHead_ = next;
144 }
145 }
146
147 //! Computes the total capacity of allocated memory chunks.
148 /*! \return total capacity in bytes.
149 */
150 size_t Capacity() const {
151 size_t capacity = 0;
152 for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
153 capacity += c->capacity;
154 return capacity;
155 }
156
157 //! Computes the memory blocks allocated.
158 /*! \return total used bytes.
159 */
160 size_t Size() const {
161 size_t size = 0;
162 for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
163 size += c->size;
164 return size;
165 }
166
167 //! Allocates a memory block. (concept Allocator)
168 void* Malloc(size_t size) {
169 size = RAPIDJSON_ALIGN(size);
170 if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
171 AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
172
173 void *buffer = reinterpret_cast<char *>(chunkHead_ + 1) + chunkHead_->size;
174 chunkHead_->size += size;
175 return buffer;
176 }
177
178 //! Resizes a memory block (concept Allocator)
179 void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
180 if (originalPtr == 0)
181 return Malloc(newSize);
182
183 // Do not shrink if new size is smaller than original
184 if (originalSize >= newSize)
185 return originalPtr;
186
187 // Simply expand it if it is the last allocation and there is sufficient space
188 if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) {
189 size_t increment = static_cast<size_t>(newSize - originalSize);
190 increment = RAPIDJSON_ALIGN(increment);
191 if (chunkHead_->size + increment <= chunkHead_->capacity) {
192 chunkHead_->size += increment;
193 return originalPtr;
194 }
195 }
196
197 // Realloc process: allocate and copy memory, do not free original buffer.
198 void* newBuffer = Malloc(newSize);
199 RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
200 return std::memcpy(newBuffer, originalPtr, originalSize);
201 }
202
203 //! Frees a memory block (concept Allocator)
204 static void Free(void *ptr) { (void)ptr; } // Do nothing
205
206private:
207 //! Copy constructor is not permitted.
208 MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
209 //! Copy assignment operator is not permitted.
210 MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
211
212 //! Creates a new chunk.
213 /*! \param capacity Capacity of the chunk in bytes.
214 */
215 void AddChunk(size_t capacity) {
216 if (!baseAllocator_)
217 ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
218 ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity));
219 chunk->capacity = capacity;
220 chunk->size = 0;
221 chunk->next = chunkHead_;
222 chunkHead_ = chunk;
223 }
224
225 static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
226
227 //! Chunk header for perpending to each chunk.
228 /*! Chunks are stored as a singly linked list.
229 */
230 struct ChunkHeader {
231 size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
232 size_t size; //!< Current size of allocated memory in bytes.
233 ChunkHeader *next; //!< Next chunk in the linked list.
234 };
235
236 ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
237 size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
238 void *userBuffer_; //!< User supplied buffer.
239 BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
240 BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
241};
242
243RAPIDJSON_NAMESPACE_END
244
245#endif // RAPIDJSON_ENCODINGS_H_
0246
=== added file 'shorts/xml2json/rapidjson/document.h'
--- shorts/xml2json/rapidjson/document.h 1970-01-01 00:00:00 +0000
+++ shorts/xml2json/rapidjson/document.h 2015-12-15 16:05:21 +0000
@@ -0,0 +1,1969 @@
1// Copyright (C) 2011 Milo Yip
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#ifndef RAPIDJSON_DOCUMENT_H_
22#define RAPIDJSON_DOCUMENT_H_
23
24/*! \file document.h */
25
26#include "reader.h"
27#include "internal/meta.h"
28#include "internal/strfunc.h"
29#include <new> // placement new
30
31#ifdef _MSC_VER
32RAPIDJSON_DIAG_PUSH
33RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
34#elif defined(__GNUC__)
35RAPIDJSON_DIAG_PUSH
36RAPIDJSON_DIAG_OFF(effc++)
37#endif
38
39///////////////////////////////////////////////////////////////////////////////
40// RAPIDJSON_HAS_STDSTRING
41
42#ifndef RAPIDJSON_HAS_STDSTRING
43#ifdef RAPIDJSON_DOXYGEN_RUNNING
44#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
45#else
46#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
47#endif
48/*! \def RAPIDJSON_HAS_STDSTRING
49 \ingroup RAPIDJSON_CONFIG
50 \brief Enable RapidJSON support for \c std::string
51
52 By defining this preprocessor symbol to \c 1, several convenience functions for using
53 \ref rapidjson::GenericValue with \c std::string are enabled, especially
54 for construction and comparison.
55
56 \hideinitializer
57*/
58#include <string>
59#endif // RAPIDJSON_HAS_STDSTRING
60
61#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
62#include <iterator> // std::iterator, std::random_access_iterator_tag
63#endif
64
65#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
66#include <utility> // std::move
67#endif
68
69RAPIDJSON_NAMESPACE_BEGIN
70
71// Forward declaration.
72template <typename Encoding, typename Allocator>
73class GenericValue;
74
75//! Name-value pair in a JSON object value.
76/*!
77 This class was internal to GenericValue. It used to be a inner struct.
78 But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
79 https://code.google.com/p/rapidjson/issues/detail?id=64
80*/
81template <typename Encoding, typename Allocator>
82struct GenericMember {
83 GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
84 GenericValue<Encoding, Allocator> value; //!< value of member.
85};
86
87///////////////////////////////////////////////////////////////////////////////
88// GenericMemberIterator
89
90#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
91
92//! (Constant) member iterator for a JSON object value
93/*!
94 \tparam Const Is this a constant iterator?
95 \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
96 \tparam Allocator Allocator type for allocating memory of object, array and string.
97
98 This class implements a Random Access Iterator for GenericMember elements
99 of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
100
101 \note This iterator implementation is mainly intended to avoid implicit
102 conversions from iterator values to \c NULL,
103 e.g. from GenericValue::FindMember.
104
105 \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
106 pointer-based implementation, if your platform doesn't provide
107 the C++ <iterator> header.
108
109 \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
110 */
111template <bool Const, typename Encoding, typename Allocator>
112class GenericMemberIterator
113 : public std::iterator<std::random_access_iterator_tag
114 , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
115
116 friend class GenericValue<Encoding,Allocator>;
117 template <bool, typename, typename> friend class GenericMemberIterator;
118
119 typedef GenericMember<Encoding,Allocator> PlainType;
120 typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
121 typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
122
123public:
124 //! Iterator type itself
125 typedef GenericMemberIterator Iterator;
126 //! Constant iterator type
127 typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator;
128 //! Non-constant iterator type
129 typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
130
131 //! Pointer to (const) GenericMember
132 typedef typename BaseType::pointer Pointer;
133 //! Reference to (const) GenericMember
134 typedef typename BaseType::reference Reference;
135 //! Signed integer type (e.g. \c ptrdiff_t)
136 typedef typename BaseType::difference_type DifferenceType;
137
138 //! Default constructor (singular value)
139 /*! Creates an iterator pointing to no element.
140 \note All operations, except for comparisons, are undefined on such values.
141 */
142 GenericMemberIterator() : ptr_() {}
143
144 //! Iterator conversions to more const
145 /*!
146 \param it (Non-const) iterator to copy from
147
148 Allows the creation of an iterator from another GenericMemberIterator
149 that is "less const". Especially, creating a non-constant iterator
150 from a constant iterator are disabled:
151 \li const -> non-const (not ok)
152 \li const -> const (ok)
153 \li non-const -> const (ok)
154 \li non-const -> non-const (ok)
155
156 \note If the \c Const template parameter is already \c false, this
157 constructor effectively defines a regular copy-constructor.
158 Otherwise, the copy constructor is implicitly defined.
159 */
160 GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
161
162 //! @name stepping
163 //@{
164 Iterator& operator++(){ ++ptr_; return *this; }
165 Iterator& operator--(){ --ptr_; return *this; }
166 Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
167 Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
168 //@}
169
170 //! @name increment/decrement
171 //@{
172 Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
173 Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
174
175 Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
176 Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
177 //@}
178
179 //! @name relations
180 //@{
181 bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
182 bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
183 bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
184 bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
185 bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
186 bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
187 //@}
188
189 //! @name dereference
190 //@{
191 Reference operator*() const { return *ptr_; }
192 Pointer operator->() const { return ptr_; }
193 Reference operator[](DifferenceType n) const { return ptr_[n]; }
194 //@}
195
196 //! Distance
197 DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
198
199private:
200 //! Internal constructor from plain pointer
201 explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
202
203 Pointer ptr_; //!< raw pointer
204};
205
206#else // RAPIDJSON_NOMEMBERITERATORCLASS
207
208// class-based member iterator implementation disabled, use plain pointers
209
210template <bool Const, typename Encoding, typename Allocator>
211struct GenericMemberIterator;
212
213//! non-const GenericMemberIterator
214template <typename Encoding, typename Allocator>
215struct GenericMemberIterator<false,Encoding,Allocator> {
216 //! use plain pointer as iterator type
217 typedef GenericMember<Encoding,Allocator>* Iterator;
218};
219//! const GenericMemberIterator
220template <typename Encoding, typename Allocator>
221struct GenericMemberIterator<true,Encoding,Allocator> {
222 //! use plain const pointer as iterator type
223 typedef const GenericMember<Encoding,Allocator>* Iterator;
224};
225
226#endif // RAPIDJSON_NOMEMBERITERATORCLASS
227
228///////////////////////////////////////////////////////////////////////////////
229// GenericStringRef
230
231//! Reference to a constant string (not taking a copy)
232/*!
233 \tparam CharType character type of the string
234
235 This helper class is used to automatically infer constant string
236 references for string literals, especially from \c const \b (!)
237 character arrays.
238
239 The main use is for creating JSON string values without copying the
240 source string via an \ref Allocator. This requires that the referenced
241 string pointers have a sufficient lifetime, which exceeds the lifetime
242 of the associated GenericValue.
243
244 \b Example
245 \code
246 Value v("foo"); // ok, no need to copy & calculate length
247 const char foo[] = "foo";
248 v.SetString(foo); // ok
249
250 const char* bar = foo;
251 // Value x(bar); // not ok, can't rely on bar's lifetime
252 Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
253 Value y(StringRef(bar, 3)); // ok, explicitly pass length
254 \endcode
255
256 \see StringRef, GenericValue::SetString
257*/
258template<typename CharType>
259struct GenericStringRef {
260 typedef CharType Ch; //!< character type of the string
261
262 //! Create string reference from \c const character array
263 /*!
264 This constructor implicitly creates a constant string reference from
265 a \c const character array. It has better performance than
266 \ref StringRef(const CharType*) by inferring the string \ref length
267 from the array length, and also supports strings containing null
268 characters.
269
270 \tparam N length of the string, automatically inferred
271
272 \param str Constant character array, lifetime assumed to be longer
273 than the use of the string in e.g. a GenericValue
274
275 \post \ref s == str
276
277 \note Constant complexity.
278 \note There is a hidden, private overload to disallow references to
279 non-const character arrays to be created via this constructor.
280 By this, e.g. function-scope arrays used to be filled via
281 \c snprintf are excluded from consideration.
282 In such cases, the referenced string should be \b copied to the
283 GenericValue instead.
284 */
285 template<SizeType N>
286 GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
287 : s(str), length(N-1) {}
288
289 //! Explicitly create string reference from \c const character pointer
290 /*!
291 This constructor can be used to \b explicitly create a reference to
292 a constant string pointer.
293
294 \see StringRef(const CharType*)
295
296 \param str Constant character pointer, lifetime assumed to be longer
297 than the use of the string in e.g. a GenericValue
298
299 \post \ref s == str
300
301 \note There is a hidden, private overload to disallow references to
302 non-const character arrays to be created via this constructor.
303 By this, e.g. function-scope arrays used to be filled via
304 \c snprintf are excluded from consideration.
305 In such cases, the referenced string should be \b copied to the
306 GenericValue instead.
307 */
308 explicit GenericStringRef(const CharType* str)
309 : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
310
311 //! Create constant string reference from pointer and length
312 /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
313 \param len length of the string, excluding the trailing NULL terminator
314
315 \post \ref s == str && \ref length == len
316 \note Constant complexity.
317 */
318 GenericStringRef(const CharType* str, SizeType len)
319 : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
320
321 //! implicit conversion to plain CharType pointer
322 operator const Ch *() const { return s; }
323
324 const Ch* const s; //!< plain CharType pointer
325 const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
326
327private:
328 //! Disallow copy-assignment
329 GenericStringRef operator=(const GenericStringRef&);
330 //! Disallow construction from non-const array
331 template<SizeType N>
332 GenericStringRef(CharType (&str)[N]) /* = delete */;
333};
334
335//! Mark a character pointer as constant string
336/*! Mark a plain character pointer as a "string literal". This function
337 can be used to avoid copying a character string to be referenced as a
338 value in a JSON GenericValue object, if the string's lifetime is known
339 to be valid long enough.
340 \tparam CharType Character type of the string
341 \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
342 \return GenericStringRef string reference object
343 \relatesalso GenericStringRef
344
345 \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
346*/
347template<typename CharType>
348inline GenericStringRef<CharType> StringRef(const CharType* str) {
349 return GenericStringRef<CharType>(str, internal::StrLen(str));
350}
351
352//! Mark a character pointer as constant string
353/*! Mark a plain character pointer as a "string literal". This function
354 can be used to avoid copying a character string to be referenced as a
355 value in a JSON GenericValue object, if the string's lifetime is known
356 to be valid long enough.
357
358 This version has better performance with supplied length, and also
359 supports string containing null characters.
360
361 \tparam CharType character type of the string
362 \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
363 \param length The length of source string.
364 \return GenericStringRef string reference object
365 \relatesalso GenericStringRef
366*/
367template<typename CharType>
368inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
369 return GenericStringRef<CharType>(str, SizeType(length));
370}
371
372#if RAPIDJSON_HAS_STDSTRING
373//! Mark a string object as constant string
374/*! Mark a string object (e.g. \c std::string) as a "string literal".
375 This function can be used to avoid copying a string to be referenced as a
376 value in a JSON GenericValue object, if the string's lifetime is known
377 to be valid long enough.
378
379 \tparam CharType character type of the string
380 \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
381 \return GenericStringRef string reference object
382 \relatesalso GenericStringRef
383 \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
384*/
385template<typename CharType>
386inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
387 return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
388}
389#endif
390
391///////////////////////////////////////////////////////////////////////////////
392// GenericValue type traits
393namespace internal {
394
395template <typename T, typename Encoding = void, typename Allocator = void>
396struct IsGenericValueImpl : FalseType {};
397
398// select candidates according to nested encoding and allocator types
399template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
400 : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
401
402// helper to match arbitrary GenericValue instantiations, including derived classes
403template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
404
405} // namespace internal
406
407///////////////////////////////////////////////////////////////////////////////
408// GenericValue
409
410//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
411/*!
412 A JSON value can be one of 7 types. This class is a variant type supporting
413 these types.
414
415 Use the Value if UTF8 and default allocator
416
417 \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
418 \tparam Allocator Allocator type for allocating memory of object, array and string.
419*/
420template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
421class GenericValue {
422public:
423 //! Name-value pair in an object.
424 typedef GenericMember<Encoding, Allocator> Member;
425 typedef Encoding EncodingType; //!< Encoding type from template parameter.
426 typedef Allocator AllocatorType; //!< Allocator type from template parameter.
427 typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
428 typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
429 typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
430 typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
431 typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
432 typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
433
434 //!@name Constructors and destructor.
435 //@{
436
437 //! Default constructor creates a null value.
438 GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {}
439
440#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
441 //! Move constructor in C++11
442 GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) {
443 rhs.flags_ = kNullFlag; // give up contents
444 }
445#endif
446
447private:
448 //! Copy constructor is not permitted.
449 GenericValue(const GenericValue& rhs);
450
451public:
452
453 //! Constructor with JSON value type.
454 /*! This creates a Value of specified type with default content.
455 \param type Type of the value.
456 \note Default content for number is zero.
457 */
458 explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
459 static const unsigned defaultFlags[7] = {
460 kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
461 kNumberAnyFlag
462 };
463 RAPIDJSON_ASSERT(type <= kNumberType);
464 flags_ = defaultFlags[type];
465
466 // Use ShortString to store empty string.
467 if (type == kStringType)
468 data_.ss.SetLength(0);
469 }
470
471 //! Explicit copy constructor (with allocator)
472 /*! Creates a copy of a Value by using the given Allocator
473 \tparam SourceAllocator allocator of \c rhs
474 \param rhs Value to copy from (read-only)
475 \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
476 \see CopyFrom()
477 */
478 template< typename SourceAllocator >
479 GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
480
481 //! Constructor for boolean value.
482 /*! \param b Boolean value
483 \note This constructor is limited to \em real boolean values and rejects
484 implicitly converted types like arbitrary pointers. Use an explicit cast
485 to \c bool, if you want to construct a boolean JSON value in such cases.
486 */
487#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
488 template <typename T>
489 explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT
490#else
491 explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
492#endif
493 : data_(), flags_(b ? kTrueFlag : kFalseFlag) {
494 // safe-guard against failing SFINAE
495 RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
496 }
497
498 //! Constructor for int value.
499 explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) {
500 data_.n.i64 = i;
501 if (i >= 0)
502 flags_ |= kUintFlag | kUint64Flag;
503 }
504
505 //! Constructor for unsigned value.
506 explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) {
507 data_.n.u64 = u;
508 if (!(u & 0x80000000))
509 flags_ |= kIntFlag | kInt64Flag;
510 }
511
512 //! Constructor for int64_t value.
513 explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) {
514 data_.n.i64 = i64;
515 if (i64 >= 0) {
516 flags_ |= kNumberUint64Flag;
517 if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
518 flags_ |= kUintFlag;
519 if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
520 flags_ |= kIntFlag;
521 }
522 else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
523 flags_ |= kIntFlag;
524 }
525
526 //! Constructor for uint64_t value.
527 explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
528 data_.n.u64 = u64;
529 if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
530 flags_ |= kInt64Flag;
531 if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
532 flags_ |= kUintFlag;
533 if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
534 flags_ |= kIntFlag;
535 }
536
537 //! Constructor for double value.
538 explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
539
540 //! Constructor for constant string (i.e. do not make a copy of string)
541 GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); }
542
543 //! Constructor for constant string (i.e. do not make a copy of string)
544 explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); }
545
546 //! Constructor for copy-string (i.e. do make a copy of string)
547 GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); }
548
549 //! Constructor for copy-string (i.e. do make a copy of string)
550 GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
551
552#if RAPIDJSON_HAS_STDSTRING
553 //! Constructor for copy-string from a string object (i.e. do make a copy of string)
554 /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
555 */
556 GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
557#endif
558
559 //! Destructor.
560 /*! Need to destruct elements of array, members of object, or copy-string.
561 */
562 ~GenericValue() {
563 if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
564 switch(flags_) {
565 case kArrayFlag:
566 for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
567 v->~GenericValue();
568 Allocator::Free(data_.a.elements);
569 break;
570
571 case kObjectFlag:
572 for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
573 m->~Member();
574 Allocator::Free(data_.o.members);
575 break;
576
577 case kCopyStringFlag:
578 Allocator::Free(const_cast<Ch*>(data_.s.str));
579 break;
580
581 default:
582 break; // Do nothing for other types.
583 }
584 }
585 }
586
587 //@}
588
589 //!@name Assignment operators
590 //@{
591
592 //! Assignment with move semantics.
593 /*! \param rhs Source of the assignment. It will become a null value after assignment.
594 */
595 GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
596 RAPIDJSON_ASSERT(this != &rhs);
597 this->~GenericValue();
598 RawAssign(rhs);
599 return *this;
600 }
601
602#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
603 //! Move assignment in C++11
604 GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
605 return *this = rhs.Move();
606 }
607#endif
608
609 //! Assignment of constant string reference (no copy)
610 /*! \param str Constant string reference to be assigned
611 \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
612 \see GenericStringRef, operator=(T)
613 */
614 GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
615 GenericValue s(str);
616 return *this = s;
617 }
618
619 //! Assignment with primitive types.
620 /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
621 \param value The value to be assigned.
622
623 \note The source type \c T explicitly disallows all pointer types,
624 especially (\c const) \ref Ch*. This helps avoiding implicitly
625 referencing character strings with insufficient lifetime, use
626 \ref SetString(const Ch*, Allocator&) (for copying) or
627 \ref StringRef() (to explicitly mark the pointer as constant) instead.
628 All other pointer types would implicitly convert to \c bool,
629 use \ref SetBool() instead.
630 */
631 template <typename T>
632 RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
633 operator=(T value) {
634 GenericValue v(value);
635 return *this = v;
636 }
637
638 //! Deep-copy assignment from Value
639 /*! Assigns a \b copy of the Value to the current Value object
640 \tparam SourceAllocator Allocator type of \c rhs
641 \param rhs Value to copy from (read-only)
642 \param allocator Allocator to use for copying
643 */
644 template <typename SourceAllocator>
645 GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
646 RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
647 this->~GenericValue();
648 new (this) GenericValue(rhs, allocator);
649 return *this;
650 }
651
652 //! Exchange the contents of this value with those of other.
653 /*!
654 \param other Another value.
655 \note Constant complexity.
656 */
657 GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
658 GenericValue temp;
659 temp.RawAssign(*this);
660 RawAssign(other);
661 other.RawAssign(temp);
662 return *this;
663 }
664
665 //! Prepare Value for move semantics
666 /*! \return *this */
667 GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
668 //@}
669
670 //!@name Equal-to and not-equal-to operators
671 //@{
672 //! Equal-to operator
673 /*!
674 \note If an object contains duplicated named member, comparing equality with any object is always \c false.
675 \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
676 */
677 template <typename SourceAllocator>
678 bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
679 typedef GenericValue<Encoding, SourceAllocator> RhsType;
680 if (GetType() != rhs.GetType())
681 return false;
682
683 switch (GetType()) {
684 case kObjectType: // Warning: O(n^2) inner-loop
685 if (data_.o.size != rhs.data_.o.size)
686 return false;
687 for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
688 typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
689 if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
690 return false;
691 }
692 return true;
693
694 case kArrayType:
695 if (data_.a.size != rhs.data_.a.size)
696 return false;
697 for (SizeType i = 0; i < data_.a.size; i++)
698 if ((*this)[i] != rhs[i])
699 return false;
700 return true;
701
702 case kStringType:
703 return StringEqual(rhs);
704
705 case kNumberType:
706 if (IsDouble() || rhs.IsDouble())
707 return GetDouble() == rhs.GetDouble(); // May convert one operand from integer to double.
708 else
709 return data_.n.u64 == rhs.data_.n.u64;
710
711 default: // kTrueType, kFalseType, kNullType
712 return true;
713 }
714 }
715
716 //! Equal-to operator with const C-string pointer
717 bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
718
719#if RAPIDJSON_HAS_STDSTRING
720 //! Equal-to operator with string object
721 /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
722 */
723 bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
724#endif
725
726 //! Equal-to operator with primitive types
727 /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
728 */
729 template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
730
731 //! Not-equal-to operator
732 /*! \return !(*this == rhs)
733 */
734 template <typename SourceAllocator>
735 bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
736
737 //! Not-equal-to operator with const C-string pointer
738 bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
739
740 //! Not-equal-to operator with arbitrary types
741 /*! \return !(*this == rhs)
742 */
743 template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
744
745 //! Equal-to operator with arbitrary types (symmetric version)
746 /*! \return (rhs == lhs)
747 */
748 template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
749
750 //! Not-Equal-to operator with arbitrary types (symmetric version)
751 /*! \return !(rhs == lhs)
752 */
753 template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
754 //@}
755
756 //!@name Type
757 //@{
758
759 Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); }
760 bool IsNull() const { return flags_ == kNullFlag; }
761 bool IsFalse() const { return flags_ == kFalseFlag; }
762 bool IsTrue() const { return flags_ == kTrueFlag; }
763 bool IsBool() const { return (flags_ & kBoolFlag) != 0; }
764 bool IsObject() const { return flags_ == kObjectFlag; }
765 bool IsArray() const { return flags_ == kArrayFlag; }
766 bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
767 bool IsInt() const { return (flags_ & kIntFlag) != 0; }
768 bool IsUint() const { return (flags_ & kUintFlag) != 0; }
769 bool IsInt64() const { return (flags_ & kInt64Flag) != 0; }
770 bool IsUint64() const { return (flags_ & kUint64Flag) != 0; }
771 bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
772 bool IsString() const { return (flags_ & kStringFlag) != 0; }
773
774 //@}
775
776 //!@name Null
777 //@{
778
779 GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
780
781 //@}
782
783 //!@name Bool
784 //@{
785
786 bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
787 //!< Set boolean value
788 /*! \post IsBool() == true */
789 GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
790
791 //@}
792
793 //!@name Object
794 //@{
795
796 //! Set this value as an empty object.
797 /*! \post IsObject() == true */
798 GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
799
800 //! Get the number of members in the object.
801 SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
802
803 //! Check whether the object is empty.
804 bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
805
806 //! Get a value from an object associated with the name.
807 /*! \pre IsObject() == true
808 \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
809 \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
810 Since 0.2, if the name is not correct, it will assert.
811 If user is unsure whether a member exists, user should use HasMember() first.
812 A better approach is to use FindMember().
813 \note Linear time complexity.
814 */
815 template <typename T>
816 RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
817 GenericValue n(StringRef(name));
818 return (*this)[n];
819 }
820 template <typename T>
821 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]; }
822
823 //! Get a value from an object associated with the name.
824 /*! \pre IsObject() == true
825 \tparam SourceAllocator Allocator of the \c name value
826
827 \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
828 And it can also handle strings with embedded null characters.
829
830 \note Linear time complexity.
831 */
832 template <typename SourceAllocator>
833 GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
834 MemberIterator member = FindMember(name);
835 if (member != MemberEnd())
836 return member->value;
837 else {
838 RAPIDJSON_ASSERT(false); // see above note
839 static GenericValue NullValue;
840 return NullValue;
841 }
842 }
843 template <typename SourceAllocator>
844 const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
845
846 //! Const member iterator
847 /*! \pre IsObject() == true */
848 ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
849 //! Const \em past-the-end member iterator
850 /*! \pre IsObject() == true */
851 ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); }
852 //! Member iterator
853 /*! \pre IsObject() == true */
854 MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); }
855 //! \em Past-the-end member iterator
856 /*! \pre IsObject() == true */
857 MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); }
858
859 //! Check whether a member exists in the object.
860 /*!
861 \param name Member name to be searched.
862 \pre IsObject() == true
863 \return Whether a member with that name exists.
864 \note It is better to use FindMember() directly if you need the obtain the value as well.
865 \note Linear time complexity.
866 */
867 bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
868
869 //! Check whether a member exists in the object with GenericValue name.
870 /*!
871 This version is faster because it does not need a StrLen(). It can also handle string with null character.
872 \param name Member name to be searched.
873 \pre IsObject() == true
874 \return Whether a member with that name exists.
875 \note It is better to use FindMember() directly if you need the obtain the value as well.
876 \note Linear time complexity.
877 */
878 template <typename SourceAllocator>
879 bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
880
881 //! Find member by name.
882 /*!
883 \param name Member name to be searched.
884 \pre IsObject() == true
885 \return Iterator to member, if it exists.
886 Otherwise returns \ref MemberEnd().
887
888 \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
889 the requested member doesn't exist. For consistency with e.g.
890 \c std::map, this has been changed to MemberEnd() now.
891 \note Linear time complexity.
892 */
893 MemberIterator FindMember(const Ch* name) {
894 GenericValue n(StringRef(name));
895 return FindMember(n);
896 }
897
898 ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
899
900 //! Find member by name.
901 /*!
902 This version is faster because it does not need a StrLen(). It can also handle string with null character.
903 \param name Member name to be searched.
904 \pre IsObject() == true
905 \return Iterator to member, if it exists.
906 Otherwise returns \ref MemberEnd().
907
908 \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
909 the requested member doesn't exist. For consistency with e.g.
910 \c std::map, this has been changed to MemberEnd() now.
911 \note Linear time complexity.
912 */
913 template <typename SourceAllocator>
914 MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
915 RAPIDJSON_ASSERT(IsObject());
916 RAPIDJSON_ASSERT(name.IsString());
917 MemberIterator member = MemberBegin();
918 for ( ; member != MemberEnd(); ++member)
919 if (name.StringEqual(member->name))
920 break;
921 return member;
922 }
923 template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
924
925 //! Add a member (name-value pair) to the object.
926 /*! \param name A string value as name of member.
927 \param value Value of any type.
928 \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
929 \return The value itself for fluent API.
930 \note The ownership of \c name and \c value will be transferred to this object on success.
931 \pre IsObject() && name.IsString()
932 \post name.IsNull() && value.IsNull()
933 \note Amortized Constant time complexity.
934 */
935 GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
936 RAPIDJSON_ASSERT(IsObject());
937 RAPIDJSON_ASSERT(name.IsString());
938
939 Object& o = data_.o;
940 if (o.size >= o.capacity) {
941 if (o.capacity == 0) {
942 o.capacity = kDefaultObjectCapacity;
943 o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)));
944 }
945 else {
946 SizeType oldCapacity = o.capacity;
947 o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
948 o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)));
949 }
950 }
951 o.members[o.size].name.RawAssign(name);
952 o.members[o.size].value.RawAssign(value);
953 o.size++;
954 return *this;
955 }
956
957 //! Add a constant string value as member (name-value pair) to the object.
958 /*! \param name A string value as name of member.
959 \param value constant string reference as value of member.
960 \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
961 \return The value itself for fluent API.
962 \pre IsObject()
963 \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
964 \note Amortized Constant time complexity.
965 */
966 GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
967 GenericValue v(value);
968 return AddMember(name, v, allocator);
969 }
970
971 //! Add any primitive value as member (name-value pair) to the object.
972 /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
973 \param name A string value as name of member.
974 \param value Value of primitive type \c T as value of member
975 \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
976 \return The value itself for fluent API.
977 \pre IsObject()
978
979 \note The source type \c T explicitly disallows all pointer types,
980 especially (\c const) \ref Ch*. This helps avoiding implicitly
981 referencing character strings with insufficient lifetime, use
982 \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
983 AddMember(StringRefType, StringRefType, Allocator&).
984 All other pointer types would implicitly convert to \c bool,
985 use an explicit cast instead, if needed.
986 \note Amortized Constant time complexity.
987 */
988 template <typename T>
989 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
990 AddMember(GenericValue& name, T value, Allocator& allocator) {
991 GenericValue v(value);
992 return AddMember(name, v, allocator);
993 }
994
995#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
996 GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
997 return AddMember(name, value, allocator);
998 }
999 GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
1000 return AddMember(name, value, allocator);
1001 }
1002 GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
1003 return AddMember(name, value, allocator);
1004 }
1005 GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
1006 GenericValue n(name);
1007 return AddMember(n, value, allocator);
1008 }
1009#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
1010
1011
1012 //! Add a member (name-value pair) to the object.
1013 /*! \param name A constant string reference as name of member.
1014 \param value Value of any type.
1015 \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
1016 \return The value itself for fluent API.
1017 \note The ownership of \c value will be transferred to this object on success.
1018 \pre IsObject()
1019 \post value.IsNull()
1020 \note Amortized Constant time complexity.
1021 */
1022 GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
1023 GenericValue n(name);
1024 return AddMember(n, value, allocator);
1025 }
1026
1027 //! Add a constant string value as member (name-value pair) to the object.
1028 /*! \param name A constant string reference as name of member.
1029 \param value constant string reference as value of member.
1030 \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
1031 \return The value itself for fluent API.
1032 \pre IsObject()
1033 \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
1034 \note Amortized Constant time complexity.
1035 */
1036 GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
1037 GenericValue v(value);
1038 return AddMember(name, v, allocator);
1039 }
1040
1041 //! Add any primitive value as member (name-value pair) to the object.
1042 /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
1043 \param name A constant string reference as name of member.
1044 \param value Value of primitive type \c T as value of member
1045 \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
1046 \return The value itself for fluent API.
1047 \pre IsObject()
1048
1049 \note The source type \c T explicitly disallows all pointer types,
1050 especially (\c const) \ref Ch*. This helps avoiding implicitly
1051 referencing character strings with insufficient lifetime, use
1052 \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
1053 AddMember(StringRefType, StringRefType, Allocator&).
1054 All other pointer types would implicitly convert to \c bool,
1055 use an explicit cast instead, if needed.
1056 \note Amortized Constant time complexity.
1057 */
1058 template <typename T>
1059 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
1060 AddMember(StringRefType name, T value, Allocator& allocator) {
1061 GenericValue n(name);
1062 return AddMember(n, value, allocator);
1063 }
1064
1065 //! Remove all members in the object.
1066 /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
1067 \note Linear time complexity.
1068 */
1069 void RemoveAllMembers() {
1070 RAPIDJSON_ASSERT(IsObject());
1071 for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
1072 m->~Member();
1073 data_.o.size = 0;
1074 }
1075
1076 //! Remove a member in object by its name.
1077 /*! \param name Name of member to be removed.
1078 \return Whether the member existed.
1079 \note This function may reorder the object members. Use \ref
1080 EraseMember(ConstMemberIterator) if you need to preserve the
1081 relative order of the remaining members.
1082 \note Linear time complexity.
1083 */
1084 bool RemoveMember(const Ch* name) {
1085 GenericValue n(StringRef(name));
1086 return RemoveMember(n);
1087 }
1088
1089 template <typename SourceAllocator>
1090 bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
1091 MemberIterator m = FindMember(name);
1092 if (m != MemberEnd()) {
1093 RemoveMember(m);
1094 return true;
1095 }
1096 else
1097 return false;
1098 }
1099
1100 //! Remove a member in object by iterator.
1101 /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
1102 \return the new iterator after removal.
1103 \note This function may reorder the object members. Use \ref
1104 EraseMember(ConstMemberIterator) if you need to preserve the
1105 relative order of the remaining members.
1106 \note Constant time complexity.
1107 */
1108 MemberIterator RemoveMember(MemberIterator m) {
1109 RAPIDJSON_ASSERT(IsObject());
1110 RAPIDJSON_ASSERT(data_.o.size > 0);
1111 RAPIDJSON_ASSERT(data_.o.members != 0);
1112 RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
1113
1114 MemberIterator last(data_.o.members + (data_.o.size - 1));
1115 if (data_.o.size > 1 && m != last) {
1116 // Move the last one to this place
1117 *m = *last;
1118 }
1119 else {
1120 // Only one left, just destroy
1121 m->~Member();
1122 }
1123 --data_.o.size;
1124 return m;
1125 }
1126
1127 //! Remove a member from an object by iterator.
1128 /*! \param pos iterator to the member to remove
1129 \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
1130 \return Iterator following the removed element.
1131 If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
1132 \note This function preserves the relative order of the remaining object
1133 members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
1134 \note Linear time complexity.
1135 */
1136 MemberIterator EraseMember(ConstMemberIterator pos) {
1137 return EraseMember(pos, pos +1);
1138 }
1139
1140 //! Remove members in the range [first, last) from an object.
1141 /*! \param first iterator to the first member to remove
1142 \param last iterator following the last member to remove
1143 \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
1144 \return Iterator following the last removed element.
1145 \note This function preserves the relative order of the remaining object
1146 members.
1147 \note Linear time complexity.
1148 */
1149 MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
1150 RAPIDJSON_ASSERT(IsObject());
1151 RAPIDJSON_ASSERT(data_.o.size > 0);
1152 RAPIDJSON_ASSERT(data_.o.members != 0);
1153 RAPIDJSON_ASSERT(first >= MemberBegin());
1154 RAPIDJSON_ASSERT(first <= last);
1155 RAPIDJSON_ASSERT(last <= MemberEnd());
1156
1157 MemberIterator pos = MemberBegin() + (first - MemberBegin());
1158 for (MemberIterator itr = pos; itr != last; ++itr)
1159 itr->~Member();
1160 std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member));
1161 data_.o.size -= (last - first);
1162 return pos;
1163 }
1164
1165 //@}
1166
1167 //!@name Array
1168 //@{
1169
1170 //! Set this value as an empty array.
1171 /*! \post IsArray == true */
1172 GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
1173
1174 //! Get the number of elements in array.
1175 SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
1176
1177 //! Get the capacity of array.
1178 SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
1179
1180 //! Check whether the array is empty.
1181 bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
1182
1183 //! Remove all elements in the array.
1184 /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
1185 \note Linear time complexity.
1186 */
1187 void Clear() {
1188 RAPIDJSON_ASSERT(IsArray());
1189 for (SizeType i = 0; i < data_.a.size; ++i)
1190 data_.a.elements[i].~GenericValue();
1191 data_.a.size = 0;
1192 }
1193
1194 //! Get an element from array by index.
1195 /*! \pre IsArray() == true
1196 \param index Zero-based index of element.
1197 \see operator[](T*)
1198 */
1199 GenericValue& operator[](SizeType index) {
1200 RAPIDJSON_ASSERT(IsArray());
1201 RAPIDJSON_ASSERT(index < data_.a.size);
1202 return data_.a.elements[index];
1203 }
1204 const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
1205
1206 //! Element iterator
1207 /*! \pre IsArray() == true */
1208 ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
1209 //! \em Past-the-end element iterator
1210 /*! \pre IsArray() == true */
1211 ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
1212 //! Constant element iterator
1213 /*! \pre IsArray() == true */
1214 ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
1215 //! Constant \em past-the-end element iterator
1216 /*! \pre IsArray() == true */
1217 ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
1218
1219 //! Request the array to have enough capacity to store elements.
1220 /*! \param newCapacity The capacity that the array at least need to have.
1221 \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
1222 \return The value itself for fluent API.
1223 \note Linear time complexity.
1224 */
1225 GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
1226 RAPIDJSON_ASSERT(IsArray());
1227 if (newCapacity > data_.a.capacity) {
1228 data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
1229 data_.a.capacity = newCapacity;
1230 }
1231 return *this;
1232 }
1233
1234 //! Append a GenericValue at the end of the array.
1235 /*! \param value Value to be appended.
1236 \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
1237 \pre IsArray() == true
1238 \post value.IsNull() == true
1239 \return The value itself for fluent API.
1240 \note The ownership of \c value will be transferred to this array on success.
1241 \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
1242 \note Amortized constant time complexity.
1243 */
1244 GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
1245 RAPIDJSON_ASSERT(IsArray());
1246 if (data_.a.size >= data_.a.capacity)
1247 Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
1248 data_.a.elements[data_.a.size++].RawAssign(value);
1249 return *this;
1250 }
1251
1252#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
1253 GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
1254 return PushBack(value, allocator);
1255 }
1256#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
1257
1258 //! Append a constant string reference at the end of the array.
1259 /*! \param value Constant string reference to be appended.
1260 \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
1261 \pre IsArray() == true
1262 \return The value itself for fluent API.
1263 \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
1264 \note Amortized constant time complexity.
1265 \see GenericStringRef
1266 */
1267 GenericValue& PushBack(StringRefType value, Allocator& allocator) {
1268 return (*this).template PushBack<StringRefType>(value, allocator);
1269 }
1270
1271 //! Append a primitive value at the end of the array.
1272 /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
1273 \param value Value of primitive type T to be appended.
1274 \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
1275 \pre IsArray() == true
1276 \return The value itself for fluent API.
1277 \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
1278
1279 \note The source type \c T explicitly disallows all pointer types,
1280 especially (\c const) \ref Ch*. This helps avoiding implicitly
1281 referencing character strings with insufficient lifetime, use
1282 \ref PushBack(GenericValue&, Allocator&) or \ref
1283 PushBack(StringRefType, Allocator&).
1284 All other pointer types would implicitly convert to \c bool,
1285 use an explicit cast instead, if needed.
1286 \note Amortized constant time complexity.
1287 */
1288 template <typename T>
1289 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
1290 PushBack(T value, Allocator& allocator) {
1291 GenericValue v(value);
1292 return PushBack(v, allocator);
1293 }
1294
1295 //! Remove the last element in the array.
1296 /*!
1297 \note Constant time complexity.
1298 */
1299 GenericValue& PopBack() {
1300 RAPIDJSON_ASSERT(IsArray());
1301 RAPIDJSON_ASSERT(!Empty());
1302 data_.a.elements[--data_.a.size].~GenericValue();
1303 return *this;
1304 }
1305
1306 //! Remove an element of array by iterator.
1307 /*!
1308 \param pos iterator to the element to remove
1309 \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
1310 \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
1311 \note Linear time complexity.
1312 */
1313 ValueIterator Erase(ConstValueIterator pos) {
1314 return Erase(pos, pos + 1);
1315 }
1316
1317 //! Remove elements in the range [first, last) of the array.
1318 /*!
1319 \param first iterator to the first element to remove
1320 \param last iterator following the last element to remove
1321 \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
1322 \return Iterator following the last removed element.
1323 \note Linear time complexity.
1324 */
1325 ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
1326 RAPIDJSON_ASSERT(IsArray());
1327 RAPIDJSON_ASSERT(data_.a.size > 0);
1328 RAPIDJSON_ASSERT(data_.a.elements != 0);
1329 RAPIDJSON_ASSERT(first >= Begin());
1330 RAPIDJSON_ASSERT(first <= last);
1331 RAPIDJSON_ASSERT(last <= End());
1332 ValueIterator pos = Begin() + (first - Begin());
1333 for (ValueIterator itr = pos; itr != last; ++itr)
1334 itr->~GenericValue();
1335 std::memmove(pos, last, (End() - last) * sizeof(GenericValue));
1336 data_.a.size -= (last - first);
1337 return pos;
1338 }
1339
1340 //@}
1341
1342 //!@name Number
1343 //@{
1344
1345 int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; }
1346 unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; }
1347 int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
1348 uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
1349
1350 double GetDouble() const {
1351 RAPIDJSON_ASSERT(IsNumber());
1352 if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
1353 if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double
1354 if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
1355 if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision)
1356 RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision)
1357 }
1358
1359 GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
1360 GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
1361 GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
1362 GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
1363 GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
1364
1365 //@}
1366
1367 //!@name String
1368 //@{
1369
1370 const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); }
1371
1372 //! Get the length of string.
1373 /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
1374 */
1375 SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
1376
1377 //! Set this value as a string without copying source string.
1378 /*! This version has better performance with supplied length, and also support string containing null character.
1379 \param s source string pointer.
1380 \param length The length of source string, excluding the trailing null terminator.
1381 \return The value itself for fluent API.
1382 \post IsString() == true && GetString() == s && GetStringLength() == length
1383 \see SetString(StringRefType)
1384 */
1385 GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
1386
1387 //! Set this value as a string without copying source string.
1388 /*! \param s source string reference
1389 \return The value itself for fluent API.
1390 \post IsString() == true && GetString() == s && GetStringLength() == s.length
1391 */
1392 GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
1393
1394 //! Set this value as a string by copying from source string.
1395 /*! This version has better performance with supplied length, and also support string containing null character.
1396 \param s source string.
1397 \param length The length of source string, excluding the trailing null terminator.
1398 \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
1399 \return The value itself for fluent API.
1400 \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
1401 */
1402 GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
1403
1404 //! Set this value as a string by copying from source string.
1405 /*! \param s source string.
1406 \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
1407 \return The value itself for fluent API.
1408 \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
1409 */
1410 GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
1411
1412#if RAPIDJSON_HAS_STDSTRING
1413 //! Set this value as a string by copying from source string.
1414 /*! \param s source string.
1415 \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
1416 \return The value itself for fluent API.
1417 \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
1418 \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
1419 */
1420 GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); }
1421#endif
1422
1423 //@}
1424
1425 //! Generate events of this value to a Handler.
1426 /*! This function adopts the GoF visitor pattern.
1427 Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
1428 It can also be used to deep clone this value via GenericDocument, which is also a Handler.
1429 \tparam Handler type of handler.
1430 \param handler An object implementing concept Handler.
1431 */
1432 template <typename Handler>
1433 bool Accept(Handler& handler) const {
1434 switch(GetType()) {
1435 case kNullType: return handler.Null();
1436 case kFalseType: return handler.Bool(false);
1437 case kTrueType: return handler.Bool(true);
1438
1439 case kObjectType:
1440 if (!handler.StartObject())
1441 return false;
1442 for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
1443 RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
1444 if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0))
1445 return false;
1446 if (!m->value.Accept(handler))
1447 return false;
1448 }
1449 return handler.EndObject(data_.o.size);
1450
1451 case kArrayType:
1452 if (!handler.StartArray())
1453 return false;
1454 for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
1455 if (!v->Accept(handler))
1456 return false;
1457 return handler.EndArray(data_.a.size);
1458
1459 case kStringType:
1460 return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
1461
1462 case kNumberType:
1463 if (IsInt()) return handler.Int(data_.n.i.i);
1464 else if (IsUint()) return handler.Uint(data_.n.u.u);
1465 else if (IsInt64()) return handler.Int64(data_.n.i64);
1466 else if (IsUint64()) return handler.Uint64(data_.n.u64);
1467 else return handler.Double(data_.n.d);
1468
1469 default:
1470 RAPIDJSON_ASSERT(false);
1471 }
1472 return false;
1473 }
1474
1475private:
1476 template <typename, typename> friend class GenericValue;
1477 template <typename, typename, typename> friend class GenericDocument;
1478
1479 enum {
1480 kBoolFlag = 0x100,
1481 kNumberFlag = 0x200,
1482 kIntFlag = 0x400,
1483 kUintFlag = 0x800,
1484 kInt64Flag = 0x1000,
1485 kUint64Flag = 0x2000,
1486 kDoubleFlag = 0x4000,
1487 kStringFlag = 0x100000,
1488 kCopyFlag = 0x200000,
1489 kInlineStrFlag = 0x400000,
1490
1491 // Initial flags of different types.
1492 kNullFlag = kNullType,
1493 kTrueFlag = kTrueType | kBoolFlag,
1494 kFalseFlag = kFalseType | kBoolFlag,
1495 kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
1496 kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
1497 kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
1498 kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
1499 kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
1500 kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
1501 kConstStringFlag = kStringType | kStringFlag,
1502 kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
1503 kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
1504 kObjectFlag = kObjectType,
1505 kArrayFlag = kArrayType,
1506
1507 kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler
1508 };
1509
1510 static const SizeType kDefaultArrayCapacity = 16;
1511 static const SizeType kDefaultObjectCapacity = 16;
1512
1513 struct String {
1514 const Ch* str;
1515 SizeType length;
1516 unsigned hashcode; //!< reserved
1517 }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
1518
1519 // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
1520 // (excluding the terminating zero) and store a value to determine the length of the contained
1521 // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
1522 // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
1523 // the string terminator as well. For getting the string length back from that value just use
1524 // "MaxSize - str[LenPos]".
1525 // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode
1526 // inline (for `UTF8`-encoded strings).
1527 struct ShortString {
1528 enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
1529 Ch str[MaxChars];
1530
1531 inline static bool Usable(SizeType len) { return (MaxSize >= len); }
1532 inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); }
1533 inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); }
1534 }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
1535
1536 // By using proper binary layout, retrieval of different integer types do not need conversions.
1537 union Number {
1538#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
1539 struct I {
1540 int i;
1541 char padding[4];
1542 }i;
1543 struct U {
1544 unsigned u;
1545 char padding2[4];
1546 }u;
1547#else
1548 struct I {
1549 char padding[4];
1550 int i;
1551 }i;
1552 struct U {
1553 char padding2[4];
1554 unsigned u;
1555 }u;
1556#endif
1557 int64_t i64;
1558 uint64_t u64;
1559 double d;
1560 }; // 8 bytes
1561
1562 struct Object {
1563 Member* members;
1564 SizeType size;
1565 SizeType capacity;
1566 }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
1567
1568 struct Array {
1569 GenericValue* elements;
1570 SizeType size;
1571 SizeType capacity;
1572 }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
1573
1574 union Data {
1575 String s;
1576 ShortString ss;
1577 Number n;
1578 Object o;
1579 Array a;
1580 }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
1581
1582 // Initialize this value as array with initial data, without calling destructor.
1583 void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
1584 flags_ = kArrayFlag;
1585 data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
1586 std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
1587 data_.a.size = data_.a.capacity = count;
1588 }
1589
1590 //! Initialize this value as object with initial data, without calling destructor.
1591 void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
1592 flags_ = kObjectFlag;
1593 data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
1594 std::memcpy(data_.o.members, members, count * sizeof(Member));
1595 data_.o.size = data_.o.capacity = count;
1596 }
1597
1598 //! Initialize this value as constant string, without calling destructor.
1599 void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
1600 flags_ = kConstStringFlag;
1601 data_.s.str = s;
1602 data_.s.length = s.length;
1603 }
1604
1605 //! Initialize this value as copy string with initial data, without calling destructor.
1606 void SetStringRaw(StringRefType s, Allocator& allocator) {
1607 Ch* str = NULL;
1608 if(ShortString::Usable(s.length)) {
1609 flags_ = kShortStringFlag;
1610 data_.ss.SetLength(s.length);
1611 str = data_.ss.str;
1612 } else {
1613 flags_ = kCopyStringFlag;
1614 data_.s.length = s.length;
1615 str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
1616 data_.s.str = str;
1617 }
1618 std::memcpy(str, s, s.length * sizeof(Ch));
1619 str[s.length] = '\0';
1620 }
1621
1622 //! Assignment without calling destructor
1623 void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
1624 data_ = rhs.data_;
1625 flags_ = rhs.flags_;
1626 rhs.flags_ = kNullFlag;
1627 }
1628
1629 template <typename SourceAllocator>
1630 bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
1631 RAPIDJSON_ASSERT(IsString());
1632 RAPIDJSON_ASSERT(rhs.IsString());
1633
1634 const SizeType len1 = GetStringLength();
1635 const SizeType len2 = rhs.GetStringLength();
1636 if(len1 != len2) { return false; }
1637
1638 const Ch* const str1 = GetString();
1639 const Ch* const str2 = rhs.GetString();
1640 if(str1 == str2) { return true; } // fast path for constant string
1641
1642 return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
1643 }
1644
1645 Data data_;
1646 unsigned flags_;
1647};
1648
1649//! GenericValue with UTF8 encoding
1650typedef GenericValue<UTF8<> > Value;
1651
1652///////////////////////////////////////////////////////////////////////////////
1653// GenericDocument
1654
1655//! A document for parsing JSON text as DOM.
1656/*!
1657 \note implements Handler concept
1658 \tparam Encoding Encoding for both parsing and string storage.
1659 \tparam Allocator Allocator for allocating memory for the DOM
1660 \tparam StackAllocator Allocator for allocating memory for stack during parsing.
1661 \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.
1662*/
1663template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
1664class GenericDocument : public GenericValue<Encoding, Allocator> {
1665public:
1666 typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
1667 typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
1668 typedef Allocator AllocatorType; //!< Allocator type from template parameter.
1669
1670 //! Constructor
1671 /*! \param allocator Optional allocator for allocating memory.
1672 \param stackCapacity Optional initial capacity of stack in bytes.
1673 \param stackAllocator Optional allocator for allocating memory for stack.
1674 */
1675 GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
1676 allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
1677 {
1678 if (!allocator_)
1679 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
1680 }
1681
1682#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
1683 //! Move constructor in C++11
1684 GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
1685 : ValueType(std::move(rhs)),
1686 allocator_(rhs.allocator_),
1687 ownAllocator_(rhs.ownAllocator_),
1688 stack_(std::move(rhs.stack_)),
1689 parseResult_(rhs.parseResult_)
1690 {
1691 rhs.allocator_ = 0;
1692 rhs.ownAllocator_ = 0;
1693 rhs.parseResult_ = ParseResult();
1694 }
1695#endif
1696
1697 ~GenericDocument() {
1698 Destroy();
1699 }
1700
1701#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
1702 //! Move assignment in C++11
1703 GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
1704 {
1705 // The cast to ValueType is necessary here, because otherwise it would
1706 // attempt to call GenericValue's templated assignment operator.
1707 ValueType::operator=(std::forward<ValueType>(rhs));
1708
1709 // Calling the destructor here would prematurely call stack_'s destructor
1710 Destroy();
1711
1712 allocator_ = rhs.allocator_;
1713 ownAllocator_ = rhs.ownAllocator_;
1714 stack_ = std::move(rhs.stack_);
1715 parseResult_ = rhs.parseResult_;
1716
1717 rhs.allocator_ = 0;
1718 rhs.ownAllocator_ = 0;
1719 rhs.parseResult_ = ParseResult();
1720
1721 return *this;
1722 }
1723#endif
1724
1725 //!@name Parse from stream
1726 //!@{
1727
1728 //! Parse JSON text from an input stream (with Encoding conversion)
1729 /*! \tparam parseFlags Combination of \ref ParseFlag.
1730 \tparam SourceEncoding Encoding of input stream
1731 \tparam InputStream Type of input stream, implementing Stream concept
1732 \param is Input stream to be parsed.
1733 \return The document itself for fluent API.
1734 */
1735 template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
1736 GenericDocument& ParseStream(InputStream& is) {
1737 ValueType::SetNull(); // Remove existing root if exist
1738 GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
1739 ClearStackOnExit scope(*this);
1740 parseResult_ = reader.template Parse<parseFlags>(is, *this);
1741 if (parseResult_) {
1742 RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
1743 this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
1744 }
1745 return *this;
1746 }
1747
1748 //! Parse JSON text from an input stream
1749 /*! \tparam parseFlags Combination of \ref ParseFlag.
1750 \tparam InputStream Type of input stream, implementing Stream concept
1751 \param is Input stream to be parsed.
1752 \return The document itself for fluent API.
1753 */
1754 template <unsigned parseFlags, typename InputStream>
1755 GenericDocument& ParseStream(InputStream& is) {
1756 return ParseStream<parseFlags,Encoding,InputStream>(is);
1757 }
1758
1759 //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
1760 /*! \tparam InputStream Type of input stream, implementing Stream concept
1761 \param is Input stream to be parsed.
1762 \return The document itself for fluent API.
1763 */
1764 template <typename InputStream>
1765 GenericDocument& ParseStream(InputStream& is) {
1766 return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
1767 }
1768 //!@}
1769
1770 //!@name Parse in-place from mutable string
1771 //!@{
1772
1773 //! Parse JSON text from a mutable string (with Encoding conversion)
1774 /*! \tparam parseFlags Combination of \ref ParseFlag.
1775 \tparam SourceEncoding Transcoding from input Encoding
1776 \param str Mutable zero-terminated string to be parsed.
1777 \return The document itself for fluent API.
1778 */
1779 template <unsigned parseFlags, typename SourceEncoding>
1780 GenericDocument& ParseInsitu(Ch* str) {
1781 GenericInsituStringStream<Encoding> s(str);
1782 return ParseStream<parseFlags | kParseInsituFlag, SourceEncoding>(s);
1783 }
1784
1785 //! Parse JSON text from a mutable string
1786 /*! \tparam parseFlags Combination of \ref ParseFlag.
1787 \param str Mutable zero-terminated string to be parsed.
1788 \return The document itself for fluent API.
1789 */
1790 template <unsigned parseFlags>
1791 GenericDocument& ParseInsitu(Ch* str) {
1792 return ParseInsitu<parseFlags, Encoding>(str);
1793 }
1794
1795 //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
1796 /*! \param str Mutable zero-terminated string to be parsed.
1797 \return The document itself for fluent API.
1798 */
1799 GenericDocument& ParseInsitu(Ch* str) {
1800 return ParseInsitu<kParseDefaultFlags, Encoding>(str);
1801 }
1802 //!@}
1803
1804 //!@name Parse from read-only string
1805 //!@{
1806
1807 //! Parse JSON text from a read-only string (with Encoding conversion)
1808 /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
1809 \tparam SourceEncoding Transcoding from input Encoding
1810 \param str Read-only zero-terminated string to be parsed.
1811 */
1812 template <unsigned parseFlags, typename SourceEncoding>
1813 GenericDocument& Parse(const Ch* str) {
1814 RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
1815 GenericStringStream<SourceEncoding> s(str);
1816 return ParseStream<parseFlags, SourceEncoding>(s);
1817 }
1818
1819 //! Parse JSON text from a read-only string
1820 /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
1821 \param str Read-only zero-terminated string to be parsed.
1822 */
1823 template <unsigned parseFlags>
1824 GenericDocument& Parse(const Ch* str) {
1825 return Parse<parseFlags, Encoding>(str);
1826 }
1827
1828 //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
1829 /*! \param str Read-only zero-terminated string to be parsed.
1830 */
1831 GenericDocument& Parse(const Ch* str) {
1832 return Parse<kParseDefaultFlags>(str);
1833 }
1834 //!@}
1835
1836 //!@name Handling parse errors
1837 //!@{
1838
1839 //! Whether a parse error has occured in the last parsing.
1840 bool HasParseError() const { return parseResult_.IsError(); }
1841
1842 //! Get the \ref ParseErrorCode of last parsing.
1843 ParseErrorCode GetParseError() const { return parseResult_.Code(); }
1844
1845 //! Get the position of last parsing error in input, 0 otherwise.
1846 size_t GetErrorOffset() const { return parseResult_.Offset(); }
1847
1848 //!@}
1849
1850 //! Get the allocator of this document.
1851 Allocator& GetAllocator() { return *allocator_; }
1852
1853 //! Get the capacity of stack in bytes.
1854 size_t GetStackCapacity() const { return stack_.GetCapacity(); }
1855
1856private:
1857 // clear stack on any exit from ParseStream, e.g. due to exception
1858 struct ClearStackOnExit {
1859 explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
1860 ~ClearStackOnExit() { d_.ClearStack(); }
1861 private:
1862 ClearStackOnExit(const ClearStackOnExit&);
1863 ClearStackOnExit& operator=(const ClearStackOnExit&);
1864 GenericDocument& d_;
1865 };
1866
1867 // callers of the following private Handler functions
1868 template <typename,typename,typename> friend class GenericReader; // for parsing
1869 template <typename, typename> friend class GenericValue; // for deep copying
1870
1871 // Implementation of Handler
1872 bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
1873 bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
1874 bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
1875 bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
1876 bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
1877 bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
1878 bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
1879
1880 bool String(const Ch* str, SizeType length, bool copy) {
1881 if (copy)
1882 new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
1883 else
1884 new (stack_.template Push<ValueType>()) ValueType(str, length);
1885 return true;
1886 }
1887
1888 bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
1889
1890 bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
1891
1892 bool EndObject(SizeType memberCount) {
1893 typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
1894 stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
1895 return true;
1896 }
1897
1898 bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
1899
1900 bool EndArray(SizeType elementCount) {
1901 ValueType* elements = stack_.template Pop<ValueType>(elementCount);
1902 stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
1903 return true;
1904 }
1905
1906private:
1907 //! Prohibit copying
1908 GenericDocument(const GenericDocument&);
1909 //! Prohibit assignment
1910 GenericDocument& operator=(const GenericDocument&);
1911
1912 void ClearStack() {
1913 if (Allocator::kNeedFree)
1914 while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
1915 (stack_.template Pop<ValueType>(1))->~ValueType();
1916 else
1917 stack_.Clear();
1918 stack_.ShrinkToFit();
1919 }
1920
1921 void Destroy() {
1922 RAPIDJSON_DELETE(ownAllocator_);
1923 }
1924
1925 static const size_t kDefaultStackCapacity = 1024;
1926 Allocator* allocator_;
1927 Allocator* ownAllocator_;
1928 internal::Stack<StackAllocator> stack_;
1929 ParseResult parseResult_;
1930};
1931
1932//! GenericDocument with UTF8 encoding
1933typedef GenericDocument<UTF8<> > Document;
1934
1935// defined here due to the dependency on GenericDocument
1936template <typename Encoding, typename Allocator>
1937template <typename SourceAllocator>
1938inline
1939GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
1940{
1941 switch (rhs.GetType()) {
1942 case kObjectType:
1943 case kArrayType: { // perform deep copy via SAX Handler
1944 GenericDocument<Encoding,Allocator> d(&allocator);
1945 rhs.Accept(d);
1946 RawAssign(*d.stack_.template Pop<GenericValue>(1));
1947 }
1948 break;
1949 case kStringType:
1950 if (rhs.flags_ == kConstStringFlag) {
1951 flags_ = rhs.flags_;
1952 data_ = *reinterpret_cast<const Data*>(&rhs.data_);
1953 } else {
1954 SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
1955 }
1956 break;
1957 default: // kNumberType, kTrueType, kFalseType, kNullType
1958 flags_ = rhs.flags_;
1959 data_ = *reinterpret_cast<const Data*>(&rhs.data_);
1960 }
1961}
1962
1963RAPIDJSON_NAMESPACE_END
1964
1965#if defined(_MSC_VER) || defined(__GNUC__)
1966RAPIDJSON_DIAG_POP
1967#endif
1968
1969#endif // RAPIDJSON_DOCUMENT_H_
01970
=== added file 'shorts/xml2json/rapidjson/encodedstream.h'
--- shorts/xml2json/rapidjson/encodedstream.h 1970-01-01 00:00:00 +0000
+++ shorts/xml2json/rapidjson/encodedstream.h 2015-12-15 16:05:21 +0000
@@ -0,0 +1,290 @@
1// Copyright (C) 2011 Milo Yip
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#ifndef RAPIDJSON_ENCODEDSTREAM_H_
22#define RAPIDJSON_ENCODEDSTREAM_H_
23
24#include "rapidjson.h"
25
26#ifdef __GNUC__
27RAPIDJSON_DIAG_PUSH
28RAPIDJSON_DIAG_OFF(effc++)
29#endif
30
31RAPIDJSON_NAMESPACE_BEGIN
32
33//! Input byte stream wrapper with a statically bound encoding.
34/*!
35 \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
36 \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
37*/
38template <typename Encoding, typename InputByteStream>
39class EncodedInputStream {
40 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
41public:
42 typedef typename Encoding::Ch Ch;
43
44 EncodedInputStream(InputByteStream& is) : is_(is) {
45 current_ = Encoding::TakeBOM(is_);
46 }
47
48 Ch Peek() const { return current_; }
49 Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
50 size_t Tell() const { return is_.Tell(); }
51
52 // Not implemented
53 void Put(Ch) { RAPIDJSON_ASSERT(false); }
54 void Flush() { RAPIDJSON_ASSERT(false); }
55 Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
56 size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
57
58private:
59 EncodedInputStream(const EncodedInputStream&);
60 EncodedInputStream& operator=(const EncodedInputStream&);
61
62 InputByteStream& is_;
63 Ch current_;
64};
65
66//! Output byte stream wrapper with statically bound encoding.
67/*!
68 \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
69 \tparam InputByteStream Type of input byte stream. For example, FileWriteStream.
70*/
71template <typename Encoding, typename OutputByteStream>
72class EncodedOutputStream {
73 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
74public:
75 typedef typename Encoding::Ch Ch;
76
77 EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
78 if (putBOM)
79 Encoding::PutBOM(os_);
80 }
81
82 void Put(Ch c) { Encoding::Put(os_, c); }
83 void Flush() { os_.Flush(); }
84
85 // Not implemented
86 Ch Peek() const { RAPIDJSON_ASSERT(false); }
87 Ch Take() { RAPIDJSON_ASSERT(false); }
88 size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
89 Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
90 size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
91
92private:
93 EncodedOutputStream(const EncodedOutputStream&);
94 EncodedOutputStream& operator=(const EncodedOutputStream&);
95
96 OutputByteStream& os_;
97};
98
99#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
100
101//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
102/*!
103 \tparam CharType Type of character for reading.
104 \tparam InputByteStream type of input byte stream to be wrapped.
105*/
106template <typename CharType, typename InputByteStream>
107class AutoUTFInputStream {
108 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
109public:
110 typedef CharType Ch;
111
112 //! Constructor.
113 /*!
114 \param is input stream to be wrapped.
115 \param type UTF encoding type if it is not detected from the stream.
116 */
117 AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
118 DetectType();
119 static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
120 takeFunc_ = f[type_];
121 current_ = takeFunc_(*is_);
122 }
123
124 UTFType GetType() const { return type_; }
125 bool HasBOM() const { return hasBOM_; }
126
127 Ch Peek() const { return current_; }
128 Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
129 size_t Tell() const { return is_->Tell(); }
130
131 // Not implemented
132 void Put(Ch) { RAPIDJSON_ASSERT(false); }
133 void Flush() { RAPIDJSON_ASSERT(false); }
134 Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
135 size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
136
137private:
138 AutoUTFInputStream(const AutoUTFInputStream&);
139 AutoUTFInputStream& operator=(const AutoUTFInputStream&);
140
141 // Detect encoding type with BOM or RFC 4627
142 void DetectType() {
143 // BOM (Byte Order Mark):
144 // 00 00 FE FF UTF-32BE
145 // FF FE 00 00 UTF-32LE
146 // FE FF UTF-16BE
147 // FF FE UTF-16LE
148 // EF BB BF UTF-8
149
150 const unsigned char* c = (const unsigned char *)is_->Peek4();
151 if (!c)
152 return;
153
154 unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
155 hasBOM_ = false;
156 if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
157 else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
158 else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
159 else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
160 else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
161
162 // RFC 4627: Section 3
163 // "Since the first two characters of a JSON text will always be ASCII
164 // characters [RFC0020], it is possible to determine whether an octet
165 // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
166 // at the pattern of nulls in the first four octets."
167 // 00 00 00 xx UTF-32BE
168 // 00 xx 00 xx UTF-16BE
169 // xx 00 00 00 UTF-32LE
170 // xx 00 xx 00 UTF-16LE
171 // xx xx xx xx UTF-8
172
173 if (!hasBOM_) {
174 unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
175 switch (pattern) {
176 case 0x08: type_ = kUTF32BE; break;
177 case 0x0A: type_ = kUTF16BE; break;
178 case 0x01: type_ = kUTF32LE; break;
179 case 0x05: type_ = kUTF16LE; break;
180 case 0x0F: type_ = kUTF8; break;
181 default: break; // Use type defined by user.
182 }
183 }
184
185 // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
186 switch (type_) {
187 case kUTF8:
188 // Do nothing
189 break;
190 case kUTF16LE:
191 case kUTF16BE:
192 RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
193 break;
194 case kUTF32LE:
195 case kUTF32BE:
196 RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
197 break;
198 default:
199 RAPIDJSON_ASSERT(false); // Invalid type
200 }
201 }
202
203 typedef Ch (*TakeFunc)(InputByteStream& is);
204 InputByteStream* is_;
205 UTFType type_;
206 Ch current_;
207 TakeFunc takeFunc_;
208 bool hasBOM_;
209};
210
211//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
212/*!
213 \tparam CharType Type of character for writing.
214 \tparam InputByteStream type of output byte stream to be wrapped.
215*/
216template <typename CharType, typename OutputByteStream>
217class AutoUTFOutputStream {
218 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
219public:
220 typedef CharType Ch;
221
222 //! Constructor.
223 /*!
224 \param os output stream to be wrapped.
225 \param type UTF encoding type.
226 \param putBOM Whether to write BOM at the beginning of the stream.
227 */
228 AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
229 // RUntime check whether the size of character type is sufficient. It only perform checks with assertion.
230 switch (type_) {
231 case kUTF16LE:
232 case kUTF16BE:
233 RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
234 break;
235 case kUTF32LE:
236 case kUTF32BE:
237 RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
238 break;
239 case kUTF8:
240 // Do nothing
241 break;
242 default:
243 RAPIDJSON_ASSERT(false); // Invalid UTFType
244 }
245
246 static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
247 putFunc_ = f[type_];
248
249 if (putBOM)
250 PutBOM();
251 }
252
253 UTFType GetType() const { return type_; }
254
255 void Put(Ch c) { putFunc_(*os_, c); }
256 void Flush() { os_->Flush(); }
257
258 // Not implemented
259 Ch Peek() const { RAPIDJSON_ASSERT(false); }
260 Ch Take() { RAPIDJSON_ASSERT(false); }
261 size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
262 Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
263 size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
264
265private:
266 AutoUTFOutputStream(const AutoUTFOutputStream&);
267 AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
268
269 void PutBOM() {
270 typedef void (*PutBOMFunc)(OutputByteStream&);
271 static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
272 f[type_](*os_);
273 }
274
275 typedef void (*PutFunc)(OutputByteStream&, Ch);
276
277 OutputByteStream* os_;
278 UTFType type_;
279 PutFunc putFunc_;
280};
281
282#undef RAPIDJSON_ENCODINGS_FUNC
283
284RAPIDJSON_NAMESPACE_END
285
286#ifdef __GNUC__
287RAPIDJSON_DIAG_POP
288#endif
289
290#endif // RAPIDJSON_FILESTREAM_H_
0291
=== added file 'shorts/xml2json/rapidjson/encodings.h'
--- shorts/xml2json/rapidjson/encodings.h 1970-01-01 00:00:00 +0000
+++ shorts/xml2json/rapidjson/encodings.h 2015-12-15 16:05:21 +0000
@@ -0,0 +1,630 @@
1// Copyright (C) 2011 Milo Yip
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#ifndef RAPIDJSON_ENCODINGS_H_
22#define RAPIDJSON_ENCODINGS_H_
23
24#include "rapidjson.h"
25
26#ifdef _MSC_VER
27RAPIDJSON_DIAG_PUSH
28RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
29RAPIDJSON_DIAG_OFF(4702) // unreachable code
30#elif defined(__GNUC__)
31RAPIDJSON_DIAG_PUSH
32RAPIDJSON_DIAG_OFF(effc++)
33#endif
34
35RAPIDJSON_NAMESPACE_BEGIN
36
37///////////////////////////////////////////////////////////////////////////////
38// Encoding
39
40/*! \class rapidjson::Encoding
41 \brief Concept for encoding of Unicode characters.
42
43\code
44concept Encoding {
45 typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
46
47 enum { supportUnicode = 1 }; // or 0 if not supporting unicode
48
49 //! \brief Encode a Unicode codepoint to an output stream.
50 //! \param os Output stream.
51 //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
52 template<typename OutputStream>
53 static void Encode(OutputStream& os, unsigned codepoint);
54
55 //! \brief Decode a Unicode codepoint from an input stream.
56 //! \param is Input stream.
57 //! \param codepoint Output of the unicode codepoint.
58 //! \return true if a valid codepoint can be decoded from the stream.
59 template <typename InputStream>
60 static bool Decode(InputStream& is, unsigned* codepoint);
61
62 //! \brief Validate one Unicode codepoint from an encoded stream.
63 //! \param is Input stream to obtain codepoint.
64 //! \param os Output for copying one codepoint.
65 //! \return true if it is valid.
66 //! \note This function just validating and copying the codepoint without actually decode it.
67 template <typename InputStream, typename OutputStream>
68 static bool Validate(InputStream& is, OutputStream& os);
69
70 // The following functions are deal with byte streams.
71
72 //! Take a character from input byte stream, skip BOM if exist.
73 template <typename InputByteStream>
74 static CharType TakeBOM(InputByteStream& is);
75
76 //! Take a character from input byte stream.
77 template <typename InputByteStream>
78 static Ch Take(InputByteStream& is);
79
80 //! Put BOM to output byte stream.
81 template <typename OutputByteStream>
82 static void PutBOM(OutputByteStream& os);
83
84 //! Put a character to output byte stream.
85 template <typename OutputByteStream>
86 static void Put(OutputByteStream& os, Ch c);
87};
88\endcode
89*/
90
91///////////////////////////////////////////////////////////////////////////////
92// UTF8
93
94//! UTF-8 encoding.
95/*! http://en.wikipedia.org/wiki/UTF-8
96 http://tools.ietf.org/html/rfc3629
97 \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
98 \note implements Encoding concept
99*/
100template<typename CharType = char>
101struct UTF8 {
102 typedef CharType Ch;
103
104 enum { supportUnicode = 1 };
105
106 template<typename OutputStream>
107 static void Encode(OutputStream& os, unsigned codepoint) {
108 if (codepoint <= 0x7F)
109 os.Put(static_cast<Ch>(codepoint & 0xFF));
110 else if (codepoint <= 0x7FF) {
111 os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
112 os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
113 }
114 else if (codepoint <= 0xFFFF) {
115 os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
116 os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
117 os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
118 }
119 else {
120 RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
121 os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
122 os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
123 os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
124 os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
125 }
126 }
127
128 template <typename InputStream>
129 static bool Decode(InputStream& is, unsigned* codepoint) {
130#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu)
131#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
132#define TAIL() COPY(); TRANS(0x70)
133 Ch c = is.Take();
134 if (!(c & 0x80)) {
135 *codepoint = (unsigned char)c;
136 return true;
137 }
138
139 unsigned char type = GetRange((unsigned char)c);
140 *codepoint = (0xFF >> type) & (unsigned char)c;
141 bool result = true;
142 switch (type) {
143 case 2: TAIL(); return result;
144 case 3: TAIL(); TAIL(); return result;
145 case 4: COPY(); TRANS(0x50); TAIL(); return result;
146 case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
147 case 6: TAIL(); TAIL(); TAIL(); return result;
148 case 10: COPY(); TRANS(0x20); TAIL(); return result;
149 case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
150 default: return false;
151 }
152#undef COPY
153#undef TRANS
154#undef TAIL
155 }
156
157 template <typename InputStream, typename OutputStream>
158 static bool Validate(InputStream& is, OutputStream& os) {
159#define COPY() os.Put(c = is.Take())
160#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
161#define TAIL() COPY(); TRANS(0x70)
162 Ch c;
163 COPY();
164 if (!(c & 0x80))
165 return true;
166
167 bool result = true;
168 switch (GetRange((unsigned char)c)) {
169 case 2: TAIL(); return result;
170 case 3: TAIL(); TAIL(); return result;
171 case 4: COPY(); TRANS(0x50); TAIL(); return result;
172 case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
173 case 6: TAIL(); TAIL(); TAIL(); return result;
174 case 10: COPY(); TRANS(0x20); TAIL(); return result;
175 case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
176 default: return false;
177 }
178#undef COPY
179#undef TRANS
180#undef TAIL
181 }
182
183 static unsigned char GetRange(unsigned char c) {
184 // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
185 // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
186 static const unsigned char type[] = {
187 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,
188 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,
189 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,
190 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,
191 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
192 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
193 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
194 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
195 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,
196 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,
197 };
198 return type[c];
199 }
200
201 template <typename InputByteStream>
202 static CharType TakeBOM(InputByteStream& is) {
203 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
204 Ch c = Take(is);
205 if ((unsigned char)c != 0xEFu) return c;
206 c = is.Take();
207 if ((unsigned char)c != 0xBBu) return c;
208 c = is.Take();
209 if ((unsigned char)c != 0xBFu) return c;
210 c = is.Take();
211 return c;
212 }
213
214 template <typename InputByteStream>
215 static Ch Take(InputByteStream& is) {
216 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
217 return is.Take();
218 }
219
220 template <typename OutputByteStream>
221 static void PutBOM(OutputByteStream& os) {
222 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
223 os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu);
224 }
225
226 template <typename OutputByteStream>
227 static void Put(OutputByteStream& os, Ch c) {
228 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
229 os.Put(static_cast<typename OutputByteStream::Ch>(c));
230 }
231};
232
233///////////////////////////////////////////////////////////////////////////////
234// UTF16
235
236//! UTF-16 encoding.
237/*! http://en.wikipedia.org/wiki/UTF-16
238 http://tools.ietf.org/html/rfc2781
239 \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
240 \note implements Encoding concept
241
242 \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
243 For streaming, use UTF16LE and UTF16BE, which handle endianness.
244*/
245template<typename CharType = wchar_t>
246struct UTF16 {
247 typedef CharType Ch;
248 RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
249
250 enum { supportUnicode = 1 };
251
252 template<typename OutputStream>
253 static void Encode(OutputStream& os, unsigned codepoint) {
254 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
255 if (codepoint <= 0xFFFF) {
256 RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
257 os.Put(static_cast<typename OutputStream::Ch>(codepoint));
258 }
259 else {
260 RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
261 unsigned v = codepoint - 0x10000;
262 os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
263 os.Put((v & 0x3FF) | 0xDC00);
264 }
265 }
266
267 template <typename InputStream>
268 static bool Decode(InputStream& is, unsigned* codepoint) {
269 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
270 Ch c = is.Take();
271 if (c < 0xD800 || c > 0xDFFF) {
272 *codepoint = c;
273 return true;
274 }
275 else if (c <= 0xDBFF) {
276 *codepoint = (c & 0x3FF) << 10;
277 c = is.Take();
278 *codepoint |= (c & 0x3FF);
279 *codepoint += 0x10000;
280 return c >= 0xDC00 && c <= 0xDFFF;
281 }
282 return false;
283 }
284
285 template <typename InputStream, typename OutputStream>
286 static bool Validate(InputStream& is, OutputStream& os) {
287 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
288 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
289 Ch c;
290 os.Put(c = is.Take());
291 if (c < 0xD800 || c > 0xDFFF)
292 return true;
293 else if (c <= 0xDBFF) {
294 os.Put(c = is.Take());
295 return c >= 0xDC00 && c <= 0xDFFF;
296 }
297 return false;
298 }
299};
300
301//! UTF-16 little endian encoding.
302template<typename CharType = wchar_t>
303struct UTF16LE : UTF16<CharType> {
304 template <typename InputByteStream>
305 static CharType TakeBOM(InputByteStream& is) {
306 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
307 CharType c = Take(is);
308 return (unsigned short)c == 0xFEFFu ? Take(is) : c;
309 }
310
311 template <typename InputByteStream>
312 static CharType Take(InputByteStream& is) {
313 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
314 CharType c = (unsigned char)is.Take();
315 c |= (unsigned char)is.Take() << 8;
316 return c;
317 }
318
319 template <typename OutputByteStream>
320 static void PutBOM(OutputByteStream& os) {
321 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
322 os.Put(0xFFu); os.Put(0xFEu);
323 }
324
325 template <typename OutputByteStream>
326 static void Put(OutputByteStream& os, CharType c) {
327 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
328 os.Put(c & 0xFFu);
329 os.Put((c >> 8) & 0xFFu);
330 }
331};
332
333//! UTF-16 big endian encoding.
334template<typename CharType = wchar_t>
335struct UTF16BE : UTF16<CharType> {
336 template <typename InputByteStream>
337 static CharType TakeBOM(InputByteStream& is) {
338 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
339 CharType c = Take(is);
340 return (unsigned short)c == 0xFEFFu ? Take(is) : c;
341 }
342
343 template <typename InputByteStream>
344 static CharType Take(InputByteStream& is) {
345 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
346 CharType c = (unsigned char)is.Take() << 8;
347 c |= (unsigned char)is.Take();
348 return c;
349 }
350
351 template <typename OutputByteStream>
352 static void PutBOM(OutputByteStream& os) {
353 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
354 os.Put(0xFEu); os.Put(0xFFu);
355 }
356
357 template <typename OutputByteStream>
358 static void Put(OutputByteStream& os, CharType c) {
359 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
360 os.Put((c >> 8) & 0xFFu);
361 os.Put(c & 0xFFu);
362 }
363};
364
365///////////////////////////////////////////////////////////////////////////////
366// UTF32
367
368//! UTF-32 encoding.
369/*! http://en.wikipedia.org/wiki/UTF-32
370 \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
371 \note implements Encoding concept
372
373 \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
374 For streaming, use UTF32LE and UTF32BE, which handle endianness.
375*/
376template<typename CharType = unsigned>
377struct UTF32 {
378 typedef CharType Ch;
379 RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
380
381 enum { supportUnicode = 1 };
382
383 template<typename OutputStream>
384 static void Encode(OutputStream& os, unsigned codepoint) {
385 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
386 RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
387 os.Put(codepoint);
388 }
389
390 template <typename InputStream>
391 static bool Decode(InputStream& is, unsigned* codepoint) {
392 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
393 Ch c = is.Take();
394 *codepoint = c;
395 return c <= 0x10FFFF;
396 }
397
398 template <typename InputStream, typename OutputStream>
399 static bool Validate(InputStream& is, OutputStream& os) {
400 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
401 Ch c;
402 os.Put(c = is.Take());
403 return c <= 0x10FFFF;
404 }
405};
406
407//! UTF-32 little endian enocoding.
408template<typename CharType = unsigned>
409struct UTF32LE : UTF32<CharType> {
410 template <typename InputByteStream>
411 static CharType TakeBOM(InputByteStream& is) {
412 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
413 CharType c = Take(is);
414 return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
415 }
416
417 template <typename InputByteStream>
418 static CharType Take(InputByteStream& is) {
419 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
420 CharType c = (unsigned char)is.Take();
421 c |= (unsigned char)is.Take() << 8;
422 c |= (unsigned char)is.Take() << 16;
423 c |= (unsigned char)is.Take() << 24;
424 return c;
425 }
426
427 template <typename OutputByteStream>
428 static void PutBOM(OutputByteStream& os) {
429 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
430 os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u);
431 }
432
433 template <typename OutputByteStream>
434 static void Put(OutputByteStream& os, CharType c) {
435 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
436 os.Put(c & 0xFFu);
437 os.Put((c >> 8) & 0xFFu);
438 os.Put((c >> 16) & 0xFFu);
439 os.Put((c >> 24) & 0xFFu);
440 }
441};
442
443//! UTF-32 big endian encoding.
444template<typename CharType = unsigned>
445struct UTF32BE : UTF32<CharType> {
446 template <typename InputByteStream>
447 static CharType TakeBOM(InputByteStream& is) {
448 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
449 CharType c = Take(is);
450 return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
451 }
452
453 template <typename InputByteStream>
454 static CharType Take(InputByteStream& is) {
455 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
456 CharType c = (unsigned char)is.Take() << 24;
457 c |= (unsigned char)is.Take() << 16;
458 c |= (unsigned char)is.Take() << 8;
459 c |= (unsigned char)is.Take();
460 return c;
461 }
462
463 template <typename OutputByteStream>
464 static void PutBOM(OutputByteStream& os) {
465 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
466 os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu);
467 }
468
469 template <typename OutputByteStream>
470 static void Put(OutputByteStream& os, CharType c) {
471 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
472 os.Put((c >> 24) & 0xFFu);
473 os.Put((c >> 16) & 0xFFu);
474 os.Put((c >> 8) & 0xFFu);
475 os.Put(c & 0xFFu);
476 }
477};
478
479///////////////////////////////////////////////////////////////////////////////
480// ASCII
481
482//! ASCII encoding.
483/*! http://en.wikipedia.org/wiki/ASCII
484 \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
485 \note implements Encoding concept
486*/
487template<typename CharType = char>
488struct ASCII {
489 typedef CharType Ch;
490
491 enum { supportUnicode = 0 };
492
493 template<typename OutputStream>
494 static void Encode(OutputStream& os, unsigned codepoint) {
495 RAPIDJSON_ASSERT(codepoint <= 0x7F);
496 os.Put(static_cast<Ch>(codepoint & 0xFF));
497 }
498
499 template <typename InputStream>
500 static bool Decode(InputStream& is, unsigned* codepoint) {
501 unsigned char c = static_cast<unsigned char>(is.Take());
502 *codepoint = c;
503 return c <= 0X7F;
504 }
505
506 template <typename InputStream, typename OutputStream>
507 static bool Validate(InputStream& is, OutputStream& os) {
508 unsigned char c = is.Take();
509 os.Put(c);
510 return c <= 0x7F;
511 }
512
513 template <typename InputByteStream>
514 static CharType TakeBOM(InputByteStream& is) {
515 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
516 Ch c = Take(is);
517 return c;
518 }
519
520 template <typename InputByteStream>
521 static Ch Take(InputByteStream& is) {
522 RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
523 return is.Take();
524 }
525
526 template <typename OutputByteStream>
527 static void PutBOM(OutputByteStream& os) {
528 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
529 (void)os;
530 }
531
532 template <typename OutputByteStream>
533 static void Put(OutputByteStream& os, Ch c) {
534 RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
535 os.Put(static_cast<typename OutputByteStream::Ch>(c));
536 }
537};
538
539///////////////////////////////////////////////////////////////////////////////
540// AutoUTF
541
542//! Runtime-specified UTF encoding type of a stream.
543enum UTFType {
544 kUTF8 = 0, //!< UTF-8.
545 kUTF16LE = 1, //!< UTF-16 little endian.
546 kUTF16BE = 2, //!< UTF-16 big endian.
547 kUTF32LE = 3, //!< UTF-32 little endian.
548 kUTF32BE = 4 //!< UTF-32 big endian.
549};
550
551//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
552/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
553*/
554template<typename CharType>
555struct AutoUTF {
556 typedef CharType Ch;
557
558 enum { supportUnicode = 1 };
559
560#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
561
562 template<typename OutputStream>
563 RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
564 typedef void (*EncodeFunc)(OutputStream&, unsigned);
565 static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
566 (*f[os.GetType()])(os, codepoint);
567 }
568
569 template <typename InputStream>
570 RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
571 typedef bool (*DecodeFunc)(InputStream&, unsigned*);
572 static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
573 return (*f[is.GetType()])(is, codepoint);
574 }
575
576 template <typename InputStream, typename OutputStream>
577 RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
578 typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
579 static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
580 return (*f[is.GetType()])(is, os);
581 }
582
583#undef RAPIDJSON_ENCODINGS_FUNC
584};
585
586///////////////////////////////////////////////////////////////////////////////
587// Transcoder
588
589//! Encoding conversion.
590template<typename SourceEncoding, typename TargetEncoding>
591struct Transcoder {
592 //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
593 template<typename InputStream, typename OutputStream>
594 RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
595 unsigned codepoint;
596 if (!SourceEncoding::Decode(is, &codepoint))
597 return false;
598 TargetEncoding::Encode(os, codepoint);
599 return true;
600 }
601
602 //! Validate one Unicode codepoint from an encoded stream.
603 template<typename InputStream, typename OutputStream>
604 RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
605 return Transcode(is, os); // Since source/target encoding is different, must transcode.
606 }
607};
608
609//! Specialization of Transcoder with same source and target encoding.
610template<typename Encoding>
611struct Transcoder<Encoding, Encoding> {
612 template<typename InputStream, typename OutputStream>
613 RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
614 os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
615 return true;
616 }
617
618 template<typename InputStream, typename OutputStream>
619 RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
620 return Encoding::Validate(is, os); // source/target encoding are the same
621 }
622};
623
624RAPIDJSON_NAMESPACE_END
625
626#if defined(__GNUC__) || defined(_MSV_VER)
627RAPIDJSON_DIAG_POP
628#endif
629
630#endif // RAPIDJSON_ENCODINGS_H_
0631
=== added directory 'shorts/xml2json/rapidjson/error'
=== added file 'shorts/xml2json/rapidjson/error/en.h'
--- shorts/xml2json/rapidjson/error/en.h 1970-01-01 00:00:00 +0000
+++ shorts/xml2json/rapidjson/error/en.h 2015-12-15 16:05:21 +0000
@@ -0,0 +1,71 @@
1// Copyright (C) 2011 Milo Yip
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#ifndef RAPIDJSON_ERROR_EN_H__
22#define RAPIDJSON_ERROR_EN_H__
23
24#include "error.h"
25
26RAPIDJSON_NAMESPACE_BEGIN
27
28//! Maps error code of parsing into error message.
29/*!
30 \ingroup RAPIDJSON_ERRORS
31 \param parseErrorCode Error code obtained in parsing.
32 \return the error message.
33 \note User can make a copy of this function for localization.
34 Using switch-case is safer for future modification of error codes.
35*/
36inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
37 switch (parseErrorCode) {
38 case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
39
40 case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
41 case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values.");
42
43 case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
44
45 case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
46 case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
47 case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
48
49 case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
50
51 case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
52 case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
53 case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
54 case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
55 case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
56
57 case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
58 case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
59 case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
60
61 case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
62 case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
63
64 default:
65 return RAPIDJSON_ERROR_STRING("Unknown error.");
66 }
67}
68
69RAPIDJSON_NAMESPACE_END
70
71#endif // RAPIDJSON_ERROR_EN_H__
072
=== added file 'shorts/xml2json/rapidjson/error/error.h'
--- shorts/xml2json/rapidjson/error/error.h 1970-01-01 00:00:00 +0000
+++ shorts/xml2json/rapidjson/error/error.h 2015-12-15 16:05:21 +0000
@@ -0,0 +1,150 @@
1// Copyright (C) 2011 Milo Yip
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#ifndef RAPIDJSON_ERROR_ERROR_H__
22#define RAPIDJSON_ERROR_ERROR_H__
23
24/*! \file error.h */
25
26/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
27
28///////////////////////////////////////////////////////////////////////////////
29// RAPIDJSON_ERROR_CHARTYPE
30
31//! Character type of error messages.
32/*! \ingroup RAPIDJSON_ERRORS
33 The default character type is \c char.
34 On Windows, user can define this macro as \c TCHAR for supporting both
35 unicode/non-unicode settings.
36*/
37#ifndef RAPIDJSON_ERROR_CHARTYPE
38#define RAPIDJSON_ERROR_CHARTYPE char
39#endif
40
41///////////////////////////////////////////////////////////////////////////////
42// RAPIDJSON_ERROR_STRING
43
44//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
45/*! \ingroup RAPIDJSON_ERRORS
46 By default this conversion macro does nothing.
47 On Windows, user can define this macro as \c _T(x) for supporting both
48 unicode/non-unicode settings.
49*/
50#ifndef RAPIDJSON_ERROR_STRING
51#define RAPIDJSON_ERROR_STRING(x) x
52#endif
53
54RAPIDJSON_NAMESPACE_BEGIN
55
56///////////////////////////////////////////////////////////////////////////////
57// ParseErrorCode
58
59//! Error code of parsing.
60/*! \ingroup RAPIDJSON_ERRORS
61 \see GenericReader::Parse, GenericReader::GetParseErrorCode
62*/
63enum ParseErrorCode {
64 kParseErrorNone = 0, //!< No error.
65
66 kParseErrorDocumentEmpty, //!< The document is empty.
67 kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values.
68
69 kParseErrorValueInvalid, //!< Invalid value.
70
71 kParseErrorObjectMissName, //!< Missing a name for object member.
72 kParseErrorObjectMissColon, //!< Missing a colon after a name of object member.
73 kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member.
74
75 kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element.
76
77 kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string.
78 kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid.
79 kParseErrorStringEscapeInvalid, //!< Invalid escape character in string.
80 kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string.
81 kParseErrorStringInvalidEncoding, //!< Invalid encoding in string.
82
83 kParseErrorNumberTooBig, //!< Number too big to be stored in double.
84 kParseErrorNumberMissFraction, //!< Miss fraction part in number.
85 kParseErrorNumberMissExponent, //!< Miss exponent in number.
86
87 kParseErrorTermination, //!< Parsing was terminated.
88 kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
89};
90
91//! Result of parsing (wraps ParseErrorCode)
92/*!
93 \ingroup RAPIDJSON_ERRORS
94 \code
95 Document doc;
96 ParseResult ok = doc.Parse("[42]");
97 if (!ok) {
98 fprintf(stderr, "JSON parse error: %s (%u)",
99 GetParseError_En(ok.Code()), ok.Offset());
100 exit(EXIT_FAILURE);
101 }
102 \endcode
103 \see GenericReader::Parse, GenericDocument::Parse
104*/
105struct ParseResult {
106
107 //! Default constructor, no error.
108 ParseResult() : code_(kParseErrorNone), offset_(0) {}
109 //! Constructor to set an error.
110 ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
111
112 //! Get the error code.
113 ParseErrorCode Code() const { return code_; }
114 //! Get the error offset, if \ref IsError(), 0 otherwise.
115 size_t Offset() const { return offset_; }
116
117 //! Conversion to \c bool, returns \c true, iff !\ref IsError().
118 operator bool() const { return !IsError(); }
119 //! Whether the result is an error.
120 bool IsError() const { return code_ != kParseErrorNone; }
121
122 bool operator==(const ParseResult& that) const { return code_ == that.code_; }
123 bool operator==(ParseErrorCode code) const { return code_ == code; }
124 friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
125
126 //! Reset error code.
127 void Clear() { Set(kParseErrorNone); }
128 //! Update error code and offset.
129 void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
130
131private:
132 ParseErrorCode code_;
133 size_t offset_;
134};
135
136//! Function pointer type of GetParseError().
137/*! \ingroup RAPIDJSON_ERRORS
138
139 This is the prototype for \c GetParseError_X(), where \c X is a locale.
140 User can dynamically change locale in runtime, e.g.:
141\code
142 GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
143 const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
144\endcode
145*/
146typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
147
148RAPIDJSON_NAMESPACE_END
149
150#endif // RAPIDJSON_ERROR_ERROR_H__
0151
=== added file 'shorts/xml2json/rapidjson/filereadstream.h'
--- shorts/xml2json/rapidjson/filereadstream.h 1970-01-01 00:00:00 +0000
+++ shorts/xml2json/rapidjson/filereadstream.h 2015-12-15 16:05:21 +0000
@@ -0,0 +1,94 @@
1// Copyright (C) 2011 Milo Yip
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#ifndef RAPIDJSON_FILEREADSTREAM_H_
22#define RAPIDJSON_FILEREADSTREAM_H_
23
24#include "rapidjson.h"
25#include <cstdio>
26
27RAPIDJSON_NAMESPACE_BEGIN
28
29//! File byte stream for input using fread().
30/*!
31 \note implements Stream concept
32*/
33class FileReadStream {
34public:
35 typedef char Ch; //!< Character type (byte).
36
37 //! Constructor.
38 /*!
39 \param fp File pointer opened for read.
40 \param buffer user-supplied buffer.
41 \param bufferSize size of buffer in bytes. Must >=4 bytes.
42 */
43 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) {
44 RAPIDJSON_ASSERT(fp_ != 0);
45 RAPIDJSON_ASSERT(bufferSize >= 4);
46 Read();
47 }
48
49 Ch Peek() const { return *current_; }
50 Ch Take() { Ch c = *current_; Read(); return c; }
51 size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
52
53 // Not implemented
54 void Put(Ch) { RAPIDJSON_ASSERT(false); }
55 void Flush() { RAPIDJSON_ASSERT(false); }
56 Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
57 size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
58
59 // For encoding detection only.
60 const Ch* Peek4() const {
61 return (current_ + 4 <= bufferLast_) ? current_ : 0;
62 }
63
64private:
65 void Read() {
66 if (current_ < bufferLast_)
67 ++current_;
68 else if (!eof_) {
69 count_ += readCount_;
70 readCount_ = fread(buffer_, 1, bufferSize_, fp_);
71 bufferLast_ = buffer_ + readCount_ - 1;
72 current_ = buffer_;
73
74 if (readCount_ < bufferSize_) {
75 buffer_[readCount_] = '\0';
76 ++bufferLast_;
77 eof_ = true;
78 }
79 }
80 }
81
82 std::FILE* fp_;
83 Ch *buffer_;
84 size_t bufferSize_;
85 Ch *bufferLast_;
86 Ch *current_;
87 size_t readCount_;
88 size_t count_; //!< Number of characters read
89 bool eof_;
90};
91
92RAPIDJSON_NAMESPACE_END
93
94#endif // RAPIDJSON_FILESTREAM_H_
095
=== added file 'shorts/xml2json/rapidjson/filestream.h'
--- shorts/xml2json/rapidjson/filestream.h 1970-01-01 00:00:00 +0000
+++ shorts/xml2json/rapidjson/filestream.h 2015-12-15 16:05:21 +0000
@@ -0,0 +1,73 @@
1// Copyright (C) 2011 Milo Yip
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#ifndef RAPIDJSON_FILESTREAM_H_
22#define RAPIDJSON_FILESTREAM_H_
23
24#include "rapidjson.h"
25#include <cstdio>
26
27RAPIDJSON_NAMESPACE_BEGIN
28
29//! (Deprecated) Wrapper of C file stream for input or output.
30/*!
31 This simple wrapper does not check the validity of the stream.
32 \note implements Stream concept
33 \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.
34*/
35class FileStream {
36public:
37 typedef char Ch; //!< Character type. Only support char.
38
39 FileStream(std::FILE* fp) : fp_(fp), current_('\0'), count_(0) { Read(); }
40 char Peek() const { return current_; }
41 char Take() { char c = current_; Read(); return c; }
42 size_t Tell() const { return count_; }
43 void Put(char c) { fputc(c, fp_); }
44 void Flush() { fflush(fp_); }
45
46 // Not implemented
47 char* PutBegin() { return 0; }
48 size_t PutEnd(char*) { return 0; }
49
50private:
51 // Prohibit copy constructor & assignment operator.
52 FileStream(const FileStream&);
53 FileStream& operator=(const FileStream&);
54
55 void Read() {
56 RAPIDJSON_ASSERT(fp_ != 0);
57 int c = fgetc(fp_);
58 if (c != EOF) {
59 current_ = (char)c;
60 count_++;
61 }
62 else if (current_ != '\0')
63 current_ = '\0';
64 }
65
66 std::FILE* fp_;
67 char current_;
68 size_t count_;
69};
70
71RAPIDJSON_NAMESPACE_END
72
73#endif // RAPIDJSON_FILESTREAM_H_
074
=== added file 'shorts/xml2json/rapidjson/filewritestream.h'
--- shorts/xml2json/rapidjson/filewritestream.h 1970-01-01 00:00:00 +0000
+++ shorts/xml2json/rapidjson/filewritestream.h 2015-12-15 16:05:21 +0000
@@ -0,0 +1,97 @@
1// Copyright (C) 2011 Milo Yip
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#ifndef RAPIDJSON_FILEWRITESTREAM_H_
22#define RAPIDJSON_FILEWRITESTREAM_H_
23
24#include "rapidjson.h"
25#include <cstdio>
26
27RAPIDJSON_NAMESPACE_BEGIN
28
29//! Wrapper of C file stream for input using fread().
30/*!
31 \note implements Stream concept
32*/
33class FileWriteStream {
34public:
35 typedef char Ch; //!< Character type. Only support char.
36
37 FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
38 RAPIDJSON_ASSERT(fp_ != 0);
39 }
40
41 void Put(char c) {
42 if (current_ >= bufferEnd_)
43 Flush();
44
45 *current_++ = c;
46 }
47
48 void PutN(char c, size_t n) {
49 size_t avail = static_cast<size_t>(bufferEnd_ - current_);
50 while (n > avail) {
51 std::memset(current_, c, avail);
52 current_ += avail;
53 Flush();
54 n -= avail;
55 avail = static_cast<size_t>(bufferEnd_ - current_);
56 }
57
58 if (n > 0) {
59 std::memset(current_, c, n);
60 current_ += n;
61 }
62 }
63
64 void Flush() {
65 if (current_ != buffer_) {
66 fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
67 current_ = buffer_;
68 }
69 }
70
71 // Not implemented
72 char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
73 char Take() { RAPIDJSON_ASSERT(false); return 0; }
74 size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
75 char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
76 size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
77
78private:
79 // Prohibit copy constructor & assignment operator.
80 FileWriteStream(const FileWriteStream&);
81 FileWriteStream& operator=(const FileWriteStream&);
82
83 std::FILE* fp_;
84 char *buffer_;
85 char *bufferEnd_;
86 char *current_;
87};
88
89//! Implement specialized version of PutN() with memset() for better performance.
90template<>
91inline void PutN(FileWriteStream& stream, char c, size_t n) {
92 stream.PutN(c, n);
93}
94
95RAPIDJSON_NAMESPACE_END
96
97#endif // RAPIDJSON_FILESTREAM_H_
098
=== added directory 'shorts/xml2json/rapidjson/internal'
=== added file 'shorts/xml2json/rapidjson/internal/biginteger.h'
--- shorts/xml2json/rapidjson/internal/biginteger.h 1970-01-01 00:00:00 +0000
+++ shorts/xml2json/rapidjson/internal/biginteger.h 2015-12-15 16:05:21 +0000
@@ -0,0 +1,294 @@
1// Copyright (C) 2011 Milo Yip
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#ifndef RAPIDJSON_BIGINTEGER_H_
22#define RAPIDJSON_BIGINTEGER_H_
23
24#include "../rapidjson.h"
25
26#if defined(_MSC_VER) && defined(_M_AMD64)
27#include <intrin.h> // for _umul128
28#endif
29
30RAPIDJSON_NAMESPACE_BEGIN
31namespace internal {
32
33class BigInteger {
34public:
35 typedef uint64_t Type;
36
37 BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
38 std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
39 }
40
41 explicit BigInteger(uint64_t u) : count_(1) {
42 digits_[0] = u;
43 }
44
45 BigInteger(const char* decimals, size_t length) : count_(1) {
46 RAPIDJSON_ASSERT(length > 0);
47 digits_[0] = 0;
48 size_t i = 0;
49 const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
50 while (length >= kMaxDigitPerIteration) {
51 AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
52 length -= kMaxDigitPerIteration;
53 i += kMaxDigitPerIteration;
54 }
55
56 if (length > 0)
57 AppendDecimal64(decimals + i, decimals + i + length);
58 }
59
60 BigInteger& operator=(uint64_t u) {
61 digits_[0] = u;
62 count_ = 1;
63 return *this;
64 }
65
66 BigInteger& operator+=(uint64_t u) {
67 Type backup = digits_[0];
68 digits_[0] += u;
69 for (size_t i = 0; i < count_ - 1; i++) {
70 if (digits_[i] >= backup)
71 return *this; // no carry
72 backup = digits_[i + 1];
73 digits_[i + 1] += 1;
74 }
75
76 // Last carry
77 if (digits_[count_ - 1] < backup)
78 PushBack(1);
79
80 return *this;
81 }
82
83 BigInteger& operator*=(uint64_t u) {
84 if (u == 0) return *this = 0;
85 if (u == 1) return *this;
86 if (*this == 1) return *this = u;
87
88 uint64_t k = 0;
89 for (size_t i = 0; i < count_; i++) {
90 uint64_t hi;
91 digits_[i] = MulAdd64(digits_[i], u, k, &hi);
92 k = hi;
93 }
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches