Merge lp:~qqworini/ubuntu-rssreader-app/fix-crash-rewrite-opml into lp:ubuntu-rssreader-app
- fix-crash-rewrite-opml
- Merge into reboot
Status: | Merged | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Joey Chan | ||||||||||||||||||||
Approved revision: | 428 | ||||||||||||||||||||
Merged at revision: | 453 | ||||||||||||||||||||
Proposed branch: | lp:~qqworini/ubuntu-rssreader-app/fix-crash-rewrite-opml | ||||||||||||||||||||
Merge into: | lp:ubuntu-rssreader-app | ||||||||||||||||||||
Diff against target: |
9146 lines (+5314/-1200) 42 files modified
.bzrignore (+1/-0) shorts/po/com.ubuntu.shorts.pot (+28/-28) shorts/po/zh_CN.po (+0/-458) shorts/qml/components/ArticleViewItem.qml (+6/-1) shorts/qml/content/ContentPickerDialog.qml (+4/-0) shorts/qml/content/ImportFeeds.qml (+10/-2) shorts/qml/content/OpmlParser.qml (+42/-19) shorts/qml/nongoogle/AppendNGFeedPage.qml (+14/-9) shorts/qml/nongoogle/XmlNetwork.qml (+57/-42) shorts/qml/shorts-app.qml (+2/-0) shorts/qml/utils/databasemodule_v2.js (+7/-5) shorts/utilities.cpp (+89/-15) shorts/utilities.h (+20/-1) shorts/xml2json/rapidjson/allocators.h (+3/-1) shorts/xml2json/rapidjson/document.h (+607/-160) shorts/xml2json/rapidjson/encodedstream.h (+30/-1) shorts/xml2json/rapidjson/encodings.h (+77/-0) shorts/xml2json/rapidjson/filereadstream.h (+1/-1) shorts/xml2json/rapidjson/filewritestream.h (+1/-1) shorts/xml2json/rapidjson/fwd.h (+151/-0) shorts/xml2json/rapidjson/internal/diyfp.h (+1/-1) shorts/xml2json/rapidjson/internal/dtoa.h (+33/-6) shorts/xml2json/rapidjson/internal/ieee754.h (+1/-0) shorts/xml2json/rapidjson/internal/regex.h (+705/-0) shorts/xml2json/rapidjson/internal/stack.h (+39/-5) shorts/xml2json/rapidjson/internal/strfunc.h (+17/-1) shorts/xml2json/rapidjson/internal/strtod.h (+0/-1) shorts/xml2json/rapidjson/internal/swap.h (+9/-0) shorts/xml2json/rapidjson/istreamwrapper.h (+110/-0) shorts/xml2json/rapidjson/memorybuffer.h (+1/-1) shorts/xml2json/rapidjson/memorystream.h (+3/-3) shorts/xml2json/rapidjson/ostreamwrapper.h (+76/-0) shorts/xml2json/rapidjson/pointer.h (+55/-27) shorts/xml2json/rapidjson/prettywriter.h (+52/-10) shorts/xml2json/rapidjson/rapidjson.h (+76/-150) shorts/xml2json/rapidjson/reader.h (+539/-200) shorts/xml2json/rapidjson/schema.h (+2017/-0) shorts/xml2json/rapidjson/stream.h (+179/-0) shorts/xml2json/rapidjson/stringbuffer.h (+25/-1) shorts/xml2json/rapidjson/writer.h (+222/-48) shorts/xml2json/rapidxml/rapidxml.hpp (+1/-1) shorts/xml2json/xml2json.hpp (+3/-1) |
||||||||||||||||||||
To merge this branch: | bzr merge lp:~qqworini/ubuntu-rssreader-app/fix-crash-rewrite-opml | ||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jenkins Bot | continuous-integration | Approve | |
Ubuntu Shorts Developers | Pending | ||
Review via email: mp+297077@code.launchpad.net |
Commit message
fix crash bug, rewrite opml parser, update xml2json with latest upstream. fix bug 1543995.
And a new help page.
Description of the change
fix crash bug, rewrite opml parser, update xml2json with latest upstream. fix bug 1543995.
And a new help page.
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
None: https:/
- 425. By Joey Chan
-
fix crash bug, rewrite opml parser, update xml2json with latest upstream. fix bug 1543995. fix Po file conflict. version 2
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:425
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 426. By Joey Chan
-
fix crash bug, rewrite opml parser, update xml2json with latest upstream. fix bug 1543995. fix Po file conflict. version 2
- 427. By Joey Chan
-
fix crash bug, rewrite opml parser, update xml2json with latest upstream. fix bug 1543995. fix Po file conflict. version 3
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:427
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 428. By Joey Chan
-
fix crash bug, rewrite opml parser, update xml2json with latest upstream. fix bug 1543995. Update zh_CN Po file conflict. version 4
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:428
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2015-07-17 14:42:42 +0000 |
3 | +++ .bzrignore 2016-06-15 16:13:25 +0000 |
4 | @@ -1,1 +1,2 @@ |
5 | RE:(?i).*\.user |
6 | +*.afc62ac |
7 | |
8 | === modified file 'shorts/po/com.ubuntu.shorts.pot' |
9 | --- shorts/po/com.ubuntu.shorts.pot 2016-03-23 01:45:49 +0000 |
10 | +++ shorts/po/com.ubuntu.shorts.pot 2016-06-15 16:13:25 +0000 |
11 | @@ -8,7 +8,7 @@ |
12 | msgstr "" |
13 | "Project-Id-Version: \n" |
14 | "Report-Msgid-Bugs-To: \n" |
15 | -"POT-Creation-Date: 2016-03-11 20:54+0800\n" |
16 | +"POT-Creation-Date: 2016-06-10 14:54+0000\n" |
17 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
18 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
19 | "Language-Team: LANGUAGE <LL@li.org>\n" |
20 | @@ -18,7 +18,7 @@ |
21 | "Content-Transfer-Encoding: 8bit\n" |
22 | "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" |
23 | |
24 | -#: ../qml/components/ArticleViewItem.qml:120 |
25 | +#: ../qml/components/ArticleViewItem.qml:125 |
26 | msgid "Select article" |
27 | msgstr "" |
28 | |
29 | @@ -50,51 +50,51 @@ |
30 | msgid "Confirm" |
31 | msgstr "" |
32 | |
33 | -#: ../qml/content/ImportFeeds.qml:305 |
34 | +#: ../qml/content/ImportFeeds.qml:313 |
35 | msgid "Please select an opml file" |
36 | msgstr "" |
37 | |
38 | -#: ../qml/content/ImportFeeds.qml:310 |
39 | +#: ../qml/content/ImportFeeds.qml:318 |
40 | msgid "Open" |
41 | msgstr "" |
42 | |
43 | -#: ../qml/content/ImportFeeds.qml:293 |
44 | +#: ../qml/content/ImportFeeds.qml:301 |
45 | msgid "" |
46 | "Attention please, before importing opml file, Shorts only support one opml " |
47 | "structure. <br><br>" |
48 | msgstr "" |
49 | |
50 | #: ../qml/nongoogle/AppendNGFeedPage.qml:30 ../qml/pages/AppendFeedPage.qml:31 |
51 | -#: ../qml/shorts-app.qml:265 ../qml/shorts-app.qml:403 |
52 | -#: ../qml/shorts-app.qml:411 |
53 | +#: ../qml/shorts-app.qml:267 ../qml/shorts-app.qml:405 |
54 | +#: ../qml/shorts-app.qml:413 |
55 | msgid "Add feeds" |
56 | msgstr "" |
57 | |
58 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:94 |
59 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:99 |
60 | #: ../qml/pages/AppendFeedPage.qml:137 |
61 | msgid "Type a keyword or URL" |
62 | msgstr "" |
63 | |
64 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:149 |
65 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:154 |
66 | msgid "Feed Title:" |
67 | msgstr "" |
68 | |
69 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:157 |
70 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:172 |
71 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:162 |
72 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:177 |
73 | msgid "No data" |
74 | msgstr "" |
75 | |
76 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:164 |
77 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:169 |
78 | msgid "Feed Description:" |
79 | msgstr "" |
80 | |
81 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:197 |
82 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:202 |
83 | #: ../qml/pages/AppendFeedPage.qml:243 ../qml/pages/CreateTopicPage.qml:38 |
84 | -#: ../qml/pages/TopicManagement.qml:239 ../qml/shorts-app.qml:494 |
85 | +#: ../qml/pages/TopicManagement.qml:239 ../qml/shorts-app.qml:496 |
86 | msgid "Cancel" |
87 | msgstr "" |
88 | |
89 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:230 |
90 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:235 |
91 | #: ../qml/pages/AppendFeedPage.qml:276 |
92 | msgid "Next" |
93 | msgstr "" |
94 | @@ -320,7 +320,7 @@ |
95 | msgid "Click here to report a bug" |
96 | msgstr "" |
97 | |
98 | -#: ../qml/pages/PageSettings.qml:9 ../qml/shorts-app.qml:249 |
99 | +#: ../qml/pages/PageSettings.qml:9 ../qml/shorts-app.qml:251 |
100 | msgid "Settings" |
101 | msgstr "" |
102 | |
103 | @@ -352,7 +352,7 @@ |
104 | msgid "Import OPML" |
105 | msgstr "" |
106 | |
107 | -#: ../qml/pages/TopicManagement.qml:13 ../qml/shorts-app.qml:229 |
108 | +#: ../qml/pages/TopicManagement.qml:13 ../qml/shorts-app.qml:231 |
109 | msgid "Edit topics" |
110 | msgstr "" |
111 | |
112 | @@ -360,47 +360,47 @@ |
113 | msgid "Add Feed" |
114 | msgstr "" |
115 | |
116 | -#: ../qml/shorts-app.qml:196 |
117 | +#: ../qml/shorts-app.qml:198 |
118 | msgid "Refresh" |
119 | msgstr "" |
120 | |
121 | -#: ../qml/shorts-app.qml:203 |
122 | +#: ../qml/shorts-app.qml:205 |
123 | msgid "Grid View" |
124 | msgstr "" |
125 | |
126 | -#: ../qml/shorts-app.qml:203 |
127 | +#: ../qml/shorts-app.qml:205 |
128 | msgid "List view" |
129 | msgstr "" |
130 | |
131 | -#: ../qml/shorts-app.qml:239 |
132 | +#: ../qml/shorts-app.qml:241 |
133 | msgid "Disable night mode" |
134 | msgstr "" |
135 | |
136 | -#: ../qml/shorts-app.qml:239 |
137 | +#: ../qml/shorts-app.qml:241 |
138 | msgid "Enable night mode" |
139 | msgstr "" |
140 | |
141 | -#: ../qml/shorts-app.qml:334 |
142 | +#: ../qml/shorts-app.qml:336 |
143 | msgid "Saved" |
144 | msgstr "" |
145 | |
146 | -#: ../qml/shorts-app.qml:342 shorts.desktop.in.in.h:1 |
147 | +#: ../qml/shorts-app.qml:344 shorts.desktop.in.in.h:1 |
148 | msgid "Shorts" |
149 | msgstr "" |
150 | |
151 | -#: ../qml/shorts-app.qml:486 |
152 | +#: ../qml/shorts-app.qml:488 |
153 | msgid "Checking for new articles" |
154 | msgstr "" |
155 | |
156 | -#: ../qml/shorts-app.qml:510 |
157 | +#: ../qml/shorts-app.qml:512 |
158 | msgid "Perhaps some of the channels have not been updated." |
159 | msgstr "" |
160 | |
161 | -#: ../qml/shorts-app.qml:511 |
162 | +#: ../qml/shorts-app.qml:513 |
163 | msgid "Errors occurred during the update" |
164 | msgstr "" |
165 | |
166 | -#: ../qml/shorts-app.qml:525 |
167 | +#: ../qml/shorts-app.qml:527 |
168 | msgid "Ok" |
169 | msgstr "" |
170 | |
171 | |
172 | === added file 'shorts/po/zh_CN.po' |
173 | --- shorts/po/zh_CN.po 1970-01-01 00:00:00 +0000 |
174 | +++ shorts/po/zh_CN.po 2016-06-15 16:13:25 +0000 |
175 | @@ -0,0 +1,458 @@ |
176 | +# Chinese (Simplified) translation for ubuntu-rssreader-app |
177 | +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 |
178 | +# This file is distributed under the same license as the ubuntu-rssreader-app package. |
179 | +# FIRST AUTHOR <EMAIL@ADDRESS>, 2013. |
180 | +# |
181 | +msgid "" |
182 | +msgstr "" |
183 | +"Project-Id-Version: ubuntu-rssreader-app\n" |
184 | +"Report-Msgid-Bugs-To: \n" |
185 | +"POT-Creation-Date: 2016-06-10 14:54+0000\n" |
186 | +"PO-Revision-Date: 2015-06-29 01:52+0000\n" |
187 | +"Last-Translator: Ian Li <Unknown>\n" |
188 | +"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n" |
189 | +"Language: \n" |
190 | +"MIME-Version: 1.0\n" |
191 | +"Content-Type: text/plain; charset=UTF-8\n" |
192 | +"Content-Transfer-Encoding: 8bit\n" |
193 | +"Plural-Forms: nplurals=1; plural=0;\n" |
194 | +"X-Launchpad-Export-Date: 2016-03-24 06:05+0000\n" |
195 | +"X-Generator: Launchpad (build 17958)\n" |
196 | + |
197 | +#: ../qml/components/ArticleViewItem.qml:125 |
198 | +msgid "Select article" |
199 | +msgstr "选择文章" |
200 | + |
201 | +#: ../qml/components/ReadingOptions.qml:39 |
202 | +msgid "Dark" |
203 | +msgstr "深色" |
204 | + |
205 | +#: ../qml/components/ReadingOptions.qml:46 |
206 | +msgid "Light" |
207 | +msgstr "浅色" |
208 | + |
209 | +#: ../qml/components/ReadingOptions.qml:96 |
210 | +msgid "Small" |
211 | +msgstr "小" |
212 | + |
213 | +#: ../qml/components/ReadingOptions.qml:98 |
214 | +msgid "Normal" |
215 | +msgstr "" |
216 | + |
217 | +#: ../qml/components/ReadingOptions.qml:99 |
218 | +msgid "Large" |
219 | +msgstr "大" |
220 | + |
221 | +#: ../qml/content/ImportFeeds.qml:30 |
222 | +msgid "Import Feeds" |
223 | +msgstr "" |
224 | + |
225 | +#: ../qml/content/ImportFeeds.qml:42 ../qml/pages/TopicManagement.qml:258 |
226 | +msgid "Confirm" |
227 | +msgstr "确认" |
228 | + |
229 | +#: ../qml/content/ImportFeeds.qml:313 |
230 | +msgid "Please select an opml file" |
231 | +msgstr "" |
232 | + |
233 | +#: ../qml/content/ImportFeeds.qml:318 |
234 | +msgid "Open" |
235 | +msgstr "" |
236 | + |
237 | +#: ../qml/content/ImportFeeds.qml:301 |
238 | +msgid "" |
239 | +"Attention please, before importing opml file, Shorts only support one opml " |
240 | +"structure. <br><br>" |
241 | +msgstr "" |
242 | + |
243 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:30 ../qml/pages/AppendFeedPage.qml:31 |
244 | +#: ../qml/shorts-app.qml:267 ../qml/shorts-app.qml:405 |
245 | +#: ../qml/shorts-app.qml:413 |
246 | +msgid "Add feeds" |
247 | +msgstr "添加信息源" |
248 | + |
249 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:99 ../qml/pages/AppendFeedPage.qml:137 |
250 | +msgid "Type a keyword or URL" |
251 | +msgstr "请输入关键字或网址" |
252 | + |
253 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:154 |
254 | +msgid "Feed Title:" |
255 | +msgstr "" |
256 | + |
257 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:162 |
258 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:177 |
259 | +msgid "No data" |
260 | +msgstr "" |
261 | + |
262 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:169 |
263 | +msgid "Feed Description:" |
264 | +msgstr "" |
265 | + |
266 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:202 |
267 | +#: ../qml/pages/AppendFeedPage.qml:243 ../qml/pages/CreateTopicPage.qml:38 |
268 | +#: ../qml/pages/TopicManagement.qml:239 ../qml/shorts-app.qml:496 |
269 | +msgid "Cancel" |
270 | +msgstr "取消" |
271 | + |
272 | +#: ../qml/nongoogle/AppendNGFeedPage.qml:235 |
273 | +#: ../qml/pages/AppendFeedPage.qml:276 |
274 | +msgid "Next" |
275 | +msgstr "下一项" |
276 | + |
277 | +#: ../qml/pages/AppendFeedPage.qml:69 |
278 | +msgid "Failed to perform a feed search by keyword" |
279 | +msgstr "暂时搜索不到有关该关键词的信息" |
280 | + |
281 | +#: ../qml/pages/AppendFeedPage.qml:70 ../qml/pages/AppendFeedPage.qml:101 |
282 | +msgid "Search failed" |
283 | +msgstr "哎哟,好像除了点问题。。" |
284 | + |
285 | +#: ../qml/pages/AppendFeedPage.qml:100 |
286 | +msgid "Failed to perform a feed search by URL" |
287 | +msgstr "暂时搜索不到有关该网址的信息" |
288 | + |
289 | +#: ../qml/pages/AppendFeedPage.qml:185 |
290 | +msgid "Search results" |
291 | +msgstr "搜索结果" |
292 | + |
293 | +#: ../qml/pages/AppendFeedPage.qml:305 ../qml/pages/CreateTopicPage.qml:181 |
294 | +msgid "No feeds" |
295 | +msgstr "当前没有信息源" |
296 | + |
297 | +#: ../qml/pages/ArticleViewPage.qml:47 |
298 | +msgid "Save" |
299 | +msgstr "保存" |
300 | + |
301 | +#: ../qml/pages/ArticleViewPage.qml:47 |
302 | +msgid "Remove" |
303 | +msgstr "移除" |
304 | + |
305 | +#: ../qml/pages/ArticleViewPage.qml:60 |
306 | +msgid "Options" |
307 | +msgstr "选项" |
308 | + |
309 | +#: ../qml/pages/ArticleViewPage.qml:68 |
310 | +msgid "Open site" |
311 | +msgstr "打开网站" |
312 | + |
313 | +#: ../qml/pages/ArticleViewPage.qml:76 |
314 | +msgid "Share..." |
315 | +msgstr "" |
316 | + |
317 | +#: ../qml/pages/ChooseTopicPage.qml:13 |
318 | +msgid "Choose topic" |
319 | +msgstr "请选择话题" |
320 | + |
321 | +#: ../qml/pages/ChooseTopicPage.qml:77 |
322 | +msgid "Add your new feeds to a topic" |
323 | +msgstr "请添加您的信息源到某个话题中" |
324 | + |
325 | +#: ../qml/pages/ChooseTopicPage.qml:88 |
326 | +msgid " + New topic" |
327 | +msgstr " + 添加新话题" |
328 | + |
329 | +#: ../qml/pages/ChooseTopicPage.qml:108 ../qml/pages/CreateTopicPage.qml:77 |
330 | +msgid "A topic with this name already exists" |
331 | +msgstr "该话题已经存在" |
332 | + |
333 | +#: ../qml/pages/ChooseTopicPage.qml:109 ../qml/pages/ChooseTopicPage.qml:122 |
334 | +#: ../qml/pages/CreateTopicPage.qml:66 ../qml/pages/CreateTopicPage.qml:78 |
335 | +msgid "Warning" |
336 | +msgstr "提示" |
337 | + |
338 | +#: ../qml/pages/ChooseTopicPage.qml:121 ../qml/pages/CreateTopicPage.qml:65 |
339 | +msgid "Topic name can't contain only whitespaces" |
340 | +msgstr "请不要在话题中包含空格" |
341 | + |
342 | +#: ../qml/pages/CreateTopicPage.qml:12 |
343 | +msgid "Create new topic" |
344 | +msgstr "创建一个新的话题" |
345 | + |
346 | +#: ../qml/pages/CreateTopicPage.qml:56 ../qml/pages/TopicManagement.qml:92 |
347 | +msgid "Add topic" |
348 | +msgstr "添加话题" |
349 | + |
350 | +#: ../qml/pages/CreateTopicPage.qml:126 |
351 | +msgid "Type topic name" |
352 | +msgstr "请输入话题名称" |
353 | + |
354 | +#: ../qml/pages/CreateTopicPage.qml:142 |
355 | +msgid "Select feeds (optional)" |
356 | +msgstr "请选择信息源" |
357 | + |
358 | +#: ../qml/pages/EditFeedPage.qml:12 |
359 | +msgid "Edit Feed" |
360 | +msgstr "编辑信息源" |
361 | + |
362 | +#: ../qml/pages/EditFeedPage.qml:19 |
363 | +msgid "Done" |
364 | +msgstr "完成" |
365 | + |
366 | +#: ../qml/pages/EditFeedPage.qml:82 |
367 | +msgid "Title: " |
368 | +msgstr "标题: " |
369 | + |
370 | +#: ../qml/pages/EditFeedPage.qml:103 |
371 | +msgid "URL: " |
372 | +msgstr "地址: " |
373 | + |
374 | +#: ../qml/pages/EditFeedPage.qml:120 |
375 | +msgid "Topic: " |
376 | +msgstr "话题: " |
377 | + |
378 | +#: ../qml/pages/PageHelp.qml:15 |
379 | +msgid "Welcome to Shorts" |
380 | +msgstr "" |
381 | + |
382 | +#: ../qml/pages/PageHelp.qml:17 |
383 | +msgid "View Articles" |
384 | +msgstr "" |
385 | + |
386 | +#: ../qml/pages/PageHelp.qml:19 |
387 | +msgid "Search RSS" |
388 | +msgstr "" |
389 | + |
390 | +#: ../qml/pages/PageHelp.qml:21 |
391 | +msgid "Manage topics and feeds" |
392 | +msgstr "" |
393 | + |
394 | +#: ../qml/pages/PageHelp.qml:23 |
395 | +msgid "Location" |
396 | +msgstr "" |
397 | + |
398 | +#: ../qml/pages/PageHelp.qml:25 |
399 | +msgid "Enjoy" |
400 | +msgstr "" |
401 | + |
402 | +#: ../qml/pages/PageHelp.qml:105 |
403 | +msgid "Shorts is an RSS reader app developed by Canonical & Ubuntu Comunity." |
404 | +msgstr "" |
405 | + |
406 | +#: ../qml/pages/PageHelp.qml:110 |
407 | +msgid "" |
408 | +"Shorts provides most primary features which also can be seen in other RSS " |
409 | +"reader apps, with a beautiful Ubuntu style user interface." |
410 | +msgstr "" |
411 | + |
412 | +#: ../qml/pages/PageHelp.qml:117 |
413 | +msgid "Swipe left to continue." |
414 | +msgstr "" |
415 | + |
416 | +#: ../qml/pages/PageHelp.qml:136 |
417 | +msgid "Scroll left/right in grid mode or scroll up/down in list mode." |
418 | +msgstr "" |
419 | + |
420 | +#: ../qml/pages/PageHelp.qml:163 |
421 | +msgid "" |
422 | +"Swipe up will enter this search page, just type any simple words, or paste a " |
423 | +"link." |
424 | +msgstr "" |
425 | + |
426 | +#: ../qml/pages/PageHelp.qml:190 |
427 | +msgid "" |
428 | +"Every feed must belong to one topic, swipe one item to delete feed/topic." |
429 | +msgstr "" |
430 | + |
431 | +#: ../qml/pages/PageHelp.qml:223 |
432 | +msgid "Seems you are living in: " |
433 | +msgstr "" |
434 | + |
435 | +#: ../qml/pages/PageHelp.qml:232 |
436 | +msgid "" |
437 | +"Some regions/countries(e.g. China) may block Google service, if you're " |
438 | +"living there or plan to go there, we suggest to trun off the build-in Google " |
439 | +"RSS service in settings page, or nothing you should care." |
440 | +msgstr "" |
441 | + |
442 | +#: ../qml/pages/PageHelp.qml:239 |
443 | +msgid "" |
444 | +"We detect that you're living in some region/country(e.g. China) which blocks " |
445 | +"Google service, so Shorts disable the build-in Google RSS service by " |
446 | +"default. You still can turn it on here or in settings page." |
447 | +msgstr "" |
448 | + |
449 | +#: ../qml/pages/PageHelp.qml:250 |
450 | +msgid "Use Google RSS engine: " |
451 | +msgstr "" |
452 | + |
453 | +#: ../qml/pages/PageHelp.qml:287 |
454 | +msgid "Enjoy !" |
455 | +msgstr "" |
456 | + |
457 | +#: ../qml/pages/PageHelp.qml:297 |
458 | +msgid "Do not show this help page again " |
459 | +msgstr "" |
460 | + |
461 | +#: ../qml/pages/PageHelp.qml:316 |
462 | +msgid "Start using Shorts !" |
463 | +msgstr "" |
464 | + |
465 | +#: ../qml/pages/PageHelp.qml:340 |
466 | +msgid "Skip" |
467 | +msgstr "" |
468 | + |
469 | +#: ../qml/pages/PageInfo.qml:10 |
470 | +msgid "About Shorts" |
471 | +msgstr "" |
472 | + |
473 | +#: ../qml/pages/PageInfo.qml:39 |
474 | +msgid "Author" |
475 | +msgstr "" |
476 | + |
477 | +#: ../qml/pages/PageInfo.qml:53 |
478 | +msgid "Copyleft" |
479 | +msgstr "" |
480 | + |
481 | +#: ../qml/pages/PageInfo.qml:57 |
482 | +msgid "License with GPLv3" |
483 | +msgstr "" |
484 | + |
485 | +#: ../qml/pages/PageInfo.qml:62 |
486 | +msgid "" |
487 | +"Ubuntu Shorts App is the official rss reader app for Ubuntu Touch. We follow " |
488 | +"an open source model where the code is available to anyone to branch and " |
489 | +"hack on. The ubuntu shorts app follows a test driven development (TDD) where " |
490 | +"tests are written in parallel to feature implementation to help spot " |
491 | +"regressions easier." |
492 | +msgstr "" |
493 | + |
494 | +#: ../qml/pages/PageInfo.qml:68 |
495 | +msgid "Click here to report a bug" |
496 | +msgstr "" |
497 | + |
498 | +#: ../qml/pages/PageSettings.qml:9 ../qml/shorts-app.qml:251 |
499 | +msgid "Settings" |
500 | +msgstr "" |
501 | + |
502 | +#: ../qml/pages/PageSettings.qml:15 |
503 | +msgid "Help" |
504 | +msgstr "" |
505 | + |
506 | +#: ../qml/pages/PageSettings.qml:20 |
507 | +msgid "Info" |
508 | +msgstr "" |
509 | + |
510 | +#: ../qml/pages/PageSettings.qml:51 |
511 | +msgid "" |
512 | +"Some special regions/countries block Google service, we suggest to turn off " |
513 | +"the switch below if living in there." |
514 | +msgstr "" |
515 | + |
516 | +#: ../qml/pages/PageSettings.qml:59 |
517 | +msgid "Use Google Search: " |
518 | +msgstr "" |
519 | + |
520 | +#: ../qml/pages/PageSettings.qml:84 |
521 | +msgid "" |
522 | +"For those users, who want to import their RSS feeds from other sources, " |
523 | +"please press the button below." |
524 | +msgstr "" |
525 | + |
526 | +#: ../qml/pages/PageSettings.qml:94 |
527 | +msgid "Import OPML" |
528 | +msgstr "" |
529 | + |
530 | +#: ../qml/pages/TopicManagement.qml:13 ../qml/shorts-app.qml:231 |
531 | +msgid "Edit topics" |
532 | +msgstr "编辑话题" |
533 | + |
534 | +#: ../qml/pages/TopicManagement.qml:274 |
535 | +msgid "Add Feed" |
536 | +msgstr "添加信息源" |
537 | + |
538 | +#: ../qml/shorts-app.qml:198 |
539 | +msgid "Refresh" |
540 | +msgstr "刷新" |
541 | + |
542 | +#: ../qml/shorts-app.qml:205 |
543 | +msgid "Grid View" |
544 | +msgstr "网格视图" |
545 | + |
546 | +#: ../qml/shorts-app.qml:205 |
547 | +msgid "List view" |
548 | +msgstr "列表视图" |
549 | + |
550 | +#: ../qml/shorts-app.qml:241 |
551 | +msgid "Disable night mode" |
552 | +msgstr "" |
553 | + |
554 | +#: ../qml/shorts-app.qml:241 |
555 | +msgid "Enable night mode" |
556 | +msgstr "" |
557 | + |
558 | +#: ../qml/shorts-app.qml:336 |
559 | +msgid "Saved" |
560 | +msgstr "已保存" |
561 | + |
562 | +#: ../qml/shorts-app.qml:344 shorts.desktop.in.in.h:1 |
563 | +msgid "Shorts" |
564 | +msgstr "摘要阅读" |
565 | + |
566 | +#: ../qml/shorts-app.qml:488 |
567 | +msgid "Checking for new articles" |
568 | +msgstr "正在查询新的文章" |
569 | + |
570 | +#: ../qml/shorts-app.qml:512 |
571 | +msgid "Perhaps some of the channels have not been updated." |
572 | +msgstr "部分频道内容可能未更新。" |
573 | + |
574 | +#: ../qml/shorts-app.qml:513 |
575 | +msgid "Errors occurred during the update" |
576 | +msgstr "更新过程中出错" |
577 | + |
578 | +#: ../qml/shorts-app.qml:527 |
579 | +msgid "Ok" |
580 | +msgstr "确认" |
581 | + |
582 | +#: ../qml/tabs/BaseTab.qml:153 |
583 | +msgid "There are no articles to show" |
584 | +msgstr "当前没有文章可显示" |
585 | + |
586 | +#. TRANSLATORS: this is a time formatting string, |
587 | +#. see http://qt-project.org/doc/qt-5.0/qtqml/qml-qtquick2-date.html#details for valid expressions |
588 | +#: ../qml/utils/dateutils.js:39 |
589 | +msgid "MMMM d" |
590 | +msgstr "M 月 d 日" |
591 | + |
592 | +#: ../qml/utils/dateutils.js:54 |
593 | +#, qt-format |
594 | +msgid "Yesterday at %1" |
595 | +msgstr "昨天 %1" |
596 | + |
597 | +#. TRANSLATORS: this is a time formatting string, |
598 | +#. see http://qt-project.org/doc/qt-5.0/qtqml/qml-qtquick2-date.html#details for valid expressions |
599 | +#: ../qml/utils/dateutils.js:57 |
600 | +msgid "h:mm AP" |
601 | +msgstr "AP h:mm" |
602 | + |
603 | +#. TRANSLATORS: this is a time formatting string, |
604 | +#. see http://qt-project.org/doc/qt-5.0/qtqml/qml-qtquick2-date.html#details for valid expressions |
605 | +#: ../qml/utils/dateutils.js:69 |
606 | +msgid "ddd, h:mm AP" |
607 | +msgstr "dddd,AP h:mm" |
608 | + |
609 | +#: ../qml/utils/dateutils.js:76 |
610 | +msgid "A few seconds ago..." |
611 | +msgstr "刚刚" |
612 | + |
613 | +#: ../qml/utils/dateutils.js:79 |
614 | +#, qt-format |
615 | +msgid "%1 minute ago" |
616 | +msgid_plural "%1 minutes ago" |
617 | +msgstr[0] "%1 分钟前" |
618 | + |
619 | +#: ../qml/utils/dateutils.js:83 |
620 | +#, qt-format |
621 | +msgid "%1 hour ago" |
622 | +msgid_plural "%1 hours ago" |
623 | +msgstr[0] "%1 小时前" |
624 | + |
625 | +#: ../qml/utils/dateutils.js:89 |
626 | +#, qt-format |
627 | +msgid "%1 day ago" |
628 | +msgid_plural "%1 days ago" |
629 | +msgstr[0] "%1 天前" |
630 | + |
631 | +#: shorts.desktop.in.in.h:2 |
632 | +msgid "shorts;rss;reader;" |
633 | +msgstr "简讯;rss;聚合;阅读;" |
634 | |
635 | === removed file 'shorts/po/zh_CN.po' |
636 | --- shorts/po/zh_CN.po 2016-03-24 06:05:40 +0000 |
637 | +++ shorts/po/zh_CN.po 1970-01-01 00:00:00 +0000 |
638 | @@ -1,458 +0,0 @@ |
639 | -# Chinese (Simplified) translation for ubuntu-rssreader-app |
640 | -# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 |
641 | -# This file is distributed under the same license as the ubuntu-rssreader-app package. |
642 | -# FIRST AUTHOR <EMAIL@ADDRESS>, 2013. |
643 | -# |
644 | -msgid "" |
645 | -msgstr "" |
646 | -"Project-Id-Version: ubuntu-rssreader-app\n" |
647 | -"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" |
648 | -"POT-Creation-Date: 2016-03-11 20:54+0800\n" |
649 | -"PO-Revision-Date: 2015-06-29 01:52+0000\n" |
650 | -"Last-Translator: Ian Li <Unknown>\n" |
651 | -"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n" |
652 | -"MIME-Version: 1.0\n" |
653 | -"Content-Type: text/plain; charset=UTF-8\n" |
654 | -"Content-Transfer-Encoding: 8bit\n" |
655 | -"Plural-Forms: nplurals=1; plural=0;\n" |
656 | -"X-Launchpad-Export-Date: 2016-03-24 06:05+0000\n" |
657 | -"X-Generator: Launchpad (build 17958)\n" |
658 | - |
659 | -#: ../qml/components/ArticleViewItem.qml:120 |
660 | -msgid "Select article" |
661 | -msgstr "选择文章" |
662 | - |
663 | -#: ../qml/components/ReadingOptions.qml:39 |
664 | -msgid "Dark" |
665 | -msgstr "深色" |
666 | - |
667 | -#: ../qml/components/ReadingOptions.qml:46 |
668 | -msgid "Light" |
669 | -msgstr "浅色" |
670 | - |
671 | -#: ../qml/components/ReadingOptions.qml:96 |
672 | -msgid "Small" |
673 | -msgstr "小" |
674 | - |
675 | -#: ../qml/components/ReadingOptions.qml:98 |
676 | -msgid "Normal" |
677 | -msgstr "" |
678 | - |
679 | -#: ../qml/components/ReadingOptions.qml:99 |
680 | -msgid "Large" |
681 | -msgstr "大" |
682 | - |
683 | -#: ../qml/content/ImportFeeds.qml:30 |
684 | -msgid "Import Feeds" |
685 | -msgstr "" |
686 | - |
687 | -#: ../qml/content/ImportFeeds.qml:42 ../qml/pages/TopicManagement.qml:258 |
688 | -msgid "Confirm" |
689 | -msgstr "确认" |
690 | - |
691 | -#: ../qml/content/ImportFeeds.qml:305 |
692 | -msgid "Please select an opml file" |
693 | -msgstr "" |
694 | - |
695 | -#: ../qml/content/ImportFeeds.qml:310 |
696 | -msgid "Open" |
697 | -msgstr "" |
698 | - |
699 | -#: ../qml/content/ImportFeeds.qml:293 |
700 | -msgid "" |
701 | -"Attention please, before importing opml file, Shorts only support one opml " |
702 | -"structure. <br><br>" |
703 | -msgstr "" |
704 | - |
705 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:30 ../qml/pages/AppendFeedPage.qml:31 |
706 | -#: ../qml/shorts-app.qml:265 ../qml/shorts-app.qml:403 |
707 | -#: ../qml/shorts-app.qml:411 |
708 | -msgid "Add feeds" |
709 | -msgstr "添加信息源" |
710 | - |
711 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:94 |
712 | -#: ../qml/pages/AppendFeedPage.qml:137 |
713 | -msgid "Type a keyword or URL" |
714 | -msgstr "请输入关键字或网址" |
715 | - |
716 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:149 |
717 | -msgid "Feed Title:" |
718 | -msgstr "" |
719 | - |
720 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:157 |
721 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:172 |
722 | -msgid "No data" |
723 | -msgstr "" |
724 | - |
725 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:164 |
726 | -msgid "Feed Description:" |
727 | -msgstr "" |
728 | - |
729 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:197 |
730 | -#: ../qml/pages/AppendFeedPage.qml:243 ../qml/pages/CreateTopicPage.qml:38 |
731 | -#: ../qml/pages/TopicManagement.qml:239 ../qml/shorts-app.qml:494 |
732 | -msgid "Cancel" |
733 | -msgstr "取消" |
734 | - |
735 | -#: ../qml/nongoogle/AppendNGFeedPage.qml:230 |
736 | -#: ../qml/pages/AppendFeedPage.qml:276 |
737 | -msgid "Next" |
738 | -msgstr "下一项" |
739 | - |
740 | -#: ../qml/pages/AppendFeedPage.qml:69 |
741 | -msgid "Failed to perform a feed search by keyword" |
742 | -msgstr "暂时搜索不到有关该关键词的信息" |
743 | - |
744 | -#: ../qml/pages/AppendFeedPage.qml:70 ../qml/pages/AppendFeedPage.qml:101 |
745 | -msgid "Search failed" |
746 | -msgstr "哎哟,好像除了点问题。。" |
747 | - |
748 | -#: ../qml/pages/AppendFeedPage.qml:100 |
749 | -msgid "Failed to perform a feed search by URL" |
750 | -msgstr "暂时搜索不到有关该网址的信息" |
751 | - |
752 | -#: ../qml/pages/AppendFeedPage.qml:185 |
753 | -msgid "Search results" |
754 | -msgstr "搜索结果" |
755 | - |
756 | -#: ../qml/pages/AppendFeedPage.qml:305 ../qml/pages/CreateTopicPage.qml:181 |
757 | -msgid "No feeds" |
758 | -msgstr "当前没有信息源" |
759 | - |
760 | -#: ../qml/pages/ArticleViewPage.qml:47 |
761 | -msgid "Save" |
762 | -msgstr "保存" |
763 | - |
764 | -#: ../qml/pages/ArticleViewPage.qml:47 |
765 | -msgid "Remove" |
766 | -msgstr "移除" |
767 | - |
768 | -#: ../qml/pages/ArticleViewPage.qml:60 |
769 | -msgid "Options" |
770 | -msgstr "选项" |
771 | - |
772 | -#: ../qml/pages/ArticleViewPage.qml:68 |
773 | -msgid "Open site" |
774 | -msgstr "打开网站" |
775 | - |
776 | -#: ../qml/pages/ArticleViewPage.qml:76 |
777 | -msgid "Share..." |
778 | -msgstr "" |
779 | - |
780 | -#: ../qml/pages/ChooseTopicPage.qml:13 |
781 | -msgid "Choose topic" |
782 | -msgstr "请选择话题" |
783 | - |
784 | -#: ../qml/pages/ChooseTopicPage.qml:77 |
785 | -msgid "Add your new feeds to a topic" |
786 | -msgstr "请添加您的信息源到某个话题中" |
787 | - |
788 | -#: ../qml/pages/ChooseTopicPage.qml:88 |
789 | -msgid " + New topic" |
790 | -msgstr " + 添加新话题" |
791 | - |
792 | -#: ../qml/pages/ChooseTopicPage.qml:108 ../qml/pages/CreateTopicPage.qml:77 |
793 | -msgid "A topic with this name already exists" |
794 | -msgstr "该话题已经存在" |
795 | - |
796 | -#: ../qml/pages/ChooseTopicPage.qml:109 ../qml/pages/ChooseTopicPage.qml:122 |
797 | -#: ../qml/pages/CreateTopicPage.qml:66 ../qml/pages/CreateTopicPage.qml:78 |
798 | -msgid "Warning" |
799 | -msgstr "提示" |
800 | - |
801 | -#: ../qml/pages/ChooseTopicPage.qml:121 ../qml/pages/CreateTopicPage.qml:65 |
802 | -msgid "Topic name can't contain only whitespaces" |
803 | -msgstr "请不要在话题中包含空格" |
804 | - |
805 | -#: ../qml/pages/CreateTopicPage.qml:12 |
806 | -msgid "Create new topic" |
807 | -msgstr "创建一个新的话题" |
808 | - |
809 | -#: ../qml/pages/CreateTopicPage.qml:56 ../qml/pages/TopicManagement.qml:92 |
810 | -msgid "Add topic" |
811 | -msgstr "添加话题" |
812 | - |
813 | -#: ../qml/pages/CreateTopicPage.qml:126 |
814 | -msgid "Type topic name" |
815 | -msgstr "请输入话题名称" |
816 | - |
817 | -#: ../qml/pages/CreateTopicPage.qml:142 |
818 | -msgid "Select feeds (optional)" |
819 | -msgstr "请选择信息源" |
820 | - |
821 | -#: ../qml/pages/EditFeedPage.qml:12 |
822 | -msgid "Edit Feed" |
823 | -msgstr "编辑信息源" |
824 | - |
825 | -#: ../qml/pages/EditFeedPage.qml:19 |
826 | -msgid "Done" |
827 | -msgstr "完成" |
828 | - |
829 | -#: ../qml/pages/EditFeedPage.qml:82 |
830 | -msgid "Title: " |
831 | -msgstr "标题: " |
832 | - |
833 | -#: ../qml/pages/EditFeedPage.qml:103 |
834 | -msgid "URL: " |
835 | -msgstr "地址: " |
836 | - |
837 | -#: ../qml/pages/EditFeedPage.qml:120 |
838 | -msgid "Topic: " |
839 | -msgstr "话题: " |
840 | - |
841 | -#: ../qml/pages/PageHelp.qml:15 |
842 | -msgid "Welcome to Shorts" |
843 | -msgstr "" |
844 | - |
845 | -#: ../qml/pages/PageHelp.qml:17 |
846 | -msgid "View Articles" |
847 | -msgstr "" |
848 | - |
849 | -#: ../qml/pages/PageHelp.qml:19 |
850 | -msgid "Search RSS" |
851 | -msgstr "" |
852 | - |
853 | -#: ../qml/pages/PageHelp.qml:21 |
854 | -msgid "Manage topics and feeds" |
855 | -msgstr "" |
856 | - |
857 | -#: ../qml/pages/PageHelp.qml:23 |
858 | -msgid "Location" |
859 | -msgstr "" |
860 | - |
861 | -#: ../qml/pages/PageHelp.qml:25 |
862 | -msgid "Enjoy" |
863 | -msgstr "" |
864 | - |
865 | -#: ../qml/pages/PageHelp.qml:105 |
866 | -msgid "Shorts is an RSS reader app developed by Canonical & Ubuntu Comunity." |
867 | -msgstr "" |
868 | - |
869 | -#: ../qml/pages/PageHelp.qml:110 |
870 | -msgid "" |
871 | -"Shorts provides most primary features which also can be seen in other RSS " |
872 | -"reader apps, with a beautiful Ubuntu style user interface." |
873 | -msgstr "" |
874 | - |
875 | -#: ../qml/pages/PageHelp.qml:117 |
876 | -msgid "Swipe left to continue." |
877 | -msgstr "" |
878 | - |
879 | -#: ../qml/pages/PageHelp.qml:136 |
880 | -msgid "Scroll left/right in grid mode or scroll up/down in list mode." |
881 | -msgstr "" |
882 | - |
883 | -#: ../qml/pages/PageHelp.qml:163 |
884 | -msgid "" |
885 | -"Swipe up will enter this search page, just type any simple words, or paste a " |
886 | -"link." |
887 | -msgstr "" |
888 | - |
889 | -#: ../qml/pages/PageHelp.qml:190 |
890 | -msgid "" |
891 | -"Every feed must belong to one topic, swipe one item to delete feed/topic." |
892 | -msgstr "" |
893 | - |
894 | -#: ../qml/pages/PageHelp.qml:223 |
895 | -msgid "Seems you are living in: " |
896 | -msgstr "" |
897 | - |
898 | -#: ../qml/pages/PageHelp.qml:232 |
899 | -msgid "" |
900 | -"Some regions/countries(e.g. China) may block Google service, if you're " |
901 | -"living there or plan to go there, we suggest to trun off the build-in Google " |
902 | -"RSS service in settings page, or nothing you should care." |
903 | -msgstr "" |
904 | - |
905 | -#: ../qml/pages/PageHelp.qml:239 |
906 | -msgid "" |
907 | -"We detect that you're living in some region/country(e.g. China) which blocks " |
908 | -"Google service, so Shorts disable the build-in Google RSS service by " |
909 | -"default. You still can turn it on here or in settings page." |
910 | -msgstr "" |
911 | - |
912 | -#: ../qml/pages/PageHelp.qml:250 |
913 | -msgid "Use Google RSS engine: " |
914 | -msgstr "" |
915 | - |
916 | -#: ../qml/pages/PageHelp.qml:287 |
917 | -msgid "Enjoy !" |
918 | -msgstr "" |
919 | - |
920 | -#: ../qml/pages/PageHelp.qml:297 |
921 | -msgid "Do not show this help page again " |
922 | -msgstr "" |
923 | - |
924 | -#: ../qml/pages/PageHelp.qml:316 |
925 | -msgid "Start using Shorts !" |
926 | -msgstr "" |
927 | - |
928 | -#: ../qml/pages/PageHelp.qml:340 |
929 | -msgid "Skip" |
930 | -msgstr "" |
931 | - |
932 | -#: ../qml/pages/PageInfo.qml:10 |
933 | -msgid "About Shorts" |
934 | -msgstr "" |
935 | - |
936 | -#: ../qml/pages/PageInfo.qml:39 |
937 | -msgid "Author" |
938 | -msgstr "" |
939 | - |
940 | -#: ../qml/pages/PageInfo.qml:53 |
941 | -msgid "Copyleft" |
942 | -msgstr "" |
943 | - |
944 | -#: ../qml/pages/PageInfo.qml:57 |
945 | -msgid "License with GPLv3" |
946 | -msgstr "" |
947 | - |
948 | -#: ../qml/pages/PageInfo.qml:62 |
949 | -msgid "" |
950 | -"Ubuntu Shorts App is the official rss reader app for Ubuntu Touch. We follow " |
951 | -"an open source model where the code is available to anyone to branch and " |
952 | -"hack on. The ubuntu shorts app follows a test driven development (TDD) where " |
953 | -"tests are written in parallel to feature implementation to help spot " |
954 | -"regressions easier." |
955 | -msgstr "" |
956 | - |
957 | -#: ../qml/pages/PageInfo.qml:68 |
958 | -msgid "Click here to report a bug" |
959 | -msgstr "" |
960 | - |
961 | -#: ../qml/pages/PageSettings.qml:9 ../qml/shorts-app.qml:249 |
962 | -msgid "Settings" |
963 | -msgstr "" |
964 | - |
965 | -#: ../qml/pages/PageSettings.qml:15 |
966 | -msgid "Help" |
967 | -msgstr "" |
968 | - |
969 | -#: ../qml/pages/PageSettings.qml:20 |
970 | -msgid "Info" |
971 | -msgstr "" |
972 | - |
973 | -#: ../qml/pages/PageSettings.qml:51 |
974 | -msgid "" |
975 | -"Some special regions/countries block Google service, we suggest to turn off " |
976 | -"the switch below if living in there." |
977 | -msgstr "" |
978 | - |
979 | -#: ../qml/pages/PageSettings.qml:59 |
980 | -msgid "Use Google Search: " |
981 | -msgstr "" |
982 | - |
983 | -#: ../qml/pages/PageSettings.qml:84 |
984 | -msgid "" |
985 | -"For those users, who want to import their RSS feeds from other sources, " |
986 | -"please press the button below." |
987 | -msgstr "" |
988 | - |
989 | -#: ../qml/pages/PageSettings.qml:94 |
990 | -msgid "Import OPML" |
991 | -msgstr "" |
992 | - |
993 | -#: ../qml/pages/TopicManagement.qml:13 ../qml/shorts-app.qml:229 |
994 | -msgid "Edit topics" |
995 | -msgstr "编辑话题" |
996 | - |
997 | -#: ../qml/pages/TopicManagement.qml:274 |
998 | -msgid "Add Feed" |
999 | -msgstr "添加信息源" |
1000 | - |
1001 | -#: ../qml/shorts-app.qml:196 |
1002 | -msgid "Refresh" |
1003 | -msgstr "刷新" |
1004 | - |
1005 | -#: ../qml/shorts-app.qml:203 |
1006 | -msgid "Grid View" |
1007 | -msgstr "网格视图" |
1008 | - |
1009 | -#: ../qml/shorts-app.qml:203 |
1010 | -msgid "List view" |
1011 | -msgstr "列表视图" |
1012 | - |
1013 | -#: ../qml/shorts-app.qml:239 |
1014 | -msgid "Disable night mode" |
1015 | -msgstr "" |
1016 | - |
1017 | -#: ../qml/shorts-app.qml:239 |
1018 | -msgid "Enable night mode" |
1019 | -msgstr "" |
1020 | - |
1021 | -#: ../qml/shorts-app.qml:334 |
1022 | -msgid "Saved" |
1023 | -msgstr "已保存" |
1024 | - |
1025 | -#: ../qml/shorts-app.qml:342 shorts.desktop.in.in.h:1 |
1026 | -msgid "Shorts" |
1027 | -msgstr "摘要阅读" |
1028 | - |
1029 | -#: ../qml/shorts-app.qml:486 |
1030 | -msgid "Checking for new articles" |
1031 | -msgstr "正在查询新的文章" |
1032 | - |
1033 | -#: ../qml/shorts-app.qml:510 |
1034 | -msgid "Perhaps some of the channels have not been updated." |
1035 | -msgstr "部分频道内容可能未更新。" |
1036 | - |
1037 | -#: ../qml/shorts-app.qml:511 |
1038 | -msgid "Errors occurred during the update" |
1039 | -msgstr "更新过程中出错" |
1040 | - |
1041 | -#: ../qml/shorts-app.qml:525 |
1042 | -msgid "Ok" |
1043 | -msgstr "确认" |
1044 | - |
1045 | -#: ../qml/tabs/BaseTab.qml:153 |
1046 | -msgid "There are no articles to show" |
1047 | -msgstr "当前没有文章可显示" |
1048 | - |
1049 | -#. TRANSLATORS: this is a time formatting string, |
1050 | -#. see http://qt-project.org/doc/qt-5.0/qtqml/qml-qtquick2-date.html#details for valid expressions |
1051 | -#: ../qml/utils/dateutils.js:39 |
1052 | -msgid "MMMM d" |
1053 | -msgstr "M 月 d 日" |
1054 | - |
1055 | -#: ../qml/utils/dateutils.js:54 |
1056 | -#, qt-format |
1057 | -msgid "Yesterday at %1" |
1058 | -msgstr "昨天 %1" |
1059 | - |
1060 | -#. TRANSLATORS: this is a time formatting string, |
1061 | -#. see http://qt-project.org/doc/qt-5.0/qtqml/qml-qtquick2-date.html#details for valid expressions |
1062 | -#: ../qml/utils/dateutils.js:57 |
1063 | -msgid "h:mm AP" |
1064 | -msgstr "AP h:mm" |
1065 | - |
1066 | -#. TRANSLATORS: this is a time formatting string, |
1067 | -#. see http://qt-project.org/doc/qt-5.0/qtqml/qml-qtquick2-date.html#details for valid expressions |
1068 | -#: ../qml/utils/dateutils.js:69 |
1069 | -msgid "ddd, h:mm AP" |
1070 | -msgstr "dddd,AP h:mm" |
1071 | - |
1072 | -#: ../qml/utils/dateutils.js:76 |
1073 | -msgid "A few seconds ago..." |
1074 | -msgstr "刚刚" |
1075 | - |
1076 | -#: ../qml/utils/dateutils.js:79 |
1077 | -#, qt-format |
1078 | -msgid "%1 minute ago" |
1079 | -msgid_plural "%1 minutes ago" |
1080 | -msgstr[0] "%1 分钟前" |
1081 | - |
1082 | -#: ../qml/utils/dateutils.js:83 |
1083 | -#, qt-format |
1084 | -msgid "%1 hour ago" |
1085 | -msgid_plural "%1 hours ago" |
1086 | -msgstr[0] "%1 小时前" |
1087 | - |
1088 | -#: ../qml/utils/dateutils.js:89 |
1089 | -#, qt-format |
1090 | -msgid "%1 day ago" |
1091 | -msgid_plural "%1 days ago" |
1092 | -msgstr[0] "%1 天前" |
1093 | - |
1094 | -#: shorts.desktop.in.in.h:2 |
1095 | -msgid "shorts;rss;reader;" |
1096 | -msgstr "简讯;rss;聚合;阅读;" |
1097 | |
1098 | === modified file 'shorts/qml/components/ArticleViewItem.qml' |
1099 | --- shorts/qml/components/ArticleViewItem.qml 2016-01-16 10:55:38 +0000 |
1100 | +++ shorts/qml/components/ArticleViewItem.qml 2016-06-15 16:13:25 +0000 |
1101 | @@ -59,6 +59,11 @@ |
1102 | } |
1103 | } |
1104 | |
1105 | + function escape2Html(str) { |
1106 | + var arrEntities={'lt':'<','gt':'>','nbsp':' ','amp':'&','quot':'"'}; |
1107 | + return str.replace(/&(lt|gt|nbsp|amp|quot);/ig,function(all,t){return arrEntities[t];}); |
1108 | + } |
1109 | + |
1110 | |
1111 | ////////////////////////////////////////////// a listview to show the RSS content |
1112 | ListView { |
1113 | @@ -195,7 +200,7 @@ |
1114 | } |
1115 | |
1116 | Label { |
1117 | - text: model.content |
1118 | + text: escape2Html(model.content) |
1119 | |
1120 | fontSize: { |
1121 | switch(rssListview.contentFontSize) { |
1122 | |
1123 | === modified file 'shorts/qml/content/ContentPickerDialog.qml' |
1124 | --- shorts/qml/content/ContentPickerDialog.qml 2016-01-10 09:04:00 +0000 |
1125 | +++ shorts/qml/content/ContentPickerDialog.qml 2016-06-15 16:13:25 +0000 |
1126 | @@ -29,6 +29,10 @@ |
1127 | id: picker |
1128 | visible: false |
1129 | |
1130 | + header: PageHeader { |
1131 | + visible: false |
1132 | + } |
1133 | + |
1134 | property var pickerParent |
1135 | |
1136 | ContentPeerPicker { |
1137 | |
1138 | === modified file 'shorts/qml/content/ImportFeeds.qml' |
1139 | --- shorts/qml/content/ImportFeeds.qml 2016-01-14 15:35:31 +0000 |
1140 | +++ shorts/qml/content/ImportFeeds.qml 2016-06-15 16:13:25 +0000 |
1141 | @@ -45,7 +45,9 @@ |
1142 | DB.importOPMLobject(repeaterFeedList.opmlList) |
1143 | mainView.reloadViews() |
1144 | pageStack.pop() |
1145 | + pageStack.pop() |
1146 | mainView.refresh() |
1147 | +// print ("repeaterFeedList.opmlList: ", JSON.stringify(repeaterFeedList.opmlList[0])) |
1148 | } |
1149 | } |
1150 | |
1151 | @@ -147,6 +149,7 @@ |
1152 | |
1153 | ListItem.Empty { |
1154 | id: liStandardRoot |
1155 | + height: units.gu(6.5) |
1156 | |
1157 | property var opmlRoot: repeaterFeedList.opmlList == undefined ? |
1158 | undefined : repeaterFeedList.opmlList[index] |
1159 | @@ -172,6 +175,7 @@ |
1160 | |
1161 | CheckBox { |
1162 | id: checkboxRoot |
1163 | + anchors.verticalCenter: parent.verticalCenter |
1164 | } |
1165 | |
1166 | Label{ |
1167 | @@ -217,7 +221,8 @@ |
1168 | Repeater { |
1169 | id: repeaterFeedsChildren |
1170 | model: liStandardRoot.opmlRoot == undefined ? |
1171 | - "" : liStandardRoot.opmlRoot.children |
1172 | +// "" : liStandardRoot.opmlRoot.children |
1173 | + "" : liStandardRoot.opmlRoot.outline |
1174 | |
1175 | ListItem.Standard { |
1176 | id: listitemFeed |
1177 | @@ -227,7 +232,10 @@ |
1178 | // height: visible ? units.gu(6) : 0 |
1179 | |
1180 | property var opmlFeed: liStandardRoot.opmlRoot == undefined ? |
1181 | - undefined : liStandardRoot.opmlRoot.children[index] |
1182 | + undefined : liStandardRoot.opmlRoot.outline[index] |
1183 | +// undefined : liStandardRoot.opmlRoot.children[index] |
1184 | +// undefined : (liStandardRoot.opmlRoot.outline[index] == undefined ? |
1185 | +// liStandardRoot.opmlRoot.outline : liStandardRoot.opmlRoot.outline[index]) |
1186 | |
1187 | Connections { |
1188 | target: liStandardRoot |
1189 | |
1190 | === modified file 'shorts/qml/content/OpmlParser.qml' |
1191 | --- shorts/qml/content/OpmlParser.qml 2016-01-10 09:04:00 +0000 |
1192 | +++ shorts/qml/content/OpmlParser.qml 2016-06-15 16:13:25 +0000 |
1193 | @@ -21,16 +21,39 @@ |
1194 | |
1195 | import QtQuick.XmlListModel 2.0 |
1196 | |
1197 | -import "../utils/databasemodule_v2.js" as DB |
1198 | -//import "../." |
1199 | |
1200 | Item { |
1201 | id: opmlParser |
1202 | |
1203 | property string opmlPath: "" |
1204 | + onOpmlPathChanged: { |
1205 | + utilities.loadOpml(opmlPath) |
1206 | + } |
1207 | |
1208 | signal parseFinished(var opml) |
1209 | |
1210 | + Connections { |
1211 | + target: utilities |
1212 | + |
1213 | + onSigOpmlJsom: { |
1214 | +// print("opml json: ", JSON.stringify(result)) |
1215 | +// print("opml json: ", /*result.opml.body.outline[0].outline[0].xmlUrl,*/ JSON.stringify(result.opml.body.outline[0].outline)) |
1216 | + |
1217 | + // if only one feed in a folder, there's no JS array in it, only one obj, so I add an array in a folder, make the structure compatible |
1218 | + for (var i=0; i<result.opml.body.outline.length; i++) { |
1219 | + var outLine = result.opml.body.outline[i] |
1220 | + if (result.opml.body.outline[i].outline[0] == undefined) { |
1221 | + var tmpobj = result.opml.body.outline[i].outline |
1222 | + var tmparr = new Array |
1223 | + tmparr.push(tmpobj) |
1224 | + result.opml.body.outline[i].outline = tmparr |
1225 | + } |
1226 | + } |
1227 | + |
1228 | + parseFinished(result.opml.body.outline) |
1229 | + } |
1230 | + } |
1231 | + |
1232 | XmlListModel { |
1233 | id: modelOpml |
1234 | property string subTitle |
1235 | @@ -91,23 +114,23 @@ |
1236 | } |
1237 | |
1238 | onStatusChanged: { |
1239 | - console.log("model status:", status) |
1240 | - if (status == XmlListModel.Ready) { |
1241 | - if (!subTitle) { |
1242 | - allRootsCount = count |
1243 | - // get all root object |
1244 | - getAllRootObj() |
1245 | - } |
1246 | - else { |
1247 | - // load children object one by one |
1248 | -// console.log("children objs: ", JSON.stringify(opmlObj)) |
1249 | -// console.log("model count: ", count) |
1250 | - getChildObjsFromOneRoot() |
1251 | - } |
1252 | - } |
1253 | - else if (status == XmlListModel.Error) { |
1254 | - console.log("XmlListModel.Error: ", errorString()) |
1255 | - } |
1256 | +// console.log("model status:", status) |
1257 | +// if (status == XmlListModel.Ready) { |
1258 | +// if (!subTitle) { |
1259 | +// allRootsCount = count |
1260 | +// // get all root object |
1261 | +// getAllRootObj() |
1262 | +// } |
1263 | +// else { |
1264 | +// // load children object one by one |
1265 | +//// console.log("children objs: ", JSON.stringify(opmlObj)) |
1266 | +//// console.log("model count: ", count) |
1267 | +// getChildObjsFromOneRoot() |
1268 | +// } |
1269 | +// } |
1270 | +// else if (status == XmlListModel.Error) { |
1271 | +// console.log("XmlListModel.Error: ", errorString()) |
1272 | +// } |
1273 | } |
1274 | |
1275 | query: subTitle ? "/opml/body/outline[@text='" + subTitle + "']/outline": "/opml/body/outline" |
1276 | |
1277 | === modified file 'shorts/qml/nongoogle/AppendNGFeedPage.qml' |
1278 | --- shorts/qml/nongoogle/AppendNGFeedPage.qml 2016-01-04 11:13:30 +0000 |
1279 | +++ shorts/qml/nongoogle/AppendNGFeedPage.qml 2016-06-15 16:13:25 +0000 |
1280 | @@ -1,5 +1,5 @@ |
1281 | /* |
1282 | - * Copyright (C) 2013, 2014 |
1283 | + * Copyright (C) 2013, 2014, 2015, 2016 |
1284 | * |
1285 | * This program is free software; you can redistribute it and/or modify |
1286 | * it under the terms of the GNU General Public License as published by |
1287 | @@ -24,9 +24,9 @@ |
1288 | import "../." |
1289 | |
1290 | Page { |
1291 | - id: appendFeedPage |
1292 | + id: appendFeedPageNG |
1293 | |
1294 | - objectName: "appendfeedpage" |
1295 | + objectName: "appendFeedPageNG" |
1296 | title: i18n.tr("Add feeds") |
1297 | flickable: null |
1298 | visible: false |
1299 | @@ -58,15 +58,20 @@ |
1300 | id: xmlFeedApi |
1301 | |
1302 | onLoadResult: { |
1303 | + if (mainStack.currentPage != appendFeedPageNG) { return } |
1304 | + |
1305 | if (!result.rss) { |
1306 | print("onLoadResult failed") |
1307 | } |
1308 | else { |
1309 | - var f = result.rss.channel |
1310 | + var e = result.rss.channel |
1311 | |
1312 | - feedDesc = f.description ? (f.description["#text"] ? f.description["#text"] : f.description ) : "" |
1313 | - feedTitle = f.title ? (f.title["#text"] ? f.title["#text"] : f.title ) : "" |
1314 | - feedLink = f.link ? (f.link["#text"] ? f.link["#text"] : f.link) : "" |
1315 | + try { |
1316 | + feedDesc = e.description == undefined ? "" : e.description["#text"] == undefined ? e.description : e.description["#text"] |
1317 | + feedTitle = e.title == undefined ? "" : e.title["#text"] == undefined ? e.title : e.title["#text"] |
1318 | + feedLink = e.link == undefined ? "" : e.link["#text"] == undefined ? e.link : e.link["#text"] |
1319 | + } |
1320 | + catch (err) { ; } |
1321 | feedObj = { |
1322 | "url" : feedUrl, |
1323 | "title" : feedTitle, |
1324 | @@ -129,8 +134,8 @@ |
1325 | var isUrlEntered = (userInput.indexOf(" ") === -1 && userInput.indexOf(".") !== -1) |
1326 | |
1327 | if (isUrlEntered) { |
1328 | - if (userInput.indexOf("http://") !== 0) |
1329 | - {userInput = "http://" + userInput} |
1330 | +// if (userInput.indexOf("http://") !== 0) |
1331 | +// {userInput = "http://" + userInput} |
1332 | feedUrl = userInput |
1333 | xmlFeedApi.loadFeed(userInput) |
1334 | } |
1335 | |
1336 | === modified file 'shorts/qml/nongoogle/XmlNetwork.qml' |
1337 | --- shorts/qml/nongoogle/XmlNetwork.qml 2016-03-11 13:04:57 +0000 |
1338 | +++ shorts/qml/nongoogle/XmlNetwork.qml 2016-06-15 16:13:25 +0000 |
1339 | @@ -1,53 +1,66 @@ |
1340 | import QtQuick 2.4 |
1341 | -import "../utils/xml2json.js" as XJ |
1342 | |
1343 | QtObject { |
1344 | id: rootObject |
1345 | |
1346 | - property bool inProgress: __doc != null |
1347 | +// property bool inProgress: __doc != null |
1348 | + property bool inProgress: false |
1349 | |
1350 | signal findResult(var result) |
1351 | signal loadResult(var result) |
1352 | |
1353 | property var __doc: null |
1354 | |
1355 | + property variant connObj: Connections { |
1356 | + id: connUtilities |
1357 | + target: utilities |
1358 | + |
1359 | + onSigResult: { |
1360 | + inProgress = false |
1361 | + loadResult(result) |
1362 | + } |
1363 | + } |
1364 | + |
1365 | /* Load feed by URL. |
1366 | */ |
1367 | - function loadFeed(feedUrl, num) { |
1368 | - abort(true) |
1369 | - |
1370 | - if (num) |
1371 | - num = Math.min(num, 100) |
1372 | - else num = 50 |
1373 | - |
1374 | - __doc = new XMLHttpRequest() |
1375 | - var doc = __doc |
1376 | - |
1377 | - doc.onreadystatechange = function() { |
1378 | - |
1379 | -// print("xmlnetwork onreadystatechange: ", doc.readyState, doc.status, feedUrl) |
1380 | - if (doc.readyState === XMLHttpRequest.DONE) { |
1381 | - |
1382 | - var resObj |
1383 | -// print ("status & text: ", doc.status, doc.statusText, doc.responseText) |
1384 | - if (doc.status == 200) { |
1385 | - resObj = utilities.xmlToJson(doc.responseText) |
1386 | -// resObj = utilities.xmlToJson(doc.responseText) |
1387 | -// var x2js = new XJ.X2JS(); |
1388 | -// resObj = XJ.xmlToJSON.parseString(doc.responseText) //x2js.xml_str2json( doc.responseText ); |
1389 | - } else { // Error |
1390 | - resObj = {"responseDetails" : doc.statusText, |
1391 | - "responseStatus" : doc.status} |
1392 | - } |
1393 | - |
1394 | - print ("resObj: ", resObj.rss ) |
1395 | - __doc = null |
1396 | - loadResult(resObj) |
1397 | - } |
1398 | - } |
1399 | - |
1400 | - doc.open("GET", feedUrl, true); |
1401 | - doc.send(); |
1402 | + function loadFeed(feedUrl/*, num*/) { |
1403 | +// connUtilities.target = utilities |
1404 | +// abort(true) |
1405 | + inProgress = true |
1406 | + utilities.loadFeed(feedUrl) |
1407 | + |
1408 | +// if (num) |
1409 | +// num = Math.min(num, 100) |
1410 | +// else num = 50 |
1411 | + |
1412 | +// __doc = new XMLHttpRequest() |
1413 | +// var doc = __doc |
1414 | + |
1415 | +// doc.onreadystatechange = function() { |
1416 | + |
1417 | +//// print("xmlnetwork onreadystatechange: ", doc.readyState, doc.status, feedUrl) |
1418 | +// if (doc.readyState === XMLHttpRequest.DONE) { |
1419 | + |
1420 | +// var resObj |
1421 | +//// print ("status & text: ", doc.status, doc.statusText, doc.responseText) |
1422 | +// if (doc.status == 200) { |
1423 | +// resObj = utilities.xmlToJson(doc.responseText) |
1424 | +//// resObj = utilities.xmlToJson(doc.responseText) |
1425 | +//// var x2js = new XJ.X2JS(); |
1426 | +//// resObj = XJ.xmlToJSON.parseString(doc.responseText) //x2js.xml_str2json( doc.responseText ); |
1427 | +// } else { // Error |
1428 | +// resObj = {"responseDetails" : doc.statusText, |
1429 | +// "responseStatus" : doc.status} |
1430 | +// } |
1431 | + |
1432 | +// print ("resObj: ", resObj.rss ) |
1433 | +// __doc = null |
1434 | +// loadResult(resObj) |
1435 | +// } |
1436 | +// } |
1437 | + |
1438 | +// doc.open("GET", feedUrl, true); |
1439 | +// doc.send(); |
1440 | } |
1441 | |
1442 | /* Param "isAbortOnly" used to preserve |
1443 | @@ -56,11 +69,13 @@ |
1444 | * additional recalculations. |
1445 | */ |
1446 | function abort(isAbortOnly) { |
1447 | - if (__doc != null) { |
1448 | - __doc.abort() |
1449 | - if (!isAbortOnly) |
1450 | - __doc = null |
1451 | - } |
1452 | +// if (__doc != null) { |
1453 | +// __doc.abort() |
1454 | +// if (!isAbortOnly) |
1455 | +// __doc = null |
1456 | +// } |
1457 | + |
1458 | + utilities.abort() |
1459 | } |
1460 | |
1461 | /* Return true if some kind of errors detected. |
1462 | |
1463 | === modified file 'shorts/qml/shorts-app.qml' |
1464 | --- shorts/qml/shorts-app.qml 2016-03-04 13:27:57 +0000 |
1465 | +++ shorts/qml/shorts-app.qml 2016-06-15 16:13:25 +0000 |
1466 | @@ -30,6 +30,8 @@ |
1467 | |
1468 | backgroundColor: "#F5F5F5" |
1469 | |
1470 | + property alias mainStack: pageStack |
1471 | + |
1472 | Component.onCompleted: { |
1473 | // show help page in first use |
1474 | if (optionsKeeper.needPopup) { |
1475 | |
1476 | === modified file 'shorts/qml/utils/databasemodule_v2.js' |
1477 | --- shorts/qml/utils/databasemodule_v2.js 2016-03-04 13:27:57 +0000 |
1478 | +++ shorts/qml/utils/databasemodule_v2.js 2016-06-15 16:13:25 +0000 |
1479 | @@ -703,20 +703,20 @@ |
1480 | // topic(tag) end, tagID is the unique id of a topic |
1481 | |
1482 | // insert feed start |
1483 | - for (var j=0; j<opml[i].children.length; j++) { |
1484 | - if (opml[i].children[j].isSelected) { |
1485 | + for (var j=0; j<opml[i].outline.length; j++) { |
1486 | + if (opml[i].outline[j].isSelected) { |
1487 | /* Check uniqueness. |
1488 | */ |
1489 | var feedID = -1 |
1490 | - var feedResult = tx.executeSql("SELECT * FROM feed WHERE source=?", [opml[i].children[j].xmlUrl]) |
1491 | + var feedResult = tx.executeSql("SELECT * FROM feed WHERE source=?", [opml[i].outline[j].xmlUrl]) |
1492 | if (feedResult.rows.length > 0) { |
1493 | - console.log("Database, importOPMLobject: already exist feed with source: ", opml[i].children[j].xmlUrl, "ID", feedResult.rows.item(0).id) |
1494 | + console.log("Database, importOPMLobject: already exist feed with source: ", opml[i].outline[j].xmlUrl, "ID", feedResult.rows.item(0).id) |
1495 | feedID = feedResult.rows.item(0).id |
1496 | } |
1497 | else { |
1498 | // insert feed |
1499 | feedResult = tx.executeSql('INSERT INTO feed (title, source) VALUES(?, ?)', |
1500 | - [opml[i].children[j].title , opml[i].children[j].xmlUrl]) |
1501 | + [opml[i].outline[j].title , opml[i].outline[j].xmlUrl]) |
1502 | feedID = feedResult.insertId |
1503 | console.log("Database, importOPMLobject: feed INSERT ID: ", feedID) |
1504 | } |
1505 | @@ -735,6 +735,8 @@ |
1506 | } |
1507 | } |
1508 | } |
1509 | + |
1510 | + |
1511 | } |
1512 | else { |
1513 | continue |
1514 | |
1515 | === modified file 'shorts/utilities.cpp' |
1516 | --- shorts/utilities.cpp 2016-03-11 13:04:57 +0000 |
1517 | +++ shorts/utilities.cpp 2016-06-15 16:13:25 +0000 |
1518 | @@ -4,16 +4,22 @@ |
1519 | Utilities::Utilities(QObject *parent) : |
1520 | QObject(parent) |
1521 | { |
1522 | -// qDebug() << "path: " << QDir::currentPath() ; |
1523 | -// QFile xmlFile("xml"); |
1524 | -// xmlFile.open(QIODevice::ReadOnly | QIODevice::Text); |
1525 | - |
1526 | -// qDebug() << "json: " << xmlToJson(QString(xmlFile.readAll())).size(); |
1527 | + _internalMgr = new QNetworkAccessManager(this); |
1528 | + _loadTimer = new QTimer(this); |
1529 | + _loadTimer->setSingleShot(true); |
1530 | } |
1531 | |
1532 | -QJsonObject Utilities::xmlToJson(const QString &xml) |
1533 | +QJsonObject Utilities::xmlToJson(const QByteArray &xml) |
1534 | { |
1535 | - QByteArray ba = xml.toLocal8Bit(); |
1536 | + // check if the input doc is an xml doc |
1537 | +// QString xmldoc = QString(xml); |
1538 | +// if (xmldoc.indexOf("<?xml") != 0) |
1539 | +// { |
1540 | +// return QJsonDocument::fromJson(QString('{"error":4, "errorString":"not xml doc"}').toLocal8Bit()).object(); |
1541 | +// } |
1542 | + |
1543 | +// QByteArray ba = xml.toLocal8Bit(); |
1544 | + QByteArray ba = xml; |
1545 | char* ch = ba.data(); |
1546 | std::string json = ""; |
1547 | try |
1548 | @@ -30,6 +36,62 @@ |
1549 | return QJsonDocument::fromJson(QString::fromStdString(json).toLocal8Bit()).object(); |
1550 | } |
1551 | |
1552 | +void Utilities::loadFeed(const QString &feedUrl) |
1553 | +{ |
1554 | + _loadTimer->stop(); |
1555 | + connect(_loadTimer, SIGNAL(timeout()), this, SLOT(_internalReplySlot())); |
1556 | + _loadTimer->start(20000); |
1557 | + _internalReply = this->_internalMgr->get(QNetworkRequest(QUrl(feedUrl))); |
1558 | + connect(_internalReply, SIGNAL(finished()), this, SLOT(_internalReplySlot())); |
1559 | + connect(_internalReply, SIGNAL(sslErrors(QList<QSslError>)), |
1560 | + this, SLOT(slotSslErrors(QList<QSslError>))); |
1561 | +} |
1562 | + |
1563 | +void Utilities::abort() |
1564 | +{ |
1565 | +// qDebug() << "abort0 " ; |
1566 | + _loadTimer->stop(); |
1567 | + if (this->_internalReply) |
1568 | + { |
1569 | +// qDebug() << "abort1 " ; |
1570 | + if (this->_internalReply->isRunning()) |
1571 | + { |
1572 | + this->_internalReply->abort(); |
1573 | +// qDebug() << "abort2 " ; |
1574 | + } |
1575 | + } |
1576 | +} |
1577 | + |
1578 | +void Utilities::_internalReplySlot() |
1579 | +{ |
1580 | + abort() ; |
1581 | + if (_internalReply->error() != QNetworkReply::NoError) |
1582 | + { |
1583 | + QString errString = '{"responseDetails": "pls check error in QNetworkReply::NetworkError","responseStatus":' |
1584 | + + QString::number(_internalReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()) + '}'; |
1585 | + emit QJsonDocument::fromJson(errString.toLocal8Bit()); |
1586 | + return ; |
1587 | + } |
1588 | + qDebug() << "HTTP status code: " << _internalReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() ; |
1589 | +// qDebug() << "redirect url? " << _internalReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); |
1590 | + if (_internalReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 301) |
1591 | + { |
1592 | + loadFeed(_internalReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl().toString()); |
1593 | + return ; |
1594 | + } |
1595 | +// qDebug() << "feed size: " << _internalReply->size() ; |
1596 | +// qDebug() << "feed detail: " << _internalReply->readAll() ; |
1597 | + QByteArray data = _internalReply->readAll(); |
1598 | +// emit sigResult(xmlToJson(QString(data))); |
1599 | + emit sigResult(xmlToJson(data)); |
1600 | +// qDebug() << "signal emitted. " ; |
1601 | +} |
1602 | + |
1603 | +void Utilities::slotSslErrors(QList<QSslError>) |
1604 | +{ |
1605 | + this->_internalReply->ignoreSslErrors(); |
1606 | +} |
1607 | + |
1608 | QStringList Utilities::htmlGetImg(const QString &html) |
1609 | { |
1610 | QRegExp imgTagRegex("\\<img[^\\>]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive); |
1611 | @@ -58,11 +120,23 @@ |
1612 | settings.setValue(key, value); |
1613 | } |
1614 | |
1615 | -// QJsonObject Utilities::test() |
1616 | -// { |
1617 | -// QFile xmlFile("xml"); |
1618 | -// xmlFile.open(QIODevice::ReadOnly | QIODevice::Text); |
1619 | -// |
1620 | -// QJsonObject obj = xmlToJson(QString(xmlFile.readAll())); |
1621 | -// return obj; |
1622 | -// } |
1623 | +void Utilities::loadOpml(const QString &opmlUrl) |
1624 | +{ |
1625 | + QString tmpUrl = opmlUrl ; |
1626 | + tmpUrl = tmpUrl.replace("file://", ""); |
1627 | + QFile *file=new QFile(tmpUrl); |
1628 | + bool isOpen = file->open(QIODevice::ReadOnly|QIODevice::Text); |
1629 | + if (!isOpen) |
1630 | + { |
1631 | + qDebug() << "error opening opml file ........" ; |
1632 | + return ; |
1633 | + } |
1634 | + |
1635 | + // get all data & convert to json |
1636 | + QByteArray opmldata = file->readAll(); |
1637 | + QString opmlJsonString = QString(QJsonDocument(xmlToJson(opmldata)).toJson()); |
1638 | + opmlJsonString = opmlJsonString.replace("@", ""); |
1639 | +// qDebug() << "after replace @: " << opmlJsonString ; |
1640 | + //QJsonDocument::fromJson(QString::fromStdString(json).toLocal8Bit()).object(); |
1641 | + emit sigOpmlJsom(QJsonDocument::fromJson(opmlJsonString.toLocal8Bit()).object()); |
1642 | +} |
1643 | |
1644 | === modified file 'shorts/utilities.h' |
1645 | --- shorts/utilities.h 2016-03-04 13:27:57 +0000 |
1646 | +++ shorts/utilities.h 2016-06-15 16:13:25 +0000 |
1647 | @@ -2,6 +2,7 @@ |
1648 | #define UTILITIES_H |
1649 | |
1650 | #include <QtCore> |
1651 | +#include <QtNetwork> |
1652 | |
1653 | class Utilities : public QObject |
1654 | { |
1655 | @@ -9,20 +10,38 @@ |
1656 | public: |
1657 | explicit Utilities(QObject *parent = 0); |
1658 | |
1659 | - Q_INVOKABLE QJsonObject xmlToJson(const QString &xml); |
1660 | + Q_INVOKABLE QJsonObject xmlToJson(const QByteArray &xml); |
1661 | + // load feed for non-google usage |
1662 | + Q_INVOKABLE void loadFeed(const QString &feedUrl); |
1663 | + Q_INVOKABLE void abort(); |
1664 | + |
1665 | + // |
1666 | Q_INVOKABLE QStringList htmlGetImg(const QString &html); |
1667 | |
1668 | // get & set settings' values |
1669 | Q_INVOKABLE QString getSetting(const QString &key); |
1670 | Q_INVOKABLE void setSetting(const QString &key, const QString &value); |
1671 | |
1672 | + // load opml file from local |
1673 | + Q_INVOKABLE void loadOpml(const QString &opmlUrl); |
1674 | + |
1675 | // test only |
1676 | // Q_INVOKABLE QJsonObject test(); |
1677 | |
1678 | signals: |
1679 | + void sigResult(QJsonObject result); |
1680 | + void sigOpmlJsom(QJsonObject result); |
1681 | |
1682 | public slots: |
1683 | |
1684 | +private: |
1685 | + QNetworkAccessManager *_internalMgr; |
1686 | + QNetworkReply *_internalReply; |
1687 | + QTimer *_loadTimer; |
1688 | + |
1689 | +private slots: |
1690 | + void _internalReplySlot(); |
1691 | + void slotSslErrors(QList<QSslError>); |
1692 | }; |
1693 | |
1694 | #endif // UTILITIES_H |
1695 | |
1696 | === modified file 'shorts/xml2json/rapidjson/allocators.h' |
1697 | --- shorts/xml2json/rapidjson/allocators.h 2016-03-04 13:27:57 +0000 |
1698 | +++ shorts/xml2json/rapidjson/allocators.h 2016-06-15 16:13:25 +0000 |
1699 | @@ -194,6 +194,9 @@ |
1700 | if (newSize == 0) |
1701 | return NULL; |
1702 | |
1703 | + originalSize = RAPIDJSON_ALIGN(originalSize); |
1704 | + newSize = RAPIDJSON_ALIGN(newSize); |
1705 | + |
1706 | // Do not shrink if new size is smaller than original |
1707 | if (originalSize >= newSize) |
1708 | return originalPtr; |
1709 | @@ -201,7 +204,6 @@ |
1710 | // Simply expand it if it is the last allocation and there is sufficient space |
1711 | if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { |
1712 | size_t increment = static_cast<size_t>(newSize - originalSize); |
1713 | - increment = RAPIDJSON_ALIGN(increment); |
1714 | if (chunkHead_->size + increment <= chunkHead_->capacity) { |
1715 | chunkHead_->size += increment; |
1716 | return originalPtr; |
1717 | |
1718 | === modified file 'shorts/xml2json/rapidjson/document.h' |
1719 | --- shorts/xml2json/rapidjson/document.h 2016-03-04 13:27:57 +0000 |
1720 | +++ shorts/xml2json/rapidjson/document.h 2016-06-15 16:13:25 +0000 |
1721 | @@ -20,17 +20,21 @@ |
1722 | #include "reader.h" |
1723 | #include "internal/meta.h" |
1724 | #include "internal/strfunc.h" |
1725 | +#include "memorystream.h" |
1726 | +#include "encodedstream.h" |
1727 | #include <new> // placement new |
1728 | |
1729 | #ifdef _MSC_VER |
1730 | RAPIDJSON_DIAG_PUSH |
1731 | RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant |
1732 | +RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data |
1733 | #endif |
1734 | |
1735 | #ifdef __clang__ |
1736 | RAPIDJSON_DIAG_PUSH |
1737 | RAPIDJSON_DIAG_OFF(padded) |
1738 | RAPIDJSON_DIAG_OFF(switch-enum) |
1739 | +RAPIDJSON_DIAG_OFF(c++98-compat) |
1740 | #endif |
1741 | |
1742 | #ifdef __GNUC__ |
1743 | @@ -141,6 +145,7 @@ |
1744 | Otherwise, the copy constructor is implicitly defined. |
1745 | */ |
1746 | GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} |
1747 | + Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } |
1748 | |
1749 | //! @name stepping |
1750 | //@{ |
1751 | @@ -293,7 +298,7 @@ |
1752 | */ |
1753 | #endif |
1754 | explicit GenericStringRef(const CharType* str) |
1755 | - : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); } |
1756 | + : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); } |
1757 | |
1758 | //! Create constant string reference from pointer and length |
1759 | #ifndef __clang__ // -Wdocumentation |
1760 | @@ -305,7 +310,11 @@ |
1761 | */ |
1762 | #endif |
1763 | GenericStringRef(const CharType* str, SizeType len) |
1764 | - : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); } |
1765 | + : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); } |
1766 | + |
1767 | + GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} |
1768 | + |
1769 | + GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; } |
1770 | |
1771 | //! implicit conversion to plain CharType pointer |
1772 | operator const Ch *() const { return s; } |
1773 | @@ -314,8 +323,6 @@ |
1774 | const SizeType length; //!< length of the string (excluding the trailing NULL terminator) |
1775 | |
1776 | private: |
1777 | - //! Disallow copy-assignment |
1778 | - GenericStringRef operator=(const GenericStringRef&); |
1779 | //! Disallow construction from non-const array |
1780 | template<SizeType N> |
1781 | GenericStringRef(CharType (&str)[N]) /* = delete */; |
1782 | @@ -394,6 +401,127 @@ |
1783 | } // namespace internal |
1784 | |
1785 | /////////////////////////////////////////////////////////////////////////////// |
1786 | +// TypeHelper |
1787 | + |
1788 | +namespace internal { |
1789 | + |
1790 | +template <typename ValueType, typename T> |
1791 | +struct TypeHelper {}; |
1792 | + |
1793 | +template<typename ValueType> |
1794 | +struct TypeHelper<ValueType, bool> { |
1795 | + static bool Is(const ValueType& v) { return v.IsBool(); } |
1796 | + static bool Get(const ValueType& v) { return v.GetBool(); } |
1797 | + static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } |
1798 | + static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } |
1799 | +}; |
1800 | + |
1801 | +template<typename ValueType> |
1802 | +struct TypeHelper<ValueType, int> { |
1803 | + static bool Is(const ValueType& v) { return v.IsInt(); } |
1804 | + static int Get(const ValueType& v) { return v.GetInt(); } |
1805 | + static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } |
1806 | + static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } |
1807 | +}; |
1808 | + |
1809 | +template<typename ValueType> |
1810 | +struct TypeHelper<ValueType, unsigned> { |
1811 | + static bool Is(const ValueType& v) { return v.IsUint(); } |
1812 | + static unsigned Get(const ValueType& v) { return v.GetUint(); } |
1813 | + static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } |
1814 | + static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } |
1815 | +}; |
1816 | + |
1817 | +template<typename ValueType> |
1818 | +struct TypeHelper<ValueType, int64_t> { |
1819 | + static bool Is(const ValueType& v) { return v.IsInt64(); } |
1820 | + static int64_t Get(const ValueType& v) { return v.GetInt64(); } |
1821 | + static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } |
1822 | + static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } |
1823 | +}; |
1824 | + |
1825 | +template<typename ValueType> |
1826 | +struct TypeHelper<ValueType, uint64_t> { |
1827 | + static bool Is(const ValueType& v) { return v.IsUint64(); } |
1828 | + static uint64_t Get(const ValueType& v) { return v.GetUint64(); } |
1829 | + static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } |
1830 | + static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } |
1831 | +}; |
1832 | + |
1833 | +template<typename ValueType> |
1834 | +struct TypeHelper<ValueType, double> { |
1835 | + static bool Is(const ValueType& v) { return v.IsDouble(); } |
1836 | + static double Get(const ValueType& v) { return v.GetDouble(); } |
1837 | + static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } |
1838 | + static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } |
1839 | +}; |
1840 | + |
1841 | +template<typename ValueType> |
1842 | +struct TypeHelper<ValueType, float> { |
1843 | + static bool Is(const ValueType& v) { return v.IsFloat(); } |
1844 | + static float Get(const ValueType& v) { return v.GetFloat(); } |
1845 | + static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } |
1846 | + static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } |
1847 | +}; |
1848 | + |
1849 | +template<typename ValueType> |
1850 | +struct TypeHelper<ValueType, const typename ValueType::Ch*> { |
1851 | + typedef const typename ValueType::Ch* StringType; |
1852 | + static bool Is(const ValueType& v) { return v.IsString(); } |
1853 | + static StringType Get(const ValueType& v) { return v.GetString(); } |
1854 | + static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } |
1855 | + static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } |
1856 | +}; |
1857 | + |
1858 | +#if RAPIDJSON_HAS_STDSTRING |
1859 | +template<typename ValueType> |
1860 | +struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > { |
1861 | + typedef std::basic_string<typename ValueType::Ch> StringType; |
1862 | + static bool Is(const ValueType& v) { return v.IsString(); } |
1863 | + static StringType Get(const ValueType& v) { return v.GetString(); } |
1864 | + static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } |
1865 | +}; |
1866 | +#endif |
1867 | + |
1868 | +template<typename ValueType> |
1869 | +struct TypeHelper<ValueType, typename ValueType::Array> { |
1870 | + typedef typename ValueType::Array ArrayType; |
1871 | + static bool Is(const ValueType& v) { return v.IsArray(); } |
1872 | + static ArrayType Get(ValueType& v) { return v.GetArray(); } |
1873 | + static ValueType& Set(ValueType& v, ArrayType data) { return v = data; } |
1874 | + static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; } |
1875 | +}; |
1876 | + |
1877 | +template<typename ValueType> |
1878 | +struct TypeHelper<ValueType, typename ValueType::ConstArray> { |
1879 | + typedef typename ValueType::ConstArray ArrayType; |
1880 | + static bool Is(const ValueType& v) { return v.IsArray(); } |
1881 | + static ArrayType Get(const ValueType& v) { return v.GetArray(); } |
1882 | +}; |
1883 | + |
1884 | +template<typename ValueType> |
1885 | +struct TypeHelper<ValueType, typename ValueType::Object> { |
1886 | + typedef typename ValueType::Object ObjectType; |
1887 | + static bool Is(const ValueType& v) { return v.IsObject(); } |
1888 | + static ObjectType Get(ValueType& v) { return v.GetObject(); } |
1889 | + static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } |
1890 | + static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; } |
1891 | +}; |
1892 | + |
1893 | +template<typename ValueType> |
1894 | +struct TypeHelper<ValueType, typename ValueType::ConstObject> { |
1895 | + typedef typename ValueType::ConstObject ObjectType; |
1896 | + static bool Is(const ValueType& v) { return v.IsObject(); } |
1897 | + static ObjectType Get(const ValueType& v) { return v.GetObject(); } |
1898 | +}; |
1899 | + |
1900 | +} // namespace internal |
1901 | + |
1902 | +// Forward declarations |
1903 | +template <bool, typename> class GenericArray; |
1904 | +template <bool, typename> class GenericObject; |
1905 | + |
1906 | +/////////////////////////////////////////////////////////////////////////////// |
1907 | // GenericValue |
1908 | |
1909 | //! Represents a JSON value. Use Value for UTF8 encoding and default allocator. |
1910 | @@ -420,17 +548,21 @@ |
1911 | typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. |
1912 | typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. |
1913 | typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself. |
1914 | + typedef GenericArray<false, ValueType> Array; |
1915 | + typedef GenericArray<true, ValueType> ConstArray; |
1916 | + typedef GenericObject<false, ValueType> Object; |
1917 | + typedef GenericObject<true, ValueType> ConstObject; |
1918 | |
1919 | //!@name Constructors and destructor. |
1920 | //@{ |
1921 | |
1922 | //! Default constructor creates a null value. |
1923 | - GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {} |
1924 | + GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; } |
1925 | |
1926 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
1927 | //! Move constructor in C++11 |
1928 | - GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) { |
1929 | - rhs.flags_ = kNullFlag; // give up contents |
1930 | + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) { |
1931 | + rhs.data_.f.flags = kNullFlag; // give up contents |
1932 | } |
1933 | #endif |
1934 | |
1935 | @@ -455,13 +587,13 @@ |
1936 | \param type Type of the value. |
1937 | \note Default content for number is zero. |
1938 | */ |
1939 | - explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() { |
1940 | - static const unsigned defaultFlags[7] = { |
1941 | + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { |
1942 | + static const uint16_t defaultFlags[7] = { |
1943 | kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, |
1944 | kNumberAnyFlag |
1945 | }; |
1946 | RAPIDJSON_ASSERT(type <= kNumberType); |
1947 | - flags_ = defaultFlags[type]; |
1948 | + data_.f.flags = defaultFlags[type]; |
1949 | |
1950 | // Use ShortString to store empty string. |
1951 | if (type == kStringType) |
1952 | @@ -486,96 +618,122 @@ |
1953 | */ |
1954 | #ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen |
1955 | template <typename T> |
1956 | - explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT |
1957 | + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472 |
1958 | #else |
1959 | explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT |
1960 | #endif |
1961 | - : data_(), flags_(b ? kTrueFlag : kFalseFlag) { |
1962 | + : data_() { |
1963 | // safe-guard against failing SFINAE |
1964 | RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value)); |
1965 | + data_.f.flags = b ? kTrueFlag : kFalseFlag; |
1966 | } |
1967 | |
1968 | //! Constructor for int value. |
1969 | - explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) { |
1970 | + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() { |
1971 | data_.n.i64 = i; |
1972 | - if (i >= 0) |
1973 | - flags_ |= kUintFlag | kUint64Flag; |
1974 | + data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; |
1975 | } |
1976 | |
1977 | //! Constructor for unsigned value. |
1978 | - explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) { |
1979 | + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() { |
1980 | data_.n.u64 = u; |
1981 | - if (!(u & 0x80000000)) |
1982 | - flags_ |= kIntFlag | kInt64Flag; |
1983 | + data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); |
1984 | } |
1985 | |
1986 | //! Constructor for int64_t value. |
1987 | - explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) { |
1988 | + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() { |
1989 | data_.n.i64 = i64; |
1990 | + data_.f.flags = kNumberInt64Flag; |
1991 | if (i64 >= 0) { |
1992 | - flags_ |= kNumberUint64Flag; |
1993 | + data_.f.flags |= kNumberUint64Flag; |
1994 | if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) |
1995 | - flags_ |= kUintFlag; |
1996 | + data_.f.flags |= kUintFlag; |
1997 | if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) |
1998 | - flags_ |= kIntFlag; |
1999 | + data_.f.flags |= kIntFlag; |
2000 | } |
2001 | else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) |
2002 | - flags_ |= kIntFlag; |
2003 | + data_.f.flags |= kIntFlag; |
2004 | } |
2005 | |
2006 | //! Constructor for uint64_t value. |
2007 | - explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) { |
2008 | + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() { |
2009 | data_.n.u64 = u64; |
2010 | + data_.f.flags = kNumberUint64Flag; |
2011 | if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) |
2012 | - flags_ |= kInt64Flag; |
2013 | + data_.f.flags |= kInt64Flag; |
2014 | if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) |
2015 | - flags_ |= kUintFlag; |
2016 | + data_.f.flags |= kUintFlag; |
2017 | if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) |
2018 | - flags_ |= kIntFlag; |
2019 | + data_.f.flags |= kIntFlag; |
2020 | } |
2021 | |
2022 | //! Constructor for double value. |
2023 | - explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; } |
2024 | - |
2025 | - //! Constructor for constant string (i.e. do not make a copy of string) |
2026 | - GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); } |
2027 | - |
2028 | - //! Constructor for constant string (i.e. do not make a copy of string) |
2029 | - explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); } |
2030 | - |
2031 | - //! Constructor for copy-string (i.e. do make a copy of string) |
2032 | - GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); } |
2033 | - |
2034 | - //! Constructor for copy-string (i.e. do make a copy of string) |
2035 | - GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } |
2036 | + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } |
2037 | + |
2038 | + //! Constructor for constant string (i.e. do not make a copy of string) |
2039 | + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } |
2040 | + |
2041 | + //! Constructor for constant string (i.e. do not make a copy of string) |
2042 | + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); } |
2043 | + |
2044 | + //! Constructor for copy-string (i.e. do make a copy of string) |
2045 | + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); } |
2046 | + |
2047 | + //! Constructor for copy-string (i.e. do make a copy of string) |
2048 | + GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } |
2049 | |
2050 | #if RAPIDJSON_HAS_STDSTRING |
2051 | //! Constructor for copy-string from a string object (i.e. do make a copy of string) |
2052 | /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. |
2053 | */ |
2054 | - GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } |
2055 | + GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } |
2056 | #endif |
2057 | |
2058 | + //! Constructor for Array. |
2059 | + /*! |
2060 | + \param a An array obtained by \c GetArray(). |
2061 | + \note \c Array is always pass-by-value. |
2062 | + \note the source array is moved into this value and the sourec array becomes empty. |
2063 | + */ |
2064 | + GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) { |
2065 | + a.value_.data_ = Data(); |
2066 | + a.value_.data_.f.flags = kArrayFlag; |
2067 | + } |
2068 | + |
2069 | + //! Constructor for Object. |
2070 | + /*! |
2071 | + \param o An object obtained by \c GetObject(). |
2072 | + \note \c Object is always pass-by-value. |
2073 | + \note the source object is moved into this value and the sourec object becomes empty. |
2074 | + */ |
2075 | + GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) { |
2076 | + o.value_.data_ = Data(); |
2077 | + o.value_.data_.f.flags = kObjectFlag; |
2078 | + } |
2079 | + |
2080 | //! Destructor. |
2081 | /*! Need to destruct elements of array, members of object, or copy-string. |
2082 | */ |
2083 | ~GenericValue() { |
2084 | if (Allocator::kNeedFree) { // Shortcut by Allocator's trait |
2085 | - switch(flags_) { |
2086 | + switch(data_.f.flags) { |
2087 | case kArrayFlag: |
2088 | - for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) |
2089 | - v->~GenericValue(); |
2090 | - Allocator::Free(data_.a.elements); |
2091 | + { |
2092 | + GenericValue* e = GetElementsPointer(); |
2093 | + for (GenericValue* v = e; v != e + data_.a.size; ++v) |
2094 | + v->~GenericValue(); |
2095 | + Allocator::Free(e); |
2096 | + } |
2097 | break; |
2098 | |
2099 | case kObjectFlag: |
2100 | for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) |
2101 | m->~Member(); |
2102 | - Allocator::Free(data_.o.members); |
2103 | + Allocator::Free(GetMembersPointer()); |
2104 | break; |
2105 | |
2106 | case kCopyStringFlag: |
2107 | - Allocator::Free(const_cast<Ch*>(data_.s.str)); |
2108 | + Allocator::Free(const_cast<Ch*>(GetStringPointer())); |
2109 | break; |
2110 | |
2111 | default: |
2112 | @@ -773,20 +931,51 @@ |
2113 | //!@name Type |
2114 | //@{ |
2115 | |
2116 | - Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); } |
2117 | - bool IsNull() const { return flags_ == kNullFlag; } |
2118 | - bool IsFalse() const { return flags_ == kFalseFlag; } |
2119 | - bool IsTrue() const { return flags_ == kTrueFlag; } |
2120 | - bool IsBool() const { return (flags_ & kBoolFlag) != 0; } |
2121 | - bool IsObject() const { return flags_ == kObjectFlag; } |
2122 | - bool IsArray() const { return flags_ == kArrayFlag; } |
2123 | - bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } |
2124 | - bool IsInt() const { return (flags_ & kIntFlag) != 0; } |
2125 | - bool IsUint() const { return (flags_ & kUintFlag) != 0; } |
2126 | - bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } |
2127 | - bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } |
2128 | - bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } |
2129 | - bool IsString() const { return (flags_ & kStringFlag) != 0; } |
2130 | + Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask); } |
2131 | + bool IsNull() const { return data_.f.flags == kNullFlag; } |
2132 | + bool IsFalse() const { return data_.f.flags == kFalseFlag; } |
2133 | + bool IsTrue() const { return data_.f.flags == kTrueFlag; } |
2134 | + bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; } |
2135 | + bool IsObject() const { return data_.f.flags == kObjectFlag; } |
2136 | + bool IsArray() const { return data_.f.flags == kArrayFlag; } |
2137 | + bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; } |
2138 | + bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; } |
2139 | + bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; } |
2140 | + bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; } |
2141 | + bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; } |
2142 | + bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; } |
2143 | + bool IsString() const { return (data_.f.flags & kStringFlag) != 0; } |
2144 | + |
2145 | + // Checks whether a number can be losslessly converted to a double. |
2146 | + bool IsLosslessDouble() const { |
2147 | + if (!IsNumber()) return false; |
2148 | + if (IsUint64()) { |
2149 | + uint64_t u = GetUint64(); |
2150 | + volatile double d = static_cast<double>(u); |
2151 | + return static_cast<uint64_t>(d) == u; |
2152 | + } |
2153 | + if (IsInt64()) { |
2154 | + int64_t i = GetInt64(); |
2155 | + volatile double d = static_cast<double>(i); |
2156 | + return static_cast< int64_t>(d) == i; |
2157 | + } |
2158 | + return true; // double, int, uint are always lossless |
2159 | + } |
2160 | + |
2161 | + // Checks whether a number is a float (possible lossy). |
2162 | + bool IsFloat() const { |
2163 | + if ((data_.f.flags & kDoubleFlag) == 0) |
2164 | + return false; |
2165 | + double d = GetDouble(); |
2166 | + return d >= -3.4028234e38 && d <= 3.4028234e38; |
2167 | + } |
2168 | + // Checks whether a number can be losslessly converted to a float. |
2169 | + bool IsLosslessFloat() const { |
2170 | + if (!IsNumber()) return false; |
2171 | + double a = GetDouble(); |
2172 | + double b = static_cast<double>(static_cast<float>(a)); |
2173 | + return a >= b && a <= b; // Prevent -Wfloat-equal |
2174 | + } |
2175 | |
2176 | //@} |
2177 | |
2178 | @@ -800,7 +989,7 @@ |
2179 | //!@name Bool |
2180 | //@{ |
2181 | |
2182 | - bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; } |
2183 | + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } |
2184 | //!< Set boolean value |
2185 | /*! \post IsBool() == true */ |
2186 | GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } |
2187 | @@ -874,16 +1063,16 @@ |
2188 | |
2189 | //! Const member iterator |
2190 | /*! \pre IsObject() == true */ |
2191 | - ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); } |
2192 | + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } |
2193 | //! Const \em past-the-end member iterator |
2194 | /*! \pre IsObject() == true */ |
2195 | - ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); } |
2196 | + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } |
2197 | //! Member iterator |
2198 | /*! \pre IsObject() == true */ |
2199 | - MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); } |
2200 | + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } |
2201 | //! \em Past-the-end member iterator |
2202 | /*! \pre IsObject() == true */ |
2203 | - MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); } |
2204 | + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } |
2205 | |
2206 | //! Check whether a member exists in the object. |
2207 | /*! |
2208 | @@ -989,20 +1178,21 @@ |
2209 | RAPIDJSON_ASSERT(IsObject()); |
2210 | RAPIDJSON_ASSERT(name.IsString()); |
2211 | |
2212 | - Object& o = data_.o; |
2213 | + ObjectData& o = data_.o; |
2214 | if (o.size >= o.capacity) { |
2215 | if (o.capacity == 0) { |
2216 | o.capacity = kDefaultObjectCapacity; |
2217 | - o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member))); |
2218 | + SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)))); |
2219 | } |
2220 | else { |
2221 | SizeType oldCapacity = o.capacity; |
2222 | o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 |
2223 | - o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member))); |
2224 | + SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member)))); |
2225 | } |
2226 | } |
2227 | - o.members[o.size].name.RawAssign(name); |
2228 | - o.members[o.size].value.RawAssign(value); |
2229 | + Member* members = GetMembersPointer(); |
2230 | + members[o.size].name.RawAssign(name); |
2231 | + members[o.size].value.RawAssign(value); |
2232 | o.size++; |
2233 | return *this; |
2234 | } |
2235 | @@ -1181,18 +1371,14 @@ |
2236 | MemberIterator RemoveMember(MemberIterator m) { |
2237 | RAPIDJSON_ASSERT(IsObject()); |
2238 | RAPIDJSON_ASSERT(data_.o.size > 0); |
2239 | - RAPIDJSON_ASSERT(data_.o.members != 0); |
2240 | + RAPIDJSON_ASSERT(GetMembersPointer() != 0); |
2241 | RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); |
2242 | |
2243 | - MemberIterator last(data_.o.members + (data_.o.size - 1)); |
2244 | - if (data_.o.size > 1 && m != last) { |
2245 | - // Move the last one to this place |
2246 | - *m = *last; |
2247 | - } |
2248 | - else { |
2249 | - // Only one left, just destroy |
2250 | - m->~Member(); |
2251 | - } |
2252 | + MemberIterator last(GetMembersPointer() + (data_.o.size - 1)); |
2253 | + if (data_.o.size > 1 && m != last) |
2254 | + *m = *last; // Move the last one to this place |
2255 | + else |
2256 | + m->~Member(); // Only one left, just destroy |
2257 | --data_.o.size; |
2258 | return m; |
2259 | } |
2260 | @@ -1222,7 +1408,7 @@ |
2261 | MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { |
2262 | RAPIDJSON_ASSERT(IsObject()); |
2263 | RAPIDJSON_ASSERT(data_.o.size > 0); |
2264 | - RAPIDJSON_ASSERT(data_.o.members != 0); |
2265 | + RAPIDJSON_ASSERT(GetMembersPointer() != 0); |
2266 | RAPIDJSON_ASSERT(first >= MemberBegin()); |
2267 | RAPIDJSON_ASSERT(first <= last); |
2268 | RAPIDJSON_ASSERT(last <= MemberEnd()); |
2269 | @@ -1260,6 +1446,9 @@ |
2270 | return false; |
2271 | } |
2272 | |
2273 | + Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } |
2274 | + ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } |
2275 | + |
2276 | //@} |
2277 | |
2278 | //!@name Array |
2279 | @@ -1267,7 +1456,7 @@ |
2280 | |
2281 | //! Set this value as an empty array. |
2282 | /*! \post IsArray == true */ |
2283 | - GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } |
2284 | + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } |
2285 | |
2286 | //! Get the number of elements in array. |
2287 | SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } |
2288 | @@ -1284,8 +1473,9 @@ |
2289 | */ |
2290 | void Clear() { |
2291 | RAPIDJSON_ASSERT(IsArray()); |
2292 | - for (SizeType i = 0; i < data_.a.size; ++i) |
2293 | - data_.a.elements[i].~GenericValue(); |
2294 | + GenericValue* e = GetElementsPointer(); |
2295 | + for (GenericValue* v = e; v != e + data_.a.size; ++v) |
2296 | + v->~GenericValue(); |
2297 | data_.a.size = 0; |
2298 | } |
2299 | |
2300 | @@ -1297,16 +1487,16 @@ |
2301 | GenericValue& operator[](SizeType index) { |
2302 | RAPIDJSON_ASSERT(IsArray()); |
2303 | RAPIDJSON_ASSERT(index < data_.a.size); |
2304 | - return data_.a.elements[index]; |
2305 | + return GetElementsPointer()[index]; |
2306 | } |
2307 | const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; } |
2308 | |
2309 | //! Element iterator |
2310 | /*! \pre IsArray() == true */ |
2311 | - ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } |
2312 | + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } |
2313 | //! \em Past-the-end element iterator |
2314 | /*! \pre IsArray() == true */ |
2315 | - ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } |
2316 | + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } |
2317 | //! Constant element iterator |
2318 | /*! \pre IsArray() == true */ |
2319 | ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); } |
2320 | @@ -1323,7 +1513,7 @@ |
2321 | GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { |
2322 | RAPIDJSON_ASSERT(IsArray()); |
2323 | if (newCapacity > data_.a.capacity) { |
2324 | - data_.a.elements = static_cast<GenericValue*>(allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))); |
2325 | + SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); |
2326 | data_.a.capacity = newCapacity; |
2327 | } |
2328 | return *this; |
2329 | @@ -1343,7 +1533,7 @@ |
2330 | RAPIDJSON_ASSERT(IsArray()); |
2331 | if (data_.a.size >= data_.a.capacity) |
2332 | Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); |
2333 | - data_.a.elements[data_.a.size++].RawAssign(value); |
2334 | + GetElementsPointer()[data_.a.size++].RawAssign(value); |
2335 | return *this; |
2336 | } |
2337 | |
2338 | @@ -1397,7 +1587,7 @@ |
2339 | GenericValue& PopBack() { |
2340 | RAPIDJSON_ASSERT(IsArray()); |
2341 | RAPIDJSON_ASSERT(!Empty()); |
2342 | - data_.a.elements[--data_.a.size].~GenericValue(); |
2343 | + GetElementsPointer()[--data_.a.size].~GenericValue(); |
2344 | return *this; |
2345 | } |
2346 | |
2347 | @@ -1423,7 +1613,7 @@ |
2348 | ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { |
2349 | RAPIDJSON_ASSERT(IsArray()); |
2350 | RAPIDJSON_ASSERT(data_.a.size > 0); |
2351 | - RAPIDJSON_ASSERT(data_.a.elements != 0); |
2352 | + RAPIDJSON_ASSERT(GetElementsPointer() != 0); |
2353 | RAPIDJSON_ASSERT(first >= Begin()); |
2354 | RAPIDJSON_ASSERT(first <= last); |
2355 | RAPIDJSON_ASSERT(last <= End()); |
2356 | @@ -1435,23 +1625,36 @@ |
2357 | return pos; |
2358 | } |
2359 | |
2360 | + Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } |
2361 | + ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } |
2362 | + |
2363 | //@} |
2364 | |
2365 | //!@name Number |
2366 | //@{ |
2367 | |
2368 | - int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; } |
2369 | - unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; } |
2370 | - int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; } |
2371 | - uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; } |
2372 | + int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } |
2373 | + unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } |
2374 | + int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } |
2375 | + uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; } |
2376 | |
2377 | + //! Get the value as double type. |
2378 | + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. |
2379 | + */ |
2380 | double GetDouble() const { |
2381 | RAPIDJSON_ASSERT(IsNumber()); |
2382 | - if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. |
2383 | - if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double |
2384 | - if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double |
2385 | - if ((flags_ & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision) |
2386 | - RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision) |
2387 | + if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. |
2388 | + if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double |
2389 | + if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double |
2390 | + if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision) |
2391 | + RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision) |
2392 | + } |
2393 | + |
2394 | + //! Get the value as float type. |
2395 | + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. |
2396 | + */ |
2397 | + float GetFloat() const { |
2398 | + return static_cast<float>(GetDouble()); |
2399 | } |
2400 | |
2401 | GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } |
2402 | @@ -1459,18 +1662,19 @@ |
2403 | GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } |
2404 | GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } |
2405 | GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } |
2406 | + GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; } |
2407 | |
2408 | //@} |
2409 | |
2410 | //!@name String |
2411 | //@{ |
2412 | |
2413 | - const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); } |
2414 | + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); } |
2415 | |
2416 | //! Get the length of string. |
2417 | /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). |
2418 | */ |
2419 | - SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } |
2420 | + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } |
2421 | |
2422 | //! Set this value as a string without copying source string. |
2423 | /*! This version has better performance with supplied length, and also support string containing null character. |
2424 | @@ -1520,6 +1724,30 @@ |
2425 | |
2426 | //@} |
2427 | |
2428 | + //!@name Array |
2429 | + //@{ |
2430 | + |
2431 | + //! Templated version for checking whether this value is type T. |
2432 | + /*! |
2433 | + \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch> |
2434 | + */ |
2435 | + template <typename T> |
2436 | + bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); } |
2437 | + |
2438 | + template <typename T> |
2439 | + T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); } |
2440 | + |
2441 | + template <typename T> |
2442 | + T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); } |
2443 | + |
2444 | + template<typename T> |
2445 | + ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); } |
2446 | + |
2447 | + template<typename T> |
2448 | + ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); } |
2449 | + |
2450 | + //@} |
2451 | + |
2452 | //! Generate events of this value to a Handler. |
2453 | /*! This function adopts the GoF visitor pattern. |
2454 | Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. |
2455 | @@ -1535,35 +1763,35 @@ |
2456 | case kTrueType: return handler.Bool(true); |
2457 | |
2458 | case kObjectType: |
2459 | - if (!handler.StartObject()) |
2460 | + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) |
2461 | return false; |
2462 | for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { |
2463 | RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. |
2464 | - if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0)) |
2465 | + if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0))) |
2466 | return false; |
2467 | - if (!m->value.Accept(handler)) |
2468 | + if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) |
2469 | return false; |
2470 | } |
2471 | return handler.EndObject(data_.o.size); |
2472 | |
2473 | case kArrayType: |
2474 | - if (!handler.StartArray()) |
2475 | + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) |
2476 | return false; |
2477 | - for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) |
2478 | - if (!v->Accept(handler)) |
2479 | + for (const GenericValue* v = Begin(); v != End(); ++v) |
2480 | + if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) |
2481 | return false; |
2482 | return handler.EndArray(data_.a.size); |
2483 | |
2484 | case kStringType: |
2485 | - return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0); |
2486 | + return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); |
2487 | |
2488 | default: |
2489 | RAPIDJSON_ASSERT(GetType() == kNumberType); |
2490 | - if (IsInt()) return handler.Int(data_.n.i.i); |
2491 | + if (IsDouble()) return handler.Double(data_.n.d); |
2492 | + else if (IsInt()) return handler.Int(data_.n.i.i); |
2493 | else if (IsUint()) return handler.Uint(data_.n.u.u); |
2494 | else if (IsInt64()) return handler.Int64(data_.n.i64); |
2495 | - else if (IsUint64()) return handler.Uint64(data_.n.u64); |
2496 | - else return handler.Double(data_.n.d); |
2497 | + else return handler.Uint64(data_.n.u64); |
2498 | } |
2499 | } |
2500 | |
2501 | @@ -1572,16 +1800,16 @@ |
2502 | template <typename, typename, typename> friend class GenericDocument; |
2503 | |
2504 | enum { |
2505 | - kBoolFlag = 0x100, |
2506 | - kNumberFlag = 0x200, |
2507 | - kIntFlag = 0x400, |
2508 | - kUintFlag = 0x800, |
2509 | - kInt64Flag = 0x1000, |
2510 | - kUint64Flag = 0x2000, |
2511 | - kDoubleFlag = 0x4000, |
2512 | - kStringFlag = 0x100000, |
2513 | - kCopyFlag = 0x200000, |
2514 | - kInlineStrFlag = 0x400000, |
2515 | + kBoolFlag = 0x0008, |
2516 | + kNumberFlag = 0x0010, |
2517 | + kIntFlag = 0x0020, |
2518 | + kUintFlag = 0x0040, |
2519 | + kInt64Flag = 0x0080, |
2520 | + kUint64Flag = 0x0100, |
2521 | + kDoubleFlag = 0x0200, |
2522 | + kStringFlag = 0x0400, |
2523 | + kCopyFlag = 0x0800, |
2524 | + kInlineStrFlag = 0x1000, |
2525 | |
2526 | // Initial flags of different types. |
2527 | kNullFlag = kNullType, |
2528 | @@ -1599,16 +1827,27 @@ |
2529 | kObjectFlag = kObjectType, |
2530 | kArrayFlag = kArrayType, |
2531 | |
2532 | - kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler |
2533 | + kTypeMask = 0x07 |
2534 | }; |
2535 | |
2536 | static const SizeType kDefaultArrayCapacity = 16; |
2537 | static const SizeType kDefaultObjectCapacity = 16; |
2538 | |
2539 | + struct Flag { |
2540 | +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION |
2541 | + char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer |
2542 | +#elif RAPIDJSON_64BIT |
2543 | + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes |
2544 | +#else |
2545 | + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes |
2546 | +#endif |
2547 | + uint16_t flags; |
2548 | + }; |
2549 | + |
2550 | struct String { |
2551 | + SizeType length; |
2552 | + SizeType hashcode; //!< reserved |
2553 | const Ch* str; |
2554 | - SizeType length; |
2555 | - unsigned hashcode; //!< reserved |
2556 | }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode |
2557 | |
2558 | // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars |
2559 | @@ -1617,10 +1856,10 @@ |
2560 | // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as |
2561 | // the string terminator as well. For getting the string length back from that value just use |
2562 | // "MaxSize - str[LenPos]". |
2563 | - // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode |
2564 | - // inline (for `UTF8`-encoded strings). |
2565 | + // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, |
2566 | + // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). |
2567 | struct ShortString { |
2568 | - enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; |
2569 | + enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; |
2570 | Ch str[MaxChars]; |
2571 | |
2572 | inline static bool Usable(SizeType len) { return (MaxSize >= len); } |
2573 | @@ -1654,69 +1893,79 @@ |
2574 | double d; |
2575 | }; // 8 bytes |
2576 | |
2577 | - struct Object { |
2578 | + struct ObjectData { |
2579 | + SizeType size; |
2580 | + SizeType capacity; |
2581 | Member* members; |
2582 | + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode |
2583 | + |
2584 | + struct ArrayData { |
2585 | SizeType size; |
2586 | SizeType capacity; |
2587 | - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode |
2588 | - |
2589 | - struct Array { |
2590 | GenericValue* elements; |
2591 | - SizeType size; |
2592 | - SizeType capacity; |
2593 | }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode |
2594 | |
2595 | union Data { |
2596 | String s; |
2597 | ShortString ss; |
2598 | Number n; |
2599 | - Object o; |
2600 | - Array a; |
2601 | - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode |
2602 | + ObjectData o; |
2603 | + ArrayData a; |
2604 | + Flag f; |
2605 | + }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION |
2606 | + |
2607 | + RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } |
2608 | + RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } |
2609 | + RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } |
2610 | + RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); } |
2611 | + RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } |
2612 | + RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } |
2613 | |
2614 | // Initialize this value as array with initial data, without calling destructor. |
2615 | void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { |
2616 | - flags_ = kArrayFlag; |
2617 | + data_.f.flags = kArrayFlag; |
2618 | if (count) { |
2619 | - data_.a.elements = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue))); |
2620 | - std::memcpy(data_.a.elements, values, count * sizeof(GenericValue)); |
2621 | + GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue))); |
2622 | + SetElementsPointer(e); |
2623 | + std::memcpy(e, values, count * sizeof(GenericValue)); |
2624 | } |
2625 | else |
2626 | - data_.a.elements = NULL; |
2627 | + SetElementsPointer(0); |
2628 | data_.a.size = data_.a.capacity = count; |
2629 | } |
2630 | |
2631 | //! Initialize this value as object with initial data, without calling destructor. |
2632 | void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { |
2633 | - flags_ = kObjectFlag; |
2634 | + data_.f.flags = kObjectFlag; |
2635 | if (count) { |
2636 | - data_.o.members = static_cast<Member*>(allocator.Malloc(count * sizeof(Member))); |
2637 | - std::memcpy(data_.o.members, members, count * sizeof(Member)); |
2638 | + Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member))); |
2639 | + SetMembersPointer(m); |
2640 | + std::memcpy(m, members, count * sizeof(Member)); |
2641 | } |
2642 | else |
2643 | - data_.o.members = NULL; |
2644 | + SetMembersPointer(0); |
2645 | data_.o.size = data_.o.capacity = count; |
2646 | } |
2647 | |
2648 | //! Initialize this value as constant string, without calling destructor. |
2649 | void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { |
2650 | - flags_ = kConstStringFlag; |
2651 | - data_.s.str = s; |
2652 | + data_.f.flags = kConstStringFlag; |
2653 | + SetStringPointer(s); |
2654 | data_.s.length = s.length; |
2655 | } |
2656 | |
2657 | //! Initialize this value as copy string with initial data, without calling destructor. |
2658 | void SetStringRaw(StringRefType s, Allocator& allocator) { |
2659 | - Ch* str = NULL; |
2660 | - if(ShortString::Usable(s.length)) { |
2661 | - flags_ = kShortStringFlag; |
2662 | + Ch* str = 0; |
2663 | + if (ShortString::Usable(s.length)) { |
2664 | + data_.f.flags = kShortStringFlag; |
2665 | data_.ss.SetLength(s.length); |
2666 | str = data_.ss.str; |
2667 | } else { |
2668 | - flags_ = kCopyStringFlag; |
2669 | + data_.f.flags = kCopyStringFlag; |
2670 | data_.s.length = s.length; |
2671 | str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch))); |
2672 | - data_.s.str = str; |
2673 | + SetStringPointer(str); |
2674 | } |
2675 | std::memcpy(str, s, s.length * sizeof(Ch)); |
2676 | str[s.length] = '\0'; |
2677 | @@ -1725,8 +1974,8 @@ |
2678 | //! Assignment without calling destructor |
2679 | void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { |
2680 | data_ = rhs.data_; |
2681 | - flags_ = rhs.flags_; |
2682 | - rhs.flags_ = kNullFlag; |
2683 | + // data_.f.flags = rhs.data_.f.flags; |
2684 | + rhs.data_.f.flags = kNullFlag; |
2685 | } |
2686 | |
2687 | template <typename SourceAllocator> |
2688 | @@ -1746,7 +1995,6 @@ |
2689 | } |
2690 | |
2691 | Data data_; |
2692 | - unsigned flags_; |
2693 | }; |
2694 | |
2695 | //! GenericValue with UTF8 encoding |
2696 | @@ -1869,6 +2117,21 @@ |
2697 | */ |
2698 | friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } |
2699 | |
2700 | + //! Populate this document by a generator which produces SAX events. |
2701 | + /*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype. |
2702 | + \param g Generator functor which sends SAX events to the parameter. |
2703 | + \return The document itself for fluent API. |
2704 | + */ |
2705 | + template <typename Generator> |
2706 | + GenericDocument& Populate(Generator& g) { |
2707 | + ClearStackOnExit scope(*this); |
2708 | + if (g(*this)) { |
2709 | + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object |
2710 | + ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document |
2711 | + } |
2712 | + return *this; |
2713 | + } |
2714 | + |
2715 | //!@name Parse from stream |
2716 | //!@{ |
2717 | |
2718 | @@ -1967,6 +2230,42 @@ |
2719 | GenericDocument& Parse(const Ch* str) { |
2720 | return Parse<kParseDefaultFlags>(str); |
2721 | } |
2722 | + |
2723 | + template <unsigned parseFlags, typename SourceEncoding> |
2724 | + GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { |
2725 | + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); |
2726 | + MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch)); |
2727 | + EncodedInputStream<SourceEncoding, MemoryStream> is(ms); |
2728 | + ParseStream<parseFlags, SourceEncoding>(is); |
2729 | + return *this; |
2730 | + } |
2731 | + |
2732 | + template <unsigned parseFlags> |
2733 | + GenericDocument& Parse(const Ch* str, size_t length) { |
2734 | + return Parse<parseFlags, Encoding>(str, length); |
2735 | + } |
2736 | + |
2737 | + GenericDocument& Parse(const Ch* str, size_t length) { |
2738 | + return Parse<kParseDefaultFlags>(str, length); |
2739 | + } |
2740 | + |
2741 | +#if RAPIDJSON_HAS_STDSTRING |
2742 | + template <unsigned parseFlags, typename SourceEncoding> |
2743 | + GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) { |
2744 | + // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) |
2745 | + return Parse<parseFlags, SourceEncoding>(str.c_str()); |
2746 | + } |
2747 | + |
2748 | + template <unsigned parseFlags> |
2749 | + GenericDocument& Parse(const std::basic_string<Ch>& str) { |
2750 | + return Parse<parseFlags, Encoding>(str.c_str()); |
2751 | + } |
2752 | + |
2753 | + GenericDocument& Parse(const std::basic_string<Ch>& str) { |
2754 | + return Parse<kParseDefaultFlags>(str); |
2755 | + } |
2756 | +#endif // RAPIDJSON_HAS_STDSTRING |
2757 | + |
2758 | //!@} |
2759 | |
2760 | //!@name Handling parse errors |
2761 | @@ -2017,9 +2316,10 @@ |
2762 | }; |
2763 | |
2764 | // callers of the following private Handler functions |
2765 | - template <typename,typename,typename> friend class GenericReader; // for parsing |
2766 | + // template <typename,typename,typename> friend class GenericReader; // for parsing |
2767 | template <typename, typename> friend class GenericValue; // for deep copying |
2768 | |
2769 | +public: |
2770 | // Implementation of Handler |
2771 | bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; } |
2772 | bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; } |
2773 | @@ -2029,6 +2329,14 @@ |
2774 | bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } |
2775 | bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; } |
2776 | |
2777 | + bool RawNumber(const Ch* str, SizeType length, bool copy) { |
2778 | + if (copy) |
2779 | + new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); |
2780 | + else |
2781 | + new (stack_.template Push<ValueType>()) ValueType(str, length); |
2782 | + return true; |
2783 | + } |
2784 | + |
2785 | bool String(const Ch* str, SizeType length, bool copy) { |
2786 | if (copy) |
2787 | new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator()); |
2788 | @@ -2099,20 +2407,159 @@ |
2789 | } |
2790 | break; |
2791 | case kStringType: |
2792 | - if (rhs.flags_ == kConstStringFlag) { |
2793 | - flags_ = rhs.flags_; |
2794 | + if (rhs.data_.f.flags == kConstStringFlag) { |
2795 | + data_.f.flags = rhs.data_.f.flags; |
2796 | data_ = *reinterpret_cast<const Data*>(&rhs.data_); |
2797 | } else { |
2798 | SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); |
2799 | } |
2800 | break; |
2801 | default: |
2802 | - flags_ = rhs.flags_; |
2803 | + data_.f.flags = rhs.data_.f.flags; |
2804 | data_ = *reinterpret_cast<const Data*>(&rhs.data_); |
2805 | break; |
2806 | } |
2807 | } |
2808 | |
2809 | +//! Helper class for accessing Value of array type. |
2810 | +/*! |
2811 | + Instance of this helper class is obtained by \c GenericValue::GetArray(). |
2812 | + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. |
2813 | +*/ |
2814 | +template <bool Const, typename ValueT> |
2815 | +class GenericArray { |
2816 | +public: |
2817 | + typedef GenericArray<true, ValueT> ConstArray; |
2818 | + typedef GenericArray<false, ValueT> Array; |
2819 | + typedef ValueT PlainType; |
2820 | + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; |
2821 | + typedef ValueType* ValueIterator; // This may be const or non-const iterator |
2822 | + typedef const ValueT* ConstValueIterator; |
2823 | + typedef typename ValueType::AllocatorType AllocatorType; |
2824 | + typedef typename ValueType::StringRefType StringRefType; |
2825 | + |
2826 | + template <typename, typename> |
2827 | + friend class GenericValue; |
2828 | + |
2829 | + GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} |
2830 | + GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } |
2831 | + ~GenericArray() {} |
2832 | + |
2833 | + SizeType Size() const { return value_.Size(); } |
2834 | + SizeType Capacity() const { return value_.Capacity(); } |
2835 | + bool Empty() const { return value_.Empty(); } |
2836 | + void Clear() const { value_.Clear(); } |
2837 | + ValueType& operator[](SizeType index) const { return value_[index]; } |
2838 | + ValueIterator Begin() const { return value_.Begin(); } |
2839 | + ValueIterator End() const { return value_.End(); } |
2840 | + GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; } |
2841 | + GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } |
2842 | +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
2843 | + GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } |
2844 | +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS |
2845 | + GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } |
2846 | + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } |
2847 | + GenericArray PopBack() const { value_.PopBack(); return *this; } |
2848 | + ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } |
2849 | + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } |
2850 | + |
2851 | +#if RAPIDJSON_HAS_CXX11_RANGE_FOR |
2852 | + ValueIterator begin() const { return value_.Begin(); } |
2853 | + ValueIterator end() const { return value_.End(); } |
2854 | +#endif |
2855 | + |
2856 | +private: |
2857 | + GenericArray(); |
2858 | + GenericArray(ValueType& value) : value_(value) {} |
2859 | + ValueType& value_; |
2860 | +}; |
2861 | + |
2862 | +//! Helper class for accessing Value of object type. |
2863 | +/*! |
2864 | + Instance of this helper class is obtained by \c GenericValue::GetObject(). |
2865 | + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. |
2866 | +*/ |
2867 | +template <bool Const, typename ValueT> |
2868 | +class GenericObject { |
2869 | +public: |
2870 | + typedef GenericObject<true, ValueT> ConstObject; |
2871 | + typedef GenericObject<false, ValueT> Object; |
2872 | + typedef ValueT PlainType; |
2873 | + typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; |
2874 | + typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator |
2875 | + typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator; |
2876 | + typedef typename ValueType::AllocatorType AllocatorType; |
2877 | + typedef typename ValueType::StringRefType StringRefType; |
2878 | + typedef typename ValueType::EncodingType EncodingType; |
2879 | + typedef typename ValueType::Ch Ch; |
2880 | + |
2881 | + template <typename, typename> |
2882 | + friend class GenericValue; |
2883 | + |
2884 | + GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} |
2885 | + GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } |
2886 | + ~GenericObject() {} |
2887 | + |
2888 | + SizeType MemberCount() const { return value_.MemberCount(); } |
2889 | + bool ObjectEmpty() const { return value_.ObjectEmpty(); } |
2890 | + template <typename T> ValueType& operator[](T* name) const { return value_[name]; } |
2891 | + template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; } |
2892 | +#if RAPIDJSON_HAS_STDSTRING |
2893 | + ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; } |
2894 | +#endif |
2895 | + MemberIterator MemberBegin() const { return value_.MemberBegin(); } |
2896 | + MemberIterator MemberEnd() const { return value_.MemberEnd(); } |
2897 | + bool HasMember(const Ch* name) const { return value_.HasMember(name); } |
2898 | +#if RAPIDJSON_HAS_STDSTRING |
2899 | + bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); } |
2900 | +#endif |
2901 | + template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); } |
2902 | + MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } |
2903 | + template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); } |
2904 | +#if RAPIDJSON_HAS_STDSTRING |
2905 | + MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); } |
2906 | +#endif |
2907 | + GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2908 | + GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2909 | +#if RAPIDJSON_HAS_STDSTRING |
2910 | + GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2911 | +#endif |
2912 | + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2913 | +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
2914 | + GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2915 | + GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2916 | + GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2917 | + GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2918 | +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS |
2919 | + GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2920 | + GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2921 | + template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } |
2922 | + void RemoveAllMembers() { return value_.RemoveAllMembers(); } |
2923 | + bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } |
2924 | +#if RAPIDJSON_HAS_STDSTRING |
2925 | + bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); } |
2926 | +#endif |
2927 | + template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); } |
2928 | + MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } |
2929 | + MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } |
2930 | + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } |
2931 | + bool EraseMember(const Ch* name) const { return value_.EraseMember(name); } |
2932 | +#if RAPIDJSON_HAS_STDSTRING |
2933 | + bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); } |
2934 | +#endif |
2935 | + template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); } |
2936 | + |
2937 | +#if RAPIDJSON_HAS_CXX11_RANGE_FOR |
2938 | + MemberIterator begin() const { return value_.MemberBegin(); } |
2939 | + MemberIterator end() const { return value_.MemberEnd(); } |
2940 | +#endif |
2941 | + |
2942 | +private: |
2943 | + GenericObject(); |
2944 | + GenericObject(ValueType& value) : value_(value) {} |
2945 | + ValueType& value_; |
2946 | +}; |
2947 | + |
2948 | RAPIDJSON_NAMESPACE_END |
2949 | |
2950 | #ifdef _MSC_VER |
2951 | |
2952 | === modified file 'shorts/xml2json/rapidjson/encodedstream.h' |
2953 | --- shorts/xml2json/rapidjson/encodedstream.h 2016-03-04 13:27:57 +0000 |
2954 | +++ shorts/xml2json/rapidjson/encodedstream.h 2016-06-15 16:13:25 +0000 |
2955 | @@ -15,7 +15,8 @@ |
2956 | #ifndef RAPIDJSON_ENCODEDSTREAM_H_ |
2957 | #define RAPIDJSON_ENCODEDSTREAM_H_ |
2958 | |
2959 | -#include "rapidjson.h" |
2960 | +#include "stream.h" |
2961 | +#include "memorystream.h" |
2962 | |
2963 | #ifdef __GNUC__ |
2964 | RAPIDJSON_DIAG_PUSH |
2965 | @@ -62,6 +63,34 @@ |
2966 | Ch current_; |
2967 | }; |
2968 | |
2969 | +//! Specialized for UTF8 MemoryStream. |
2970 | +template <> |
2971 | +class EncodedInputStream<UTF8<>, MemoryStream> { |
2972 | +public: |
2973 | + typedef UTF8<>::Ch Ch; |
2974 | + |
2975 | + EncodedInputStream(MemoryStream& is) : is_(is) { |
2976 | + if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take(); |
2977 | + if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take(); |
2978 | + if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take(); |
2979 | + } |
2980 | + Ch Peek() const { return is_.Peek(); } |
2981 | + Ch Take() { return is_.Take(); } |
2982 | + size_t Tell() const { return is_.Tell(); } |
2983 | + |
2984 | + // Not implemented |
2985 | + void Put(Ch) {} |
2986 | + void Flush() {} |
2987 | + Ch* PutBegin() { return 0; } |
2988 | + size_t PutEnd(Ch*) { return 0; } |
2989 | + |
2990 | + MemoryStream& is_; |
2991 | + |
2992 | +private: |
2993 | + EncodedInputStream(const EncodedInputStream&); |
2994 | + EncodedInputStream& operator=(const EncodedInputStream&); |
2995 | +}; |
2996 | + |
2997 | //! Output byte stream wrapper with statically bound encoding. |
2998 | /*! |
2999 | \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. |
3000 | |
3001 | === modified file 'shorts/xml2json/rapidjson/encodings.h' |
3002 | --- shorts/xml2json/rapidjson/encodings.h 2016-03-04 13:27:57 +0000 |
3003 | +++ shorts/xml2json/rapidjson/encodings.h 2016-06-15 16:13:25 +0000 |
3004 | @@ -120,6 +120,28 @@ |
3005 | } |
3006 | } |
3007 | |
3008 | + template<typename OutputStream> |
3009 | + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { |
3010 | + if (codepoint <= 0x7F) |
3011 | + PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); |
3012 | + else if (codepoint <= 0x7FF) { |
3013 | + PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF))); |
3014 | + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F)))); |
3015 | + } |
3016 | + else if (codepoint <= 0xFFFF) { |
3017 | + PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF))); |
3018 | + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); |
3019 | + PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F))); |
3020 | + } |
3021 | + else { |
3022 | + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); |
3023 | + PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF))); |
3024 | + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F))); |
3025 | + PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F))); |
3026 | + PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F))); |
3027 | + } |
3028 | + } |
3029 | + |
3030 | template <typename InputStream> |
3031 | static bool Decode(InputStream& is, unsigned* codepoint) { |
3032 | #define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu) |
3033 | @@ -261,6 +283,22 @@ |
3034 | } |
3035 | } |
3036 | |
3037 | + |
3038 | + template<typename OutputStream> |
3039 | + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { |
3040 | + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); |
3041 | + if (codepoint <= 0xFFFF) { |
3042 | + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair |
3043 | + PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint)); |
3044 | + } |
3045 | + else { |
3046 | + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); |
3047 | + unsigned v = codepoint - 0x10000; |
3048 | + PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); |
3049 | + PutUnsafe(os, (v & 0x3FF) | 0xDC00); |
3050 | + } |
3051 | + } |
3052 | + |
3053 | template <typename InputStream> |
3054 | static bool Decode(InputStream& is, unsigned* codepoint) { |
3055 | RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); |
3056 | @@ -386,6 +424,13 @@ |
3057 | os.Put(codepoint); |
3058 | } |
3059 | |
3060 | + template<typename OutputStream> |
3061 | + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { |
3062 | + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); |
3063 | + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); |
3064 | + PutUnsafe(os, codepoint); |
3065 | + } |
3066 | + |
3067 | template <typename InputStream> |
3068 | static bool Decode(InputStream& is, unsigned* codepoint) { |
3069 | RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); |
3070 | @@ -501,6 +546,12 @@ |
3071 | os.Put(static_cast<Ch>(codepoint & 0xFF)); |
3072 | } |
3073 | |
3074 | + template<typename OutputStream> |
3075 | + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { |
3076 | + RAPIDJSON_ASSERT(codepoint <= 0x7F); |
3077 | + PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); |
3078 | + } |
3079 | + |
3080 | template <typename InputStream> |
3081 | static bool Decode(InputStream& is, unsigned* codepoint) { |
3082 | uint8_t c = static_cast<uint8_t>(is.Take()); |
3083 | @@ -571,6 +622,13 @@ |
3084 | (*f[os.GetType()])(os, codepoint); |
3085 | } |
3086 | |
3087 | + template<typename OutputStream> |
3088 | + RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { |
3089 | + typedef void (*EncodeFunc)(OutputStream&, unsigned); |
3090 | + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) }; |
3091 | + (*f[os.GetType()])(os, codepoint); |
3092 | + } |
3093 | + |
3094 | template <typename InputStream> |
3095 | RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) { |
3096 | typedef bool (*DecodeFunc)(InputStream&, unsigned*); |
3097 | @@ -604,6 +662,15 @@ |
3098 | return true; |
3099 | } |
3100 | |
3101 | + template<typename InputStream, typename OutputStream> |
3102 | + RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) { |
3103 | + unsigned codepoint; |
3104 | + if (!SourceEncoding::Decode(is, &codepoint)) |
3105 | + return false; |
3106 | + TargetEncoding::EncodeUnsafe(os, codepoint); |
3107 | + return true; |
3108 | + } |
3109 | + |
3110 | //! Validate one Unicode codepoint from an encoded stream. |
3111 | template<typename InputStream, typename OutputStream> |
3112 | RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { |
3113 | @@ -611,6 +678,10 @@ |
3114 | } |
3115 | }; |
3116 | |
3117 | +// Forward declaration. |
3118 | +template<typename Stream> |
3119 | +inline void PutUnsafe(Stream& stream, typename Stream::Ch c); |
3120 | + |
3121 | //! Specialization of Transcoder with same source and target encoding. |
3122 | template<typename Encoding> |
3123 | struct Transcoder<Encoding, Encoding> { |
3124 | @@ -621,6 +692,12 @@ |
3125 | } |
3126 | |
3127 | template<typename InputStream, typename OutputStream> |
3128 | + RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) { |
3129 | + PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. |
3130 | + return true; |
3131 | + } |
3132 | + |
3133 | + template<typename InputStream, typename OutputStream> |
3134 | RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { |
3135 | return Encoding::Validate(is, os); // source/target encoding are the same |
3136 | } |
3137 | |
3138 | === modified file 'shorts/xml2json/rapidjson/filereadstream.h' |
3139 | --- shorts/xml2json/rapidjson/filereadstream.h 2016-03-04 13:27:57 +0000 |
3140 | +++ shorts/xml2json/rapidjson/filereadstream.h 2016-06-15 16:13:25 +0000 |
3141 | @@ -15,7 +15,7 @@ |
3142 | #ifndef RAPIDJSON_FILEREADSTREAM_H_ |
3143 | #define RAPIDJSON_FILEREADSTREAM_H_ |
3144 | |
3145 | -#include "rapidjson.h" |
3146 | +#include "stream.h" |
3147 | #include <cstdio> |
3148 | |
3149 | #ifdef __clang__ |
3150 | |
3151 | === modified file 'shorts/xml2json/rapidjson/filewritestream.h' |
3152 | --- shorts/xml2json/rapidjson/filewritestream.h 2016-03-04 13:27:57 +0000 |
3153 | +++ shorts/xml2json/rapidjson/filewritestream.h 2016-06-15 16:13:25 +0000 |
3154 | @@ -15,7 +15,7 @@ |
3155 | #ifndef RAPIDJSON_FILEWRITESTREAM_H_ |
3156 | #define RAPIDJSON_FILEWRITESTREAM_H_ |
3157 | |
3158 | -#include "rapidjson.h" |
3159 | +#include "stream.h" |
3160 | #include <cstdio> |
3161 | |
3162 | #ifdef __clang__ |
3163 | |
3164 | === added file 'shorts/xml2json/rapidjson/fwd.h' |
3165 | --- shorts/xml2json/rapidjson/fwd.h 1970-01-01 00:00:00 +0000 |
3166 | +++ shorts/xml2json/rapidjson/fwd.h 2016-06-15 16:13:25 +0000 |
3167 | @@ -0,0 +1,151 @@ |
3168 | +// Tencent is pleased to support the open source community by making RapidJSON available. |
3169 | +// |
3170 | +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. |
3171 | +// |
3172 | +// Licensed under the MIT License (the "License"); you may not use this file except |
3173 | +// in compliance with the License. You may obtain a copy of the License at |
3174 | +// |
3175 | +// http://opensource.org/licenses/MIT |
3176 | +// |
3177 | +// Unless required by applicable law or agreed to in writing, software distributed |
3178 | +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
3179 | +// CONDITIONS OF ANY KIND, either express or implied. See the License for the |
3180 | +// specific language governing permissions and limitations under the License. |
3181 | + |
3182 | +#ifndef RAPIDJSON_FWD_H_ |
3183 | +#define RAPIDJSON_FWD_H_ |
3184 | + |
3185 | +#include "rapidjson.h" |
3186 | + |
3187 | +RAPIDJSON_NAMESPACE_BEGIN |
3188 | + |
3189 | +// encodings.h |
3190 | + |
3191 | +template<typename CharType> struct UTF8; |
3192 | +template<typename CharType> struct UTF16; |
3193 | +template<typename CharType> struct UTF16BE; |
3194 | +template<typename CharType> struct UTF16LE; |
3195 | +template<typename CharType> struct UTF32; |
3196 | +template<typename CharType> struct UTF32BE; |
3197 | +template<typename CharType> struct UTF32LE; |
3198 | +template<typename CharType> struct ASCII; |
3199 | +template<typename CharType> struct AutoUTF; |
3200 | + |
3201 | +template<typename SourceEncoding, typename TargetEncoding> |
3202 | +struct Transcoder; |
3203 | + |
3204 | +// allocators.h |
3205 | + |
3206 | +class CrtAllocator; |
3207 | + |
3208 | +template <typename BaseAllocator> |
3209 | +class MemoryPoolAllocator; |
3210 | + |
3211 | +// stream.h |
3212 | + |
3213 | +template <typename Encoding> |
3214 | +struct GenericStringStream; |
3215 | + |
3216 | +typedef GenericStringStream<UTF8<char> > StringStream; |
3217 | + |
3218 | +template <typename Encoding> |
3219 | +struct GenericInsituStringStream; |
3220 | + |
3221 | +typedef GenericInsituStringStream<UTF8<char> > InsituStringStream; |
3222 | + |
3223 | +// stringbuffer.h |
3224 | + |
3225 | +template <typename Encoding, typename Allocator> |
3226 | +class GenericStringBuffer; |
3227 | + |
3228 | +typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer; |
3229 | + |
3230 | +// filereadstream.h |
3231 | + |
3232 | +class FileReadStream; |
3233 | + |
3234 | +// filewritestream.h |
3235 | + |
3236 | +class FileWriteStream; |
3237 | + |
3238 | +// memorybuffer.h |
3239 | + |
3240 | +template <typename Allocator> |
3241 | +struct GenericMemoryBuffer; |
3242 | + |
3243 | +typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer; |
3244 | + |
3245 | +// memorystream.h |
3246 | + |
3247 | +struct MemoryStream; |
3248 | + |
3249 | +// reader.h |
3250 | + |
3251 | +template<typename Encoding, typename Derived> |
3252 | +struct BaseReaderHandler; |
3253 | + |
3254 | +template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator> |
3255 | +class GenericReader; |
3256 | + |
3257 | +typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader; |
3258 | + |
3259 | +// writer.h |
3260 | + |
3261 | +template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> |
3262 | +class Writer; |
3263 | + |
3264 | +// prettywriter.h |
3265 | + |
3266 | +template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> |
3267 | +class PrettyWriter; |
3268 | + |
3269 | +// document.h |
3270 | + |
3271 | +template <typename Encoding, typename Allocator> |
3272 | +struct GenericMember; |
3273 | + |
3274 | +template <bool Const, typename Encoding, typename Allocator> |
3275 | +class GenericMemberIterator; |
3276 | + |
3277 | +template<typename CharType> |
3278 | +struct GenericStringRef; |
3279 | + |
3280 | +template <typename Encoding, typename Allocator> |
3281 | +class GenericValue; |
3282 | + |
3283 | +typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value; |
3284 | + |
3285 | +template <typename Encoding, typename Allocator, typename StackAllocator> |
3286 | +class GenericDocument; |
3287 | + |
3288 | +typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document; |
3289 | + |
3290 | +// pointer.h |
3291 | + |
3292 | +template <typename ValueType, typename Allocator> |
3293 | +class GenericPointer; |
3294 | + |
3295 | +typedef GenericPointer<Value, CrtAllocator> Pointer; |
3296 | + |
3297 | +// schema.h |
3298 | + |
3299 | +template <typename SchemaDocumentType> |
3300 | +class IGenericRemoteSchemaDocumentProvider; |
3301 | + |
3302 | +template <typename ValueT, typename Allocator> |
3303 | +class GenericSchemaDocument; |
3304 | + |
3305 | +typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument; |
3306 | +typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider; |
3307 | + |
3308 | +template < |
3309 | + typename SchemaDocumentType, |
3310 | + typename OutputHandler, |
3311 | + typename StateAllocator> |
3312 | +class GenericSchemaValidator; |
3313 | + |
3314 | +typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator; |
3315 | + |
3316 | +RAPIDJSON_NAMESPACE_END |
3317 | + |
3318 | +#endif // RAPIDJSON_RAPIDJSONFWD_H_ |
3319 | |
3320 | === modified file 'shorts/xml2json/rapidjson/internal/biginteger.h' (properties changed: -x to +x) |
3321 | === modified file 'shorts/xml2json/rapidjson/internal/diyfp.h' |
3322 | --- shorts/xml2json/rapidjson/internal/diyfp.h 2016-03-04 13:27:57 +0000 |
3323 | +++ shorts/xml2json/rapidjson/internal/diyfp.h 2016-06-15 16:13:25 +0000 |
3324 | @@ -41,7 +41,7 @@ |
3325 | #endif |
3326 | |
3327 | struct DiyFp { |
3328 | - DiyFp() {} |
3329 | + DiyFp() : f(), e() {} |
3330 | |
3331 | DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} |
3332 | |
3333 | |
3334 | === modified file 'shorts/xml2json/rapidjson/internal/dtoa.h' |
3335 | --- shorts/xml2json/rapidjson/internal/dtoa.h 2016-03-04 13:27:57 +0000 |
3336 | +++ shorts/xml2json/rapidjson/internal/dtoa.h 2016-06-15 16:13:25 +0000 |
3337 | @@ -29,6 +29,7 @@ |
3338 | #ifdef __GNUC__ |
3339 | RAPIDJSON_DIAG_PUSH |
3340 | RAPIDJSON_DIAG_OFF(effc++) |
3341 | +RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 |
3342 | #endif |
3343 | |
3344 | inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { |
3345 | @@ -145,10 +146,10 @@ |
3346 | return buffer; |
3347 | } |
3348 | |
3349 | -inline char* Prettify(char* buffer, int length, int k) { |
3350 | +inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { |
3351 | const int kk = length + k; // 10^(kk-1) <= v < 10^kk |
3352 | |
3353 | - if (length <= kk && kk <= 21) { |
3354 | + if (0 <= k && kk <= 21) { |
3355 | // 1234e7 -> 12340000000 |
3356 | for (int i = length; i < kk; i++) |
3357 | buffer[i] = '0'; |
3358 | @@ -160,7 +161,16 @@ |
3359 | // 1234e-2 -> 12.34 |
3360 | std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk)); |
3361 | buffer[kk] = '.'; |
3362 | - return &buffer[length + 1]; |
3363 | + if (0 > k + maxDecimalPlaces) { |
3364 | + // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 |
3365 | + // Remove extra trailing zeros (at least one) after truncation. |
3366 | + for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) |
3367 | + if (buffer[i] != '0') |
3368 | + return &buffer[i + 1]; |
3369 | + return &buffer[kk + 2]; // Reserve one zero |
3370 | + } |
3371 | + else |
3372 | + return &buffer[length + 1]; |
3373 | } |
3374 | else if (-6 < kk && kk <= 0) { |
3375 | // 1234e-6 -> 0.001234 |
3376 | @@ -170,7 +180,23 @@ |
3377 | buffer[1] = '.'; |
3378 | for (int i = 2; i < offset; i++) |
3379 | buffer[i] = '0'; |
3380 | - return &buffer[length + offset]; |
3381 | + if (length - kk > maxDecimalPlaces) { |
3382 | + // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 |
3383 | + // Remove extra trailing zeros (at least one) after truncation. |
3384 | + for (int i = maxDecimalPlaces + 1; i > 2; i--) |
3385 | + if (buffer[i] != '0') |
3386 | + return &buffer[i + 1]; |
3387 | + return &buffer[3]; // Reserve one zero |
3388 | + } |
3389 | + else |
3390 | + return &buffer[length + offset]; |
3391 | + } |
3392 | + else if (kk < -maxDecimalPlaces) { |
3393 | + // Truncate to zero |
3394 | + buffer[0] = '0'; |
3395 | + buffer[1] = '.'; |
3396 | + buffer[2] = '0'; |
3397 | + return &buffer[3]; |
3398 | } |
3399 | else if (length == 1) { |
3400 | // 1e30 |
3401 | @@ -186,7 +212,8 @@ |
3402 | } |
3403 | } |
3404 | |
3405 | -inline char* dtoa(double value, char* buffer) { |
3406 | +inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { |
3407 | + RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); |
3408 | Double d(value); |
3409 | if (d.IsZero()) { |
3410 | if (d.Sign()) |
3411 | @@ -203,7 +230,7 @@ |
3412 | } |
3413 | int length, K; |
3414 | Grisu2(value, buffer, &length, &K); |
3415 | - return Prettify(buffer, length, K); |
3416 | + return Prettify(buffer, length, K, maxDecimalPlaces); |
3417 | } |
3418 | } |
3419 | |
3420 | |
3421 | === modified file 'shorts/xml2json/rapidjson/internal/ieee754.h' |
3422 | --- shorts/xml2json/rapidjson/internal/ieee754.h 2016-03-04 13:27:57 +0000 |
3423 | +++ shorts/xml2json/rapidjson/internal/ieee754.h 2016-06-15 16:13:25 +0000 |
3424 | @@ -40,6 +40,7 @@ |
3425 | |
3426 | bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } |
3427 | bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } |
3428 | + bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } |
3429 | bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } |
3430 | bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } |
3431 | |
3432 | |
3433 | === added file 'shorts/xml2json/rapidjson/internal/regex.h' |
3434 | --- shorts/xml2json/rapidjson/internal/regex.h 1970-01-01 00:00:00 +0000 |
3435 | +++ shorts/xml2json/rapidjson/internal/regex.h 2016-06-15 16:13:25 +0000 |
3436 | @@ -0,0 +1,705 @@ |
3437 | +// Tencent is pleased to support the open source community by making RapidJSON available. |
3438 | +// |
3439 | +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. |
3440 | +// |
3441 | +// Licensed under the MIT License (the "License"); you may not use this file except |
3442 | +// in compliance with the License. You may obtain a copy of the License at |
3443 | +// |
3444 | +// http://opensource.org/licenses/MIT |
3445 | +// |
3446 | +// Unless required by applicable law or agreed to in writing, software distributed |
3447 | +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
3448 | +// CONDITIONS OF ANY KIND, either express or implied. See the License for the |
3449 | +// specific language governing permissions and limitations under the License. |
3450 | + |
3451 | +#ifndef RAPIDJSON_INTERNAL_REGEX_H_ |
3452 | +#define RAPIDJSON_INTERNAL_REGEX_H_ |
3453 | + |
3454 | +#include "../allocators.h" |
3455 | +#include "../stream.h" |
3456 | +#include "stack.h" |
3457 | + |
3458 | +#ifdef __clang__ |
3459 | +RAPIDJSON_DIAG_PUSH |
3460 | +RAPIDJSON_DIAG_OFF(padded) |
3461 | +RAPIDJSON_DIAG_OFF(switch-enum) |
3462 | +RAPIDJSON_DIAG_OFF(implicit-fallthrough) |
3463 | +#endif |
3464 | + |
3465 | +#ifdef __GNUC__ |
3466 | +RAPIDJSON_DIAG_PUSH |
3467 | +RAPIDJSON_DIAG_OFF(effc++) |
3468 | +#endif |
3469 | + |
3470 | +#ifdef _MSC_VER |
3471 | +RAPIDJSON_DIAG_PUSH |
3472 | +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated |
3473 | +#endif |
3474 | + |
3475 | +#ifndef RAPIDJSON_REGEX_VERBOSE |
3476 | +#define RAPIDJSON_REGEX_VERBOSE 0 |
3477 | +#endif |
3478 | + |
3479 | +RAPIDJSON_NAMESPACE_BEGIN |
3480 | +namespace internal { |
3481 | + |
3482 | +/////////////////////////////////////////////////////////////////////////////// |
3483 | +// GenericRegex |
3484 | + |
3485 | +static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 |
3486 | +static const SizeType kRegexInvalidRange = ~SizeType(0); |
3487 | + |
3488 | +//! Regular expression engine with subset of ECMAscript grammar. |
3489 | +/*! |
3490 | + Supported regular expression syntax: |
3491 | + - \c ab Concatenation |
3492 | + - \c a|b Alternation |
3493 | + - \c a? Zero or one |
3494 | + - \c a* Zero or more |
3495 | + - \c a+ One or more |
3496 | + - \c a{3} Exactly 3 times |
3497 | + - \c a{3,} At least 3 times |
3498 | + - \c a{3,5} 3 to 5 times |
3499 | + - \c (ab) Grouping |
3500 | + - \c ^a At the beginning |
3501 | + - \c a$ At the end |
3502 | + - \c . Any character |
3503 | + - \c [abc] Character classes |
3504 | + - \c [a-c] Character class range |
3505 | + - \c [a-z0-9_] Character class combination |
3506 | + - \c [^abc] Negated character classes |
3507 | + - \c [^a-c] Negated character class range |
3508 | + - \c [\b] Backspace (U+0008) |
3509 | + - \c \\| \\\\ ... Escape characters |
3510 | + - \c \\f Form feed (U+000C) |
3511 | + - \c \\n Line feed (U+000A) |
3512 | + - \c \\r Carriage return (U+000D) |
3513 | + - \c \\t Tab (U+0009) |
3514 | + - \c \\v Vertical tab (U+000B) |
3515 | + |
3516 | + \note This is a Thompson NFA engine, implemented with reference to |
3517 | + Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", |
3518 | + https://swtch.com/~rsc/regexp/regexp1.html |
3519 | +*/ |
3520 | +template <typename Encoding, typename Allocator = CrtAllocator> |
3521 | +class GenericRegex { |
3522 | +public: |
3523 | + typedef typename Encoding::Ch Ch; |
3524 | + |
3525 | + GenericRegex(const Ch* source, Allocator* allocator = 0) : |
3526 | + states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), |
3527 | + stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_() |
3528 | + { |
3529 | + GenericStringStream<Encoding> ss(source); |
3530 | + DecodedStream<GenericStringStream<Encoding> > ds(ss); |
3531 | + Parse(ds); |
3532 | + } |
3533 | + |
3534 | + ~GenericRegex() { |
3535 | + Allocator::Free(stateSet_); |
3536 | + } |
3537 | + |
3538 | + bool IsValid() const { |
3539 | + return root_ != kRegexInvalidState; |
3540 | + } |
3541 | + |
3542 | + template <typename InputStream> |
3543 | + bool Match(InputStream& is) const { |
3544 | + return SearchWithAnchoring(is, true, true); |
3545 | + } |
3546 | + |
3547 | + bool Match(const Ch* s) const { |
3548 | + GenericStringStream<Encoding> is(s); |
3549 | + return Match(is); |
3550 | + } |
3551 | + |
3552 | + template <typename InputStream> |
3553 | + bool Search(InputStream& is) const { |
3554 | + return SearchWithAnchoring(is, anchorBegin_, anchorEnd_); |
3555 | + } |
3556 | + |
3557 | + bool Search(const Ch* s) const { |
3558 | + GenericStringStream<Encoding> is(s); |
3559 | + return Search(is); |
3560 | + } |
3561 | + |
3562 | +private: |
3563 | + enum Operator { |
3564 | + kZeroOrOne, |
3565 | + kZeroOrMore, |
3566 | + kOneOrMore, |
3567 | + kConcatenation, |
3568 | + kAlternation, |
3569 | + kLeftParenthesis |
3570 | + }; |
3571 | + |
3572 | + static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.' |
3573 | + static const unsigned kRangeCharacterClass = 0xFFFFFFFE; |
3574 | + static const unsigned kRangeNegationFlag = 0x80000000; |
3575 | + |
3576 | + struct Range { |
3577 | + unsigned start; // |
3578 | + unsigned end; |
3579 | + SizeType next; |
3580 | + }; |
3581 | + |
3582 | + struct State { |
3583 | + SizeType out; //!< Equals to kInvalid for matching state |
3584 | + SizeType out1; //!< Equals to non-kInvalid for split |
3585 | + SizeType rangeStart; |
3586 | + unsigned codepoint; |
3587 | + }; |
3588 | + |
3589 | + struct Frag { |
3590 | + Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {} |
3591 | + SizeType start; |
3592 | + SizeType out; //!< link-list of all output states |
3593 | + SizeType minIndex; |
3594 | + }; |
3595 | + |
3596 | + template <typename SourceStream> |
3597 | + class DecodedStream { |
3598 | + public: |
3599 | + DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } |
3600 | + unsigned Peek() { return codepoint_; } |
3601 | + unsigned Take() { |
3602 | + unsigned c = codepoint_; |
3603 | + if (c) // No further decoding when '\0' |
3604 | + Decode(); |
3605 | + return c; |
3606 | + } |
3607 | + |
3608 | + private: |
3609 | + void Decode() { |
3610 | + if (!Encoding::Decode(ss_, &codepoint_)) |
3611 | + codepoint_ = 0; |
3612 | + } |
3613 | + |
3614 | + SourceStream& ss_; |
3615 | + unsigned codepoint_; |
3616 | + }; |
3617 | + |
3618 | + State& GetState(SizeType index) { |
3619 | + RAPIDJSON_ASSERT(index < stateCount_); |
3620 | + return states_.template Bottom<State>()[index]; |
3621 | + } |
3622 | + |
3623 | + const State& GetState(SizeType index) const { |
3624 | + RAPIDJSON_ASSERT(index < stateCount_); |
3625 | + return states_.template Bottom<State>()[index]; |
3626 | + } |
3627 | + |
3628 | + Range& GetRange(SizeType index) { |
3629 | + RAPIDJSON_ASSERT(index < rangeCount_); |
3630 | + return ranges_.template Bottom<Range>()[index]; |
3631 | + } |
3632 | + |
3633 | + const Range& GetRange(SizeType index) const { |
3634 | + RAPIDJSON_ASSERT(index < rangeCount_); |
3635 | + return ranges_.template Bottom<Range>()[index]; |
3636 | + } |
3637 | + |
3638 | + template <typename InputStream> |
3639 | + void Parse(DecodedStream<InputStream>& ds) { |
3640 | + Allocator allocator; |
3641 | + Stack<Allocator> operandStack(&allocator, 256); // Frag |
3642 | + Stack<Allocator> operatorStack(&allocator, 256); // Operator |
3643 | + Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis) |
3644 | + |
3645 | + *atomCountStack.template Push<unsigned>() = 0; |
3646 | + |
3647 | + unsigned codepoint; |
3648 | + while (ds.Peek() != 0) { |
3649 | + switch (codepoint = ds.Take()) { |
3650 | + case '^': |
3651 | + anchorBegin_ = true; |
3652 | + break; |
3653 | + |
3654 | + case '$': |
3655 | + anchorEnd_ = true; |
3656 | + break; |
3657 | + |
3658 | + case '|': |
3659 | + while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation) |
3660 | + if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) |
3661 | + return; |
3662 | + *operatorStack.template Push<Operator>() = kAlternation; |
3663 | + *atomCountStack.template Top<unsigned>() = 0; |
3664 | + break; |
3665 | + |
3666 | + case '(': |
3667 | + *operatorStack.template Push<Operator>() = kLeftParenthesis; |
3668 | + *atomCountStack.template Push<unsigned>() = 0; |
3669 | + break; |
3670 | + |
3671 | + case ')': |
3672 | + while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis) |
3673 | + if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) |
3674 | + return; |
3675 | + if (operatorStack.Empty()) |
3676 | + return; |
3677 | + operatorStack.template Pop<Operator>(1); |
3678 | + atomCountStack.template Pop<unsigned>(1); |
3679 | + ImplicitConcatenation(atomCountStack, operatorStack); |
3680 | + break; |
3681 | + |
3682 | + case '?': |
3683 | + if (!Eval(operandStack, kZeroOrOne)) |
3684 | + return; |
3685 | + break; |
3686 | + |
3687 | + case '*': |
3688 | + if (!Eval(operandStack, kZeroOrMore)) |
3689 | + return; |
3690 | + break; |
3691 | + |
3692 | + case '+': |
3693 | + if (!Eval(operandStack, kOneOrMore)) |
3694 | + return; |
3695 | + break; |
3696 | + |
3697 | + case '{': |
3698 | + { |
3699 | + unsigned n, m; |
3700 | + if (!ParseUnsigned(ds, &n)) |
3701 | + return; |
3702 | + |
3703 | + if (ds.Peek() == ',') { |
3704 | + ds.Take(); |
3705 | + if (ds.Peek() == '}') |
3706 | + m = kInfinityQuantifier; |
3707 | + else if (!ParseUnsigned(ds, &m) || m < n) |
3708 | + return; |
3709 | + } |
3710 | + else |
3711 | + m = n; |
3712 | + |
3713 | + if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}') |
3714 | + return; |
3715 | + ds.Take(); |
3716 | + } |
3717 | + break; |
3718 | + |
3719 | + case '.': |
3720 | + PushOperand(operandStack, kAnyCharacterClass); |
3721 | + ImplicitConcatenation(atomCountStack, operatorStack); |
3722 | + break; |
3723 | + |
3724 | + case '[': |
3725 | + { |
3726 | + SizeType range; |
3727 | + if (!ParseRange(ds, &range)) |
3728 | + return; |
3729 | + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass); |
3730 | + GetState(s).rangeStart = range; |
3731 | + *operandStack.template Push<Frag>() = Frag(s, s, s); |
3732 | + } |
3733 | + ImplicitConcatenation(atomCountStack, operatorStack); |
3734 | + break; |
3735 | + |
3736 | + case '\\': // Escape character |
3737 | + if (!CharacterEscape(ds, &codepoint)) |
3738 | + return; // Unsupported escape character |
3739 | + // fall through to default |
3740 | + |
3741 | + default: // Pattern character |
3742 | + PushOperand(operandStack, codepoint); |
3743 | + ImplicitConcatenation(atomCountStack, operatorStack); |
3744 | + } |
3745 | + } |
3746 | + |
3747 | + while (!operatorStack.Empty()) |
3748 | + if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1))) |
3749 | + return; |
3750 | + |
3751 | + // Link the operand to matching state. |
3752 | + if (operandStack.GetSize() == sizeof(Frag)) { |
3753 | + Frag* e = operandStack.template Pop<Frag>(1); |
3754 | + Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0)); |
3755 | + root_ = e->start; |
3756 | + |
3757 | +#if RAPIDJSON_REGEX_VERBOSE |
3758 | + printf("root: %d\n", root_); |
3759 | + for (SizeType i = 0; i < stateCount_ ; i++) { |
3760 | + State& s = GetState(i); |
3761 | + printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint); |
3762 | + } |
3763 | + printf("\n"); |
3764 | +#endif |
3765 | + } |
3766 | + |
3767 | + // Preallocate buffer for SearchWithAnchoring() |
3768 | + RAPIDJSON_ASSERT(stateSet_ == 0); |
3769 | + if (stateCount_ > 0) { |
3770 | + stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize())); |
3771 | + state0_.template Reserve<SizeType>(stateCount_); |
3772 | + state1_.template Reserve<SizeType>(stateCount_); |
3773 | + } |
3774 | + } |
3775 | + |
3776 | + SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { |
3777 | + State* s = states_.template Push<State>(); |
3778 | + s->out = out; |
3779 | + s->out1 = out1; |
3780 | + s->codepoint = codepoint; |
3781 | + s->rangeStart = kRegexInvalidRange; |
3782 | + return stateCount_++; |
3783 | + } |
3784 | + |
3785 | + void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) { |
3786 | + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); |
3787 | + *operandStack.template Push<Frag>() = Frag(s, s, s); |
3788 | + } |
3789 | + |
3790 | + void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) { |
3791 | + if (*atomCountStack.template Top<unsigned>()) |
3792 | + *operatorStack.template Push<Operator>() = kConcatenation; |
3793 | + (*atomCountStack.template Top<unsigned>())++; |
3794 | + } |
3795 | + |
3796 | + SizeType Append(SizeType l1, SizeType l2) { |
3797 | + SizeType old = l1; |
3798 | + while (GetState(l1).out != kRegexInvalidState) |
3799 | + l1 = GetState(l1).out; |
3800 | + GetState(l1).out = l2; |
3801 | + return old; |
3802 | + } |
3803 | + |
3804 | + void Patch(SizeType l, SizeType s) { |
3805 | + for (SizeType next; l != kRegexInvalidState; l = next) { |
3806 | + next = GetState(l).out; |
3807 | + GetState(l).out = s; |
3808 | + } |
3809 | + } |
3810 | + |
3811 | + bool Eval(Stack<Allocator>& operandStack, Operator op) { |
3812 | + switch (op) { |
3813 | + case kConcatenation: |
3814 | + if (operandStack.GetSize() >= sizeof(Frag) * 2) { |
3815 | + Frag e2 = *operandStack.template Pop<Frag>(1); |
3816 | + Frag e1 = *operandStack.template Pop<Frag>(1); |
3817 | + Patch(e1.out, e2.start); |
3818 | + *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex)); |
3819 | + return true; |
3820 | + } |
3821 | + return false; |
3822 | + |
3823 | + case kAlternation: |
3824 | + if (operandStack.GetSize() >= sizeof(Frag) * 2) { |
3825 | + Frag e2 = *operandStack.template Pop<Frag>(1); |
3826 | + Frag e1 = *operandStack.template Pop<Frag>(1); |
3827 | + SizeType s = NewState(e1.start, e2.start, 0); |
3828 | + *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex)); |
3829 | + return true; |
3830 | + } |
3831 | + return false; |
3832 | + |
3833 | + case kZeroOrOne: |
3834 | + if (operandStack.GetSize() >= sizeof(Frag)) { |
3835 | + Frag e = *operandStack.template Pop<Frag>(1); |
3836 | + SizeType s = NewState(kRegexInvalidState, e.start, 0); |
3837 | + *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex); |
3838 | + return true; |
3839 | + } |
3840 | + return false; |
3841 | + |
3842 | + case kZeroOrMore: |
3843 | + if (operandStack.GetSize() >= sizeof(Frag)) { |
3844 | + Frag e = *operandStack.template Pop<Frag>(1); |
3845 | + SizeType s = NewState(kRegexInvalidState, e.start, 0); |
3846 | + Patch(e.out, s); |
3847 | + *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex); |
3848 | + return true; |
3849 | + } |
3850 | + return false; |
3851 | + |
3852 | + case kOneOrMore: |
3853 | + if (operandStack.GetSize() >= sizeof(Frag)) { |
3854 | + Frag e = *operandStack.template Pop<Frag>(1); |
3855 | + SizeType s = NewState(kRegexInvalidState, e.start, 0); |
3856 | + Patch(e.out, s); |
3857 | + *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex); |
3858 | + return true; |
3859 | + } |
3860 | + return false; |
3861 | + |
3862 | + default: |
3863 | + return false; |
3864 | + } |
3865 | + } |
3866 | + |
3867 | + bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) { |
3868 | + RAPIDJSON_ASSERT(n <= m); |
3869 | + if (operandStack.GetSize() < sizeof(Frag)) |
3870 | + return false; |
3871 | + |
3872 | + if (n == 0) { |
3873 | + if (m == 0) // a{0} not support |
3874 | + return false; |
3875 | + else if (m == kInfinityQuantifier) |
3876 | + Eval(operandStack, kZeroOrMore); // a{0,} -> a* |
3877 | + else { |
3878 | + Eval(operandStack, kZeroOrOne); // a{0,5} -> a? |
3879 | + for (unsigned i = 0; i < m - 1; i++) |
3880 | + CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a? |
3881 | + for (unsigned i = 0; i < m - 1; i++) |
3882 | + Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a? |
3883 | + } |
3884 | + return true; |
3885 | + } |
3886 | + |
3887 | + for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a |
3888 | + CloneTopOperand(operandStack); |
3889 | + |
3890 | + if (m == kInfinityQuantifier) |
3891 | + Eval(operandStack, kOneOrMore); // a{3,} -> a a a+ |
3892 | + else if (m > n) { |
3893 | + CloneTopOperand(operandStack); // a{3,5} -> a a a a |
3894 | + Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a? |
3895 | + for (unsigned i = n; i < m - 1; i++) |
3896 | + CloneTopOperand(operandStack); // a{3,5} -> a a a a? a? |
3897 | + for (unsigned i = n; i < m; i++) |
3898 | + Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a? |
3899 | + } |
3900 | + |
3901 | + for (unsigned i = 0; i < n - 1; i++) |
3902 | + Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a? |
3903 | + |
3904 | + return true; |
3905 | + } |
3906 | + |
3907 | + static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; } |
3908 | + |
3909 | + void CloneTopOperand(Stack<Allocator>& operandStack) { |
3910 | + const Frag *src = operandStack.template Top<Frag>(); |
3911 | + SizeType count = stateCount_ - src->minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) |
3912 | + State* s = states_.template Push<State>(count); |
3913 | + memcpy(s, &GetState(src->minIndex), count * sizeof(State)); |
3914 | + for (SizeType j = 0; j < count; j++) { |
3915 | + if (s[j].out != kRegexInvalidState) |
3916 | + s[j].out += count; |
3917 | + if (s[j].out1 != kRegexInvalidState) |
3918 | + s[j].out1 += count; |
3919 | + } |
3920 | + *operandStack.template Push<Frag>() = Frag(src->start + count, src->out + count, src->minIndex + count); |
3921 | + stateCount_ += count; |
3922 | + } |
3923 | + |
3924 | + template <typename InputStream> |
3925 | + bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) { |
3926 | + unsigned r = 0; |
3927 | + if (ds.Peek() < '0' || ds.Peek() > '9') |
3928 | + return false; |
3929 | + while (ds.Peek() >= '0' && ds.Peek() <= '9') { |
3930 | + if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295 |
3931 | + return false; // overflow |
3932 | + r = r * 10 + (ds.Take() - '0'); |
3933 | + } |
3934 | + *u = r; |
3935 | + return true; |
3936 | + } |
3937 | + |
3938 | + template <typename InputStream> |
3939 | + bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) { |
3940 | + bool isBegin = true; |
3941 | + bool negate = false; |
3942 | + int step = 0; |
3943 | + SizeType start = kRegexInvalidRange; |
3944 | + SizeType current = kRegexInvalidRange; |
3945 | + unsigned codepoint; |
3946 | + while ((codepoint = ds.Take()) != 0) { |
3947 | + if (isBegin) { |
3948 | + isBegin = false; |
3949 | + if (codepoint == '^') { |
3950 | + negate = true; |
3951 | + continue; |
3952 | + } |
3953 | + } |
3954 | + |
3955 | + switch (codepoint) { |
3956 | + case ']': |
3957 | + if (start == kRegexInvalidRange) |
3958 | + return false; // Error: nothing inside [] |
3959 | + if (step == 2) { // Add trailing '-' |
3960 | + SizeType r = NewRange('-'); |
3961 | + RAPIDJSON_ASSERT(current != kRegexInvalidRange); |
3962 | + GetRange(current).next = r; |
3963 | + } |
3964 | + if (negate) |
3965 | + GetRange(start).start |= kRangeNegationFlag; |
3966 | + *range = start; |
3967 | + return true; |
3968 | + |
3969 | + case '\\': |
3970 | + if (ds.Peek() == 'b') { |
3971 | + ds.Take(); |
3972 | + codepoint = 0x0008; // Escape backspace character |
3973 | + } |
3974 | + else if (!CharacterEscape(ds, &codepoint)) |
3975 | + return false; |
3976 | + // fall through to default |
3977 | + |
3978 | + default: |
3979 | + switch (step) { |
3980 | + case 1: |
3981 | + if (codepoint == '-') { |
3982 | + step++; |
3983 | + break; |
3984 | + } |
3985 | + // fall through to step 0 for other characters |
3986 | + |
3987 | + case 0: |
3988 | + { |
3989 | + SizeType r = NewRange(codepoint); |
3990 | + if (current != kRegexInvalidRange) |
3991 | + GetRange(current).next = r; |
3992 | + if (start == kRegexInvalidRange) |
3993 | + start = r; |
3994 | + current = r; |
3995 | + } |
3996 | + step = 1; |
3997 | + break; |
3998 | + |
3999 | + default: |
4000 | + RAPIDJSON_ASSERT(step == 2); |
4001 | + GetRange(current).end = codepoint; |
4002 | + step = 0; |
4003 | + } |
4004 | + } |
4005 | + } |
4006 | + return false; |
4007 | + } |
4008 | + |
4009 | + SizeType NewRange(unsigned codepoint) { |
4010 | + Range* r = ranges_.template Push<Range>(); |
4011 | + r->start = r->end = codepoint; |
4012 | + r->next = kRegexInvalidRange; |
4013 | + return rangeCount_++; |
4014 | + } |
4015 | + |
4016 | + template <typename InputStream> |
4017 | + bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) { |
4018 | + unsigned codepoint; |
4019 | + switch (codepoint = ds.Take()) { |
4020 | + case '^': |
4021 | + case '$': |
4022 | + case '|': |
4023 | + case '(': |
4024 | + case ')': |
4025 | + case '?': |
4026 | + case '*': |
4027 | + case '+': |
4028 | + case '.': |
4029 | + case '[': |
4030 | + case ']': |
4031 | + case '{': |
4032 | + case '}': |
4033 | + case '\\': |
4034 | + *escapedCodepoint = codepoint; return true; |
4035 | + case 'f': *escapedCodepoint = 0x000C; return true; |
4036 | + case 'n': *escapedCodepoint = 0x000A; return true; |
4037 | + case 'r': *escapedCodepoint = 0x000D; return true; |
4038 | + case 't': *escapedCodepoint = 0x0009; return true; |
4039 | + case 'v': *escapedCodepoint = 0x000B; return true; |
4040 | + default: |
4041 | + return false; // Unsupported escape character |
4042 | + } |
4043 | + } |
4044 | + |
4045 | + template <typename InputStream> |
4046 | + bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const { |
4047 | + RAPIDJSON_ASSERT(IsValid()); |
4048 | + DecodedStream<InputStream> ds(is); |
4049 | + |
4050 | + state0_.Clear(); |
4051 | + Stack<Allocator> *current = &state0_, *next = &state1_; |
4052 | + const size_t stateSetSize = GetStateSetSize(); |
4053 | + std::memset(stateSet_, 0, stateSetSize); |
4054 | + |
4055 | + bool matched = AddState(*current, root_); |
4056 | + unsigned codepoint; |
4057 | + while (!current->Empty() && (codepoint = ds.Take()) != 0) { |
4058 | + std::memset(stateSet_, 0, stateSetSize); |
4059 | + next->Clear(); |
4060 | + matched = false; |
4061 | + for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) { |
4062 | + const State& sr = GetState(*s); |
4063 | + if (sr.codepoint == codepoint || |
4064 | + sr.codepoint == kAnyCharacterClass || |
4065 | + (sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) |
4066 | + { |
4067 | + matched = AddState(*next, sr.out) || matched; |
4068 | + if (!anchorEnd && matched) |
4069 | + return true; |
4070 | + } |
4071 | + if (!anchorBegin) |
4072 | + AddState(*next, root_); |
4073 | + } |
4074 | + internal::Swap(current, next); |
4075 | + } |
4076 | + |
4077 | + return matched; |
4078 | + } |
4079 | + |
4080 | + size_t GetStateSetSize() const { |
4081 | + return (stateCount_ + 31) / 32 * 4; |
4082 | + } |
4083 | + |
4084 | + // Return whether the added states is a match state |
4085 | + bool AddState(Stack<Allocator>& l, SizeType index) const { |
4086 | + if (index == kRegexInvalidState) |
4087 | + return true; |
4088 | + |
4089 | + const State& s = GetState(index); |
4090 | + if (s.out1 != kRegexInvalidState) { // Split |
4091 | + bool matched = AddState(l, s.out); |
4092 | + return AddState(l, s.out1) || matched; |
4093 | + } |
4094 | + else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) { |
4095 | + stateSet_[index >> 5] |= (1 << (index & 31)); |
4096 | + *l.template PushUnsafe<SizeType>() = index; |
4097 | + } |
4098 | + return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. |
4099 | + } |
4100 | + |
4101 | + bool MatchRange(SizeType rangeIndex, unsigned codepoint) const { |
4102 | + bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0; |
4103 | + while (rangeIndex != kRegexInvalidRange) { |
4104 | + const Range& r = GetRange(rangeIndex); |
4105 | + if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end) |
4106 | + return yes; |
4107 | + rangeIndex = r.next; |
4108 | + } |
4109 | + return !yes; |
4110 | + } |
4111 | + |
4112 | + Stack<Allocator> states_; |
4113 | + Stack<Allocator> ranges_; |
4114 | + SizeType root_; |
4115 | + SizeType stateCount_; |
4116 | + SizeType rangeCount_; |
4117 | + |
4118 | + static const unsigned kInfinityQuantifier = ~0u; |
4119 | + |
4120 | + // For SearchWithAnchoring() |
4121 | + uint32_t* stateSet_; // allocated by states_.GetAllocator() |
4122 | + mutable Stack<Allocator> state0_; |
4123 | + mutable Stack<Allocator> state1_; |
4124 | + bool anchorBegin_; |
4125 | + bool anchorEnd_; |
4126 | +}; |
4127 | + |
4128 | +typedef GenericRegex<UTF8<> > Regex; |
4129 | + |
4130 | +} // namespace internal |
4131 | +RAPIDJSON_NAMESPACE_END |
4132 | + |
4133 | +#ifdef __clang__ |
4134 | +RAPIDJSON_DIAG_POP |
4135 | +#endif |
4136 | + |
4137 | +#ifdef _MSC_VER |
4138 | +RAPIDJSON_DIAG_POP |
4139 | +#endif |
4140 | + |
4141 | +#endif // RAPIDJSON_INTERNAL_REGEX_H_ |
4142 | |
4143 | === modified file 'shorts/xml2json/rapidjson/internal/stack.h' |
4144 | --- shorts/xml2json/rapidjson/internal/stack.h 2016-03-04 13:27:57 +0000 |
4145 | +++ shorts/xml2json/rapidjson/internal/stack.h 2016-06-15 16:13:25 +0000 |
4146 | @@ -15,9 +15,14 @@ |
4147 | #ifndef RAPIDJSON_INTERNAL_STACK_H_ |
4148 | #define RAPIDJSON_INTERNAL_STACK_H_ |
4149 | |
4150 | -#include "../rapidjson.h" |
4151 | +#include "../allocators.h" |
4152 | #include "swap.h" |
4153 | |
4154 | +#if defined(__clang__) |
4155 | +RAPIDJSON_DIAG_PUSH |
4156 | +RAPIDJSON_DIAG_OFF(c++98-compat) |
4157 | +#endif |
4158 | + |
4159 | RAPIDJSON_NAMESPACE_BEGIN |
4160 | namespace internal { |
4161 | |
4162 | @@ -33,7 +38,6 @@ |
4163 | // Optimization note: Do not allocate memory for stack_ in constructor. |
4164 | // Do it lazily when first Push() -> Expand() -> Resize(). |
4165 | Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { |
4166 | - RAPIDJSON_ASSERT(stackCapacity > 0); |
4167 | } |
4168 | |
4169 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS |
4170 | @@ -108,11 +112,21 @@ |
4171 | // Optimization note: try to minimize the size of this function for force inline. |
4172 | // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. |
4173 | template<typename T> |
4174 | - RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { |
4175 | + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { |
4176 | // Expand the stack if needed |
4177 | - if (stackTop_ + sizeof(T) * count >= stackEnd_) |
4178 | + if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_)) |
4179 | Expand<T>(count); |
4180 | - |
4181 | + } |
4182 | + |
4183 | + template<typename T> |
4184 | + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { |
4185 | + Reserve<T>(count); |
4186 | + return PushUnsafe<T>(count); |
4187 | + } |
4188 | + |
4189 | + template<typename T> |
4190 | + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { |
4191 | + RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_); |
4192 | T* ret = reinterpret_cast<T*>(stackTop_); |
4193 | stackTop_ += sizeof(T) * count; |
4194 | return ret; |
4195 | @@ -132,8 +146,23 @@ |
4196 | } |
4197 | |
4198 | template<typename T> |
4199 | + const T* Top() const { |
4200 | + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); |
4201 | + return reinterpret_cast<T*>(stackTop_ - sizeof(T)); |
4202 | + } |
4203 | + |
4204 | + template<typename T> |
4205 | + T* End() { return reinterpret_cast<T*>(stackTop_); } |
4206 | + |
4207 | + template<typename T> |
4208 | + const T* End() const { return reinterpret_cast<T*>(stackTop_); } |
4209 | + |
4210 | + template<typename T> |
4211 | T* Bottom() { return reinterpret_cast<T*>(stack_); } |
4212 | |
4213 | + template<typename T> |
4214 | + const T* Bottom() const { return reinterpret_cast<T*>(stack_); } |
4215 | + |
4216 | bool HasAllocator() const { |
4217 | return allocator_ != 0; |
4218 | } |
4219 | @@ -142,6 +171,7 @@ |
4220 | RAPIDJSON_ASSERT(allocator_); |
4221 | return *allocator_; |
4222 | } |
4223 | + |
4224 | bool Empty() const { return stackTop_ == stack_; } |
4225 | size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); } |
4226 | size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } |
4227 | @@ -193,4 +223,8 @@ |
4228 | } // namespace internal |
4229 | RAPIDJSON_NAMESPACE_END |
4230 | |
4231 | +#if defined(__clang__) |
4232 | +RAPIDJSON_DIAG_POP |
4233 | +#endif |
4234 | + |
4235 | #endif // RAPIDJSON_STACK_H_ |
4236 | |
4237 | === modified file 'shorts/xml2json/rapidjson/internal/strfunc.h' |
4238 | --- shorts/xml2json/rapidjson/internal/strfunc.h 2016-03-04 13:27:57 +0000 |
4239 | +++ shorts/xml2json/rapidjson/internal/strfunc.h 2016-06-15 16:13:25 +0000 |
4240 | @@ -15,7 +15,7 @@ |
4241 | #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ |
4242 | #define RAPIDJSON_INTERNAL_STRFUNC_H_ |
4243 | |
4244 | -#include "../rapidjson.h" |
4245 | +#include "../stream.h" |
4246 | |
4247 | RAPIDJSON_NAMESPACE_BEGIN |
4248 | namespace internal { |
4249 | @@ -33,6 +33,22 @@ |
4250 | return SizeType(p - s); |
4251 | } |
4252 | |
4253 | +//! Returns number of code points in a encoded string. |
4254 | +template<typename Encoding> |
4255 | +bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { |
4256 | + GenericStringStream<Encoding> is(s); |
4257 | + const typename Encoding::Ch* end = s + length; |
4258 | + SizeType count = 0; |
4259 | + while (is.src_ < end) { |
4260 | + unsigned codepoint; |
4261 | + if (!Encoding::Decode(is, &codepoint)) |
4262 | + return false; |
4263 | + count++; |
4264 | + } |
4265 | + *outCount = count; |
4266 | + return true; |
4267 | +} |
4268 | + |
4269 | } // namespace internal |
4270 | RAPIDJSON_NAMESPACE_END |
4271 | |
4272 | |
4273 | === modified file 'shorts/xml2json/rapidjson/internal/strtod.h' |
4274 | --- shorts/xml2json/rapidjson/internal/strtod.h 2016-03-04 13:27:57 +0000 |
4275 | +++ shorts/xml2json/rapidjson/internal/strtod.h 2016-06-15 16:13:25 +0000 |
4276 | @@ -15,7 +15,6 @@ |
4277 | #ifndef RAPIDJSON_STRTOD_ |
4278 | #define RAPIDJSON_STRTOD_ |
4279 | |
4280 | -#include "../rapidjson.h" |
4281 | #include "ieee754.h" |
4282 | #include "biginteger.h" |
4283 | #include "diyfp.h" |
4284 | |
4285 | === modified file 'shorts/xml2json/rapidjson/internal/swap.h' |
4286 | --- shorts/xml2json/rapidjson/internal/swap.h 2016-03-04 13:27:57 +0000 |
4287 | +++ shorts/xml2json/rapidjson/internal/swap.h 2016-06-15 16:13:25 +0000 |
4288 | @@ -17,6 +17,11 @@ |
4289 | |
4290 | #include "../rapidjson.h" |
4291 | |
4292 | +#if defined(__clang__) |
4293 | +RAPIDJSON_DIAG_PUSH |
4294 | +RAPIDJSON_DIAG_OFF(c++98-compat) |
4295 | +#endif |
4296 | + |
4297 | RAPIDJSON_NAMESPACE_BEGIN |
4298 | namespace internal { |
4299 | |
4300 | @@ -34,4 +39,8 @@ |
4301 | } // namespace internal |
4302 | RAPIDJSON_NAMESPACE_END |
4303 | |
4304 | +#if defined(__clang__) |
4305 | +RAPIDJSON_DIAG_POP |
4306 | +#endif |
4307 | + |
4308 | #endif // RAPIDJSON_INTERNAL_SWAP_H_ |
4309 | |
4310 | === added file 'shorts/xml2json/rapidjson/istreamwrapper.h' |
4311 | --- shorts/xml2json/rapidjson/istreamwrapper.h 1970-01-01 00:00:00 +0000 |
4312 | +++ shorts/xml2json/rapidjson/istreamwrapper.h 2016-06-15 16:13:25 +0000 |
4313 | @@ -0,0 +1,110 @@ |
4314 | +// Tencent is pleased to support the open source community by making RapidJSON available. |
4315 | +// |
4316 | +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. |
4317 | +// |
4318 | +// Licensed under the MIT License (the "License"); you may not use this file except |
4319 | +// in compliance with the License. You may obtain a copy of the License at |
4320 | +// |
4321 | +// http://opensource.org/licenses/MIT |
4322 | +// |
4323 | +// Unless required by applicable law or agreed to in writing, software distributed |
4324 | +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
4325 | +// CONDITIONS OF ANY KIND, either express or implied. See the License for the |
4326 | +// specific language governing permissions and limitations under the License. |
4327 | + |
4328 | +#include "stream.h" |
4329 | +#include <iosfwd> |
4330 | + |
4331 | +#ifdef __clang__ |
4332 | +RAPIDJSON_DIAG_PUSH |
4333 | +RAPIDJSON_DIAG_OFF(padded) |
4334 | +#endif |
4335 | + |
4336 | +#ifdef _MSC_VER |
4337 | +RAPIDJSON_DIAG_PUSH |
4338 | +RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized |
4339 | +#endif |
4340 | + |
4341 | +RAPIDJSON_NAMESPACE_BEGIN |
4342 | + |
4343 | +//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. |
4344 | +/*! |
4345 | + The classes can be wrapped including but not limited to: |
4346 | + |
4347 | + - \c std::istringstream |
4348 | + - \c std::stringstream |
4349 | + - \c std::wistringstream |
4350 | + - \c std::wstringstream |
4351 | + - \c std::ifstream |
4352 | + - \c std::fstream |
4353 | + - \c std::wifstream |
4354 | + - \c std::wfstream |
4355 | + |
4356 | + \tparam StreamType Class derived from \c std::basic_istream. |
4357 | +*/ |
4358 | + |
4359 | +template <typename StreamType> |
4360 | +class BasicIStreamWrapper { |
4361 | +public: |
4362 | + typedef typename StreamType::char_type Ch; |
4363 | + BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {} |
4364 | + |
4365 | + Ch Peek() const { |
4366 | + typename StreamType::int_type c = stream_.peek(); |
4367 | + return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0'; |
4368 | + } |
4369 | + |
4370 | + Ch Take() { |
4371 | + typename StreamType::int_type c = stream_.get(); |
4372 | + if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) { |
4373 | + count_++; |
4374 | + return static_cast<Ch>(c); |
4375 | + } |
4376 | + else |
4377 | + return '\0'; |
4378 | + } |
4379 | + |
4380 | + // tellg() may return -1 when failed. So we count by ourself. |
4381 | + size_t Tell() const { return count_; } |
4382 | + |
4383 | + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } |
4384 | + void Put(Ch) { RAPIDJSON_ASSERT(false); } |
4385 | + void Flush() { RAPIDJSON_ASSERT(false); } |
4386 | + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } |
4387 | + |
4388 | + // For encoding detection only. |
4389 | + const Ch* Peek4() const { |
4390 | + RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream. |
4391 | + int i; |
4392 | + bool hasError = false; |
4393 | + for (i = 0; i < 4; ++i) { |
4394 | + typename StreamType::int_type c = stream_.get(); |
4395 | + if (c == StreamType::traits_type::eof()) { |
4396 | + hasError = true; |
4397 | + stream_.clear(); |
4398 | + break; |
4399 | + } |
4400 | + peekBuffer_[i] = static_cast<Ch>(c); |
4401 | + } |
4402 | + for (--i; i >= 0; --i) |
4403 | + stream_.putback(peekBuffer_[i]); |
4404 | + return !hasError ? peekBuffer_ : 0; |
4405 | + } |
4406 | + |
4407 | +private: |
4408 | + BasicIStreamWrapper(const BasicIStreamWrapper&); |
4409 | + BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); |
4410 | + |
4411 | + StreamType& stream_; |
4412 | + size_t count_; //!< Number of characters read. Note: |
4413 | + mutable Ch peekBuffer_[4]; |
4414 | +}; |
4415 | + |
4416 | +typedef BasicIStreamWrapper<std::istream> IStreamWrapper; |
4417 | +typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper; |
4418 | + |
4419 | +#if defined(__clang__) || defined(_MSC_VER) |
4420 | +RAPIDJSON_DIAG_POP |
4421 | +#endif |
4422 | + |
4423 | +RAPIDJSON_NAMESPACE_END |
4424 | |
4425 | === modified file 'shorts/xml2json/rapidjson/memorybuffer.h' |
4426 | --- shorts/xml2json/rapidjson/memorybuffer.h 2016-03-04 13:27:57 +0000 |
4427 | +++ shorts/xml2json/rapidjson/memorybuffer.h 2016-06-15 16:13:25 +0000 |
4428 | @@ -15,7 +15,7 @@ |
4429 | #ifndef RAPIDJSON_MEMORYBUFFER_H_ |
4430 | #define RAPIDJSON_MEMORYBUFFER_H_ |
4431 | |
4432 | -#include "rapidjson.h" |
4433 | +#include "stream.h" |
4434 | #include "internal/stack.h" |
4435 | |
4436 | RAPIDJSON_NAMESPACE_BEGIN |
4437 | |
4438 | === modified file 'shorts/xml2json/rapidjson/memorystream.h' |
4439 | --- shorts/xml2json/rapidjson/memorystream.h 2016-03-04 13:27:57 +0000 |
4440 | +++ shorts/xml2json/rapidjson/memorystream.h 2016-06-15 16:13:25 +0000 |
4441 | @@ -15,7 +15,7 @@ |
4442 | #ifndef RAPIDJSON_MEMORYSTREAM_H_ |
4443 | #define RAPIDJSON_MEMORYSTREAM_H_ |
4444 | |
4445 | -#include "rapidjson.h" |
4446 | +#include "stream.h" |
4447 | |
4448 | #ifdef __clang__ |
4449 | RAPIDJSON_DIAG_PUSH |
4450 | @@ -42,8 +42,8 @@ |
4451 | |
4452 | MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} |
4453 | |
4454 | - Ch Peek() const { return (src_ == end_) ? '\0' : *src_; } |
4455 | - Ch Take() { return (src_ == end_) ? '\0' : *src_++; } |
4456 | + Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } |
4457 | + Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } |
4458 | size_t Tell() const { return static_cast<size_t>(src_ - begin_); } |
4459 | |
4460 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } |
4461 | |
4462 | === added file 'shorts/xml2json/rapidjson/ostreamwrapper.h' |
4463 | --- shorts/xml2json/rapidjson/ostreamwrapper.h 1970-01-01 00:00:00 +0000 |
4464 | +++ shorts/xml2json/rapidjson/ostreamwrapper.h 2016-06-15 16:13:25 +0000 |
4465 | @@ -0,0 +1,76 @@ |
4466 | +// Tencent is pleased to support the open source community by making RapidJSON available. |
4467 | +// |
4468 | +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. |
4469 | +// |
4470 | +// Licensed under the MIT License (the "License"); you may not use this file except |
4471 | +// in compliance with the License. You may obtain a copy of the License at |
4472 | +// |
4473 | +// http://opensource.org/licenses/MIT |
4474 | +// |
4475 | +// Unless required by applicable law or agreed to in writing, software distributed |
4476 | +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
4477 | +// CONDITIONS OF ANY KIND, either express or implied. See the License for the |
4478 | +// specific language governing permissions and limitations under the License. |
4479 | + |
4480 | +#include "stream.h" |
4481 | +#include <iosfwd> |
4482 | + |
4483 | +#ifdef __clang__ |
4484 | +RAPIDJSON_DIAG_PUSH |
4485 | +RAPIDJSON_DIAG_OFF(padded) |
4486 | +#endif |
4487 | + |
4488 | +RAPIDJSON_NAMESPACE_BEGIN |
4489 | + |
4490 | +//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept. |
4491 | +/*! |
4492 | + The classes can be wrapped including but not limited to: |
4493 | + |
4494 | + - \c std::ostringstream |
4495 | + - \c std::stringstream |
4496 | + - \c std::wpstringstream |
4497 | + - \c std::wstringstream |
4498 | + - \c std::ifstream |
4499 | + - \c std::fstream |
4500 | + - \c std::wofstream |
4501 | + - \c std::wfstream |
4502 | + |
4503 | + \tparam StreamType Class derived from \c std::basic_ostream. |
4504 | +*/ |
4505 | + |
4506 | +template <typename StreamType> |
4507 | +class BasicOStreamWrapper { |
4508 | +public: |
4509 | + typedef typename StreamType::char_type Ch; |
4510 | + BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} |
4511 | + |
4512 | + void Put(Ch c) { |
4513 | + stream_.put(c); |
4514 | + } |
4515 | + |
4516 | + void Flush() { |
4517 | + stream_.flush(); |
4518 | + } |
4519 | + |
4520 | + // Not implemented |
4521 | + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } |
4522 | + char Take() { RAPIDJSON_ASSERT(false); return 0; } |
4523 | + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } |
4524 | + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } |
4525 | + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } |
4526 | + |
4527 | +private: |
4528 | + BasicOStreamWrapper(const BasicOStreamWrapper&); |
4529 | + BasicOStreamWrapper& operator=(const BasicOStreamWrapper&); |
4530 | + |
4531 | + StreamType& stream_; |
4532 | +}; |
4533 | + |
4534 | +typedef BasicOStreamWrapper<std::ostream> OStreamWrapper; |
4535 | +typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper; |
4536 | + |
4537 | +#ifdef __clang__ |
4538 | +RAPIDJSON_DIAG_POP |
4539 | +#endif |
4540 | + |
4541 | +RAPIDJSON_NAMESPACE_END |
4542 | |
4543 | === modified file 'shorts/xml2json/rapidjson/pointer.h' |
4544 | --- shorts/xml2json/rapidjson/pointer.h 2016-03-04 13:27:57 +0000 |
4545 | +++ shorts/xml2json/rapidjson/pointer.h 2016-06-15 16:13:25 +0000 |
4546 | @@ -23,6 +23,11 @@ |
4547 | RAPIDJSON_DIAG_OFF(switch-enum) |
4548 | #endif |
4549 | |
4550 | +#ifdef _MSC_VER |
4551 | +RAPIDJSON_DIAG_PUSH |
4552 | +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated |
4553 | +#endif |
4554 | + |
4555 | RAPIDJSON_NAMESPACE_BEGIN |
4556 | |
4557 | static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token |
4558 | @@ -101,7 +106,7 @@ |
4559 | //@{ |
4560 | |
4561 | //! Default constructor. |
4562 | - GenericPointer() : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} |
4563 | + GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} |
4564 | |
4565 | //! Constructor that parses a string or URI fragment representation. |
4566 | /*! |
4567 | @@ -160,7 +165,7 @@ |
4568 | GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} |
4569 | |
4570 | //! Copy constructor. |
4571 | - GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { |
4572 | + GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { |
4573 | *this = rhs; |
4574 | } |
4575 | |
4576 | @@ -305,6 +310,9 @@ |
4577 | |
4578 | //@} |
4579 | |
4580 | + //! Get the allocator of this pointer. |
4581 | + Allocator& GetAllocator() { return *allocator_; } |
4582 | + |
4583 | //!@name Tokens |
4584 | //@{ |
4585 | |
4586 | @@ -457,9 +465,18 @@ |
4587 | //! Query a value in a subtree. |
4588 | /*! |
4589 | \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. |
4590 | + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. |
4591 | \return Pointer to the value if it can be resolved. Otherwise null. |
4592 | + |
4593 | + \note |
4594 | + There are only 3 situations when a value cannot be resolved: |
4595 | + 1. A value in the path is not an array nor object. |
4596 | + 2. An object value does not contain the token. |
4597 | + 3. A token is out of range of an array value. |
4598 | + |
4599 | + Use unresolvedTokenIndex to retrieve the token index. |
4600 | */ |
4601 | - ValueType* Get(ValueType& root) const { |
4602 | + ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { |
4603 | RAPIDJSON_ASSERT(IsValid()); |
4604 | ValueType* v = &root; |
4605 | for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { |
4606 | @@ -468,18 +485,23 @@ |
4607 | { |
4608 | typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); |
4609 | if (m == v->MemberEnd()) |
4610 | - return 0; |
4611 | + break; |
4612 | v = &m->value; |
4613 | } |
4614 | - break; |
4615 | + continue; |
4616 | case kArrayType: |
4617 | if (t->index == kPointerInvalidIndex || t->index >= v->Size()) |
4618 | - return 0; |
4619 | + break; |
4620 | v = &((*v)[t->index]); |
4621 | - break; |
4622 | + continue; |
4623 | default: |
4624 | - return 0; |
4625 | + break; |
4626 | } |
4627 | + |
4628 | + // Error: unresolved token |
4629 | + if (unresolvedTokenIndex) |
4630 | + *unresolvedTokenIndex = static_cast<size_t>(t - tokens_); |
4631 | + return 0; |
4632 | } |
4633 | return v; |
4634 | } |
4635 | @@ -489,7 +511,9 @@ |
4636 | \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. |
4637 | \return Pointer to the value if it can be resolved. Otherwise null. |
4638 | */ |
4639 | - const ValueType* Get(const ValueType& root) const { return Get(const_cast<ValueType&>(root)); } |
4640 | + const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { |
4641 | + return Get(const_cast<ValueType&>(root), unresolvedTokenIndex); |
4642 | + } |
4643 | |
4644 | //@} |
4645 | |
4646 | @@ -968,11 +992,11 @@ |
4647 | src_++; |
4648 | Ch c = 0; |
4649 | for (int j = 0; j < 2; j++) { |
4650 | - c <<= 4; |
4651 | + c = static_cast<Ch>(c << 4); |
4652 | Ch h = *src_; |
4653 | - if (h >= '0' && h <= '9') c += h - '0'; |
4654 | - else if (h >= 'A' && h <= 'F') c += h - 'A' + 10; |
4655 | - else if (h >= 'a' && h <= 'f') c += h - 'a' + 10; |
4656 | + if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0'); |
4657 | + else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10); |
4658 | + else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10); |
4659 | else { |
4660 | valid_ = false; |
4661 | return 0; |
4662 | @@ -1050,23 +1074,23 @@ |
4663 | ////////////////////////////////////////////////////////////////////////////// |
4664 | |
4665 | template <typename T> |
4666 | -typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) { |
4667 | - return pointer.Get(root); |
4668 | +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) { |
4669 | + return pointer.Get(root, unresolvedTokenIndex); |
4670 | } |
4671 | |
4672 | template <typename T> |
4673 | -const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer) { |
4674 | - return pointer.Get(root); |
4675 | -} |
4676 | - |
4677 | -template <typename T, typename CharType, size_t N> |
4678 | -typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) { |
4679 | - return GenericPointer<typename T::ValueType>(source, N - 1).Get(root); |
4680 | -} |
4681 | - |
4682 | -template <typename T, typename CharType, size_t N> |
4683 | -const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) { |
4684 | - return GenericPointer<typename T::ValueType>(source, N - 1).Get(root); |
4685 | +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) { |
4686 | + return pointer.Get(root, unresolvedTokenIndex); |
4687 | +} |
4688 | + |
4689 | +template <typename T, typename CharType, size_t N> |
4690 | +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { |
4691 | + return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex); |
4692 | +} |
4693 | + |
4694 | +template <typename T, typename CharType, size_t N> |
4695 | +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { |
4696 | + return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex); |
4697 | } |
4698 | |
4699 | ////////////////////////////////////////////////////////////////////////////// |
4700 | @@ -1323,4 +1347,8 @@ |
4701 | RAPIDJSON_DIAG_POP |
4702 | #endif |
4703 | |
4704 | +#ifdef _MSC_VER |
4705 | +RAPIDJSON_DIAG_POP |
4706 | +#endif |
4707 | + |
4708 | #endif // RAPIDJSON_POINTER_H_ |
4709 | |
4710 | === modified file 'shorts/xml2json/rapidjson/prettywriter.h' |
4711 | --- shorts/xml2json/rapidjson/prettywriter.h 2016-03-04 13:27:57 +0000 |
4712 | +++ shorts/xml2json/rapidjson/prettywriter.h 2016-06-15 16:13:25 +0000 |
4713 | @@ -24,6 +24,14 @@ |
4714 | |
4715 | RAPIDJSON_NAMESPACE_BEGIN |
4716 | |
4717 | +//! Combination of PrettyWriter format flags. |
4718 | +/*! \see PrettyWriter::SetFormatOptions |
4719 | + */ |
4720 | +enum PrettyFormatOptions { |
4721 | + kFormatDefault = 0, //!< Default pretty formatting. |
4722 | + kFormatSingleLineArray = 1 //!< Format arrays on a single line. |
4723 | +}; |
4724 | + |
4725 | //! Writer with indentation and spacing. |
4726 | /*! |
4727 | \tparam OutputStream Type of ouptut os. |
4728 | @@ -31,8 +39,8 @@ |
4729 | \tparam TargetEncoding Encoding of output stream. |
4730 | \tparam StackAllocator Type of allocator for allocating memory of stack. |
4731 | */ |
4732 | -template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> |
4733 | -class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> { |
4734 | +template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> |
4735 | +class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> { |
4736 | public: |
4737 | typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base; |
4738 | typedef typename Base::Ch Ch; |
4739 | @@ -42,8 +50,12 @@ |
4740 | \param allocator User supplied allocator. If it is null, it will create a private one. |
4741 | \param levelDepth Initial capacity of stack. |
4742 | */ |
4743 | - PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : |
4744 | - Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} |
4745 | + explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : |
4746 | + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} |
4747 | + |
4748 | + |
4749 | + explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : |
4750 | + Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} |
4751 | |
4752 | //! Set custom indentation. |
4753 | /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). |
4754 | @@ -57,6 +69,14 @@ |
4755 | return *this; |
4756 | } |
4757 | |
4758 | + //! Set pretty writer formatting options. |
4759 | + /*! \param options Formatting options. |
4760 | + */ |
4761 | + PrettyWriter& SetFormatOptions(PrettyFormatOptions options) { |
4762 | + formatOptions_ = options; |
4763 | + return *this; |
4764 | + } |
4765 | + |
4766 | /*! @name Implementation of Handler |
4767 | \see Handler |
4768 | */ |
4769 | @@ -70,6 +90,12 @@ |
4770 | bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } |
4771 | bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } |
4772 | |
4773 | + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { |
4774 | + (void)copy; |
4775 | + PrettyPrefix(kNumberType); |
4776 | + return Base::WriteString(str, length); |
4777 | + } |
4778 | + |
4779 | bool String(const Ch* str, SizeType length, bool copy = false) { |
4780 | (void)copy; |
4781 | PrettyPrefix(kStringType); |
4782 | @@ -120,7 +146,7 @@ |
4783 | RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray); |
4784 | bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; |
4785 | |
4786 | - if (!empty) { |
4787 | + if (!empty && !(formatOptions_ & kFormatSingleLineArray)) { |
4788 | Base::os_->Put('\n'); |
4789 | WriteIndent(); |
4790 | } |
4791 | @@ -142,6 +168,18 @@ |
4792 | bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } |
4793 | |
4794 | //@} |
4795 | + |
4796 | + //! Write a raw JSON value. |
4797 | + /*! |
4798 | + For user to write a stringified JSON as a value. |
4799 | + |
4800 | + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. |
4801 | + \param length Length of the json. |
4802 | + \param type Type of the root of json. |
4803 | + \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. |
4804 | + */ |
4805 | + bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); } |
4806 | + |
4807 | protected: |
4808 | void PrettyPrefix(Type type) { |
4809 | (void)type; |
4810 | @@ -151,11 +189,14 @@ |
4811 | if (level->inArray) { |
4812 | if (level->valueCount > 0) { |
4813 | Base::os_->Put(','); // add comma if it is not the first element in array |
4814 | - Base::os_->Put('\n'); |
4815 | - } |
4816 | - else |
4817 | - Base::os_->Put('\n'); |
4818 | - WriteIndent(); |
4819 | + if (formatOptions_ & kFormatSingleLineArray) |
4820 | + Base::os_->Put(' '); |
4821 | + } |
4822 | + |
4823 | + if (!(formatOptions_ & kFormatSingleLineArray)) { |
4824 | + Base::os_->Put('\n'); |
4825 | + WriteIndent(); |
4826 | + } |
4827 | } |
4828 | else { // in object |
4829 | if (level->valueCount > 0) { |
4830 | @@ -191,6 +232,7 @@ |
4831 | |
4832 | Ch indentChar_; |
4833 | unsigned indentCharCount_; |
4834 | + PrettyFormatOptions formatOptions_; |
4835 | |
4836 | private: |
4837 | // Prohibit copy constructor & assignment operator. |
4838 | |
4839 | === modified file 'shorts/xml2json/rapidjson/rapidjson.h' |
4840 | --- shorts/xml2json/rapidjson/rapidjson.h 2016-03-04 13:27:57 +0000 |
4841 | +++ shorts/xml2json/rapidjson/rapidjson.h 2016-06-15 16:13:25 +0000 |
4842 | @@ -159,7 +159,7 @@ |
4843 | */ |
4844 | #ifndef RAPIDJSON_NO_INT64DEFINE |
4845 | //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN |
4846 | -#ifdef _MSC_VER |
4847 | +#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 |
4848 | #include "msinttypes/stdint.h" |
4849 | #include "msinttypes/inttypes.h" |
4850 | #else |
4851 | @@ -178,9 +178,9 @@ |
4852 | |
4853 | #ifndef RAPIDJSON_FORCEINLINE |
4854 | //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN |
4855 | -#if defined(_MSC_VER) && !defined(NDEBUG) |
4856 | +#if defined(_MSC_VER) && defined(NDEBUG) |
4857 | #define RAPIDJSON_FORCEINLINE __forceinline |
4858 | -#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG) |
4859 | +#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG) |
4860 | #define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) |
4861 | #else |
4862 | #define RAPIDJSON_FORCEINLINE |
4863 | @@ -265,7 +265,8 @@ |
4864 | \param x pointer to align |
4865 | |
4866 | Some machines require strict data alignment. Currently the default uses 4 bytes |
4867 | - alignment. User can customize by defining the RAPIDJSON_ALIGN function macro. |
4868 | + alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms. |
4869 | + User can customize by defining the RAPIDJSON_ALIGN function macro. |
4870 | */ |
4871 | #ifndef RAPIDJSON_ALIGN |
4872 | #if RAPIDJSON_64BIT == 1 |
4873 | @@ -289,6 +290,36 @@ |
4874 | #endif |
4875 | |
4876 | /////////////////////////////////////////////////////////////////////////////// |
4877 | +// RAPIDJSON_48BITPOINTER_OPTIMIZATION |
4878 | + |
4879 | +//! Use only lower 48-bit address for some pointers. |
4880 | +/*! |
4881 | + \ingroup RAPIDJSON_CONFIG |
4882 | + |
4883 | + This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address. |
4884 | + The higher 16-bit can be used for storing other data. |
4885 | + \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture. |
4886 | +*/ |
4887 | +#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION |
4888 | +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) |
4889 | +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1 |
4890 | +#else |
4891 | +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0 |
4892 | +#endif |
4893 | +#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION |
4894 | + |
4895 | +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1 |
4896 | +#if RAPIDJSON_64BIT != 1 |
4897 | +#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1 |
4898 | +#endif |
4899 | +#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x)))) |
4900 | +#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) |
4901 | +#else |
4902 | +#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x)) |
4903 | +#define RAPIDJSON_GETPOINTER(type, p) (p) |
4904 | +#endif |
4905 | + |
4906 | +/////////////////////////////////////////////////////////////////////////////// |
4907 | // RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD |
4908 | |
4909 | /*! \def RAPIDJSON_SIMD |
4910 | @@ -410,6 +441,35 @@ |
4911 | #endif |
4912 | |
4913 | /////////////////////////////////////////////////////////////////////////////// |
4914 | +// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY |
4915 | + |
4916 | +//! Compiler branching hint for expression with high probability to be true. |
4917 | +/*! |
4918 | + \ingroup RAPIDJSON_CONFIG |
4919 | + \param x Boolean expression likely to be true. |
4920 | +*/ |
4921 | +#ifndef RAPIDJSON_LIKELY |
4922 | +#if defined(__GNUC__) || defined(__clang__) |
4923 | +#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1) |
4924 | +#else |
4925 | +#define RAPIDJSON_LIKELY(x) (x) |
4926 | +#endif |
4927 | +#endif |
4928 | + |
4929 | +//! Compiler branching hint for expression with low probability to be true. |
4930 | +/*! |
4931 | + \ingroup RAPIDJSON_CONFIG |
4932 | + \param x Boolean expression unlikely to be true. |
4933 | +*/ |
4934 | +#ifndef RAPIDJSON_UNLIKELY |
4935 | +#if defined(__GNUC__) || defined(__clang__) |
4936 | +#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0) |
4937 | +#else |
4938 | +#define RAPIDJSON_UNLIKELY(x) (x) |
4939 | +#endif |
4940 | +#endif |
4941 | + |
4942 | +/////////////////////////////////////////////////////////////////////////////// |
4943 | // Helpers |
4944 | |
4945 | //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN |
4946 | @@ -501,6 +561,17 @@ |
4947 | #define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 |
4948 | #endif |
4949 | |
4950 | +#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR |
4951 | +#if defined(__clang__) |
4952 | +#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for) |
4953 | +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ |
4954 | + (defined(_MSC_VER) && _MSC_VER >= 1700) |
4955 | +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 |
4956 | +#else |
4957 | +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0 |
4958 | +#endif |
4959 | +#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR |
4960 | + |
4961 | //!@endcond |
4962 | |
4963 | /////////////////////////////////////////////////////////////////////////////// |
4964 | @@ -516,10 +587,7 @@ |
4965 | #endif |
4966 | |
4967 | /////////////////////////////////////////////////////////////////////////////// |
4968 | -// Allocators and Encodings |
4969 | - |
4970 | -#include "allocators.h" |
4971 | -#include "encodings.h" |
4972 | +// Type |
4973 | |
4974 | /*! \namespace rapidjson |
4975 | \brief main RapidJSON namespace |
4976 | @@ -527,148 +595,6 @@ |
4977 | */ |
4978 | RAPIDJSON_NAMESPACE_BEGIN |
4979 | |
4980 | -/////////////////////////////////////////////////////////////////////////////// |
4981 | -// Stream |
4982 | - |
4983 | -/*! \class rapidjson::Stream |
4984 | - \brief Concept for reading and writing characters. |
4985 | - |
4986 | - For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). |
4987 | - |
4988 | - For write-only stream, only need to implement Put() and Flush(). |
4989 | - |
4990 | -\code |
4991 | -concept Stream { |
4992 | - typename Ch; //!< Character type of the stream. |
4993 | - |
4994 | - //! Read the current character from stream without moving the read cursor. |
4995 | - Ch Peek() const; |
4996 | - |
4997 | - //! Read the current character from stream and moving the read cursor to next character. |
4998 | - Ch Take(); |
4999 | - |
5000 | - //! Get the current read cursor. |
FAILED: Continuous integration, rev:424 /core-apps- jenkins. ubuntu. com/job/ shorts- app-ci/ 21/ /core-apps- jenkins. ubuntu. com/job/ generic- update- mp/916/ console
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild: /core-apps- jenkins. ubuntu. com/job/ shorts- app-ci/ 21/rebuild
https:/