Merge lp:unity-scopes-api/staging into lp:unity-scopes-api
- staging
- Merge into trunk
Proposed by
Marcus Tomlinson
Status: | Merged |
---|---|
Approved by: | Paweł Stołowski |
Approved revision: | 324 |
Merged at revision: | 367 |
Proposed branch: | lp:unity-scopes-api/staging |
Merge into: | lp:unity-scopes-api |
Diff against target: |
2397 lines (+1285/-441) 31 files modified
CMakeLists.txt (+3/-3) RELEASE_NOTES.md (+7/-0) debian/VERSION (+1/-1) debian/changelog (+22/-0) debian/control.in (+1/-1) doc/tutorial.dox (+96/-1) include/unity/scopes/internal/JsonCppNode.h (+17/-10) include/unity/scopes/internal/JsonNodeInterface.h (+2/-3) include/unity/scopes/internal/JsonSettingsSchema.h (+1/-1) include/unity/scopes/internal/gobj_memory.h (+212/-0) scoperegistry/scoperegistry.cpp (+0/-1) src/scopes/CategoryRenderer.cpp (+1/-1) src/scopes/PreviewWidget.cpp (+9/-2) src/scopes/internal/JsonCppNode.cpp (+283/-200) src/scopes/internal/JsonSettingsSchema.cpp (+149/-162) src/scopes/internal/Logger.cpp (+2/-2) src/scopes/internal/RuntimeImpl.cpp (+1/-1) src/scopes/internal/ScopeConfig.cpp (+0/-2) src/scopes/internal/smartscopes/SmartScopesClient.cpp (+10/-0) src/scopes/internal/zmq_middleware/StopPublisher.cpp (+1/-1) src/scopes/testing/ScopeMetadataBuilder.cpp (+1/-3) test/copyright/check_copyright.sh (+1/-7) test/gtest/scopes/Registry/Registry_test.cpp (+0/-1) test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in (+0/-1) test/gtest/scopes/internal/CMakeLists.txt (+1/-0) test/gtest/scopes/internal/JsonNode/JsonNode_test.cpp (+153/-17) test/gtest/scopes/internal/JsonSettingsSchema/JsonSettingsSchema_test.cpp (+37/-5) test/gtest/scopes/internal/SettingsDB/SettingsDB_test.cpp (+4/-4) test/gtest/scopes/internal/gobj_ptr/CMakeLists.txt (+3/-0) test/gtest/scopes/internal/gobj_ptr/gobj_ptr_test.cpp (+208/-0) test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp (+59/-11) |
To merge this branch: | bzr merge lp:unity-scopes-api/staging |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Pending | |
Unity Team | Pending | ||
Review via email: mp+295415@code.launchpad.net |
Commit message
* Got rid of category header background, as per design (Bug #1446216).
* Re-enabled license/copyright test for xenial+.
* Removed libjson-cpp and replaced with json-glib based implementation (Bug #1360247).
* Fixed Yakkety build.
Description of the change
To post a comment you must log in.
lp:unity-scopes-api/staging
updated
- 319. By Marcus Tomlinson
-
Sync changelog
- 320. By Marcus Tomlinson
-
Update changelog and RELEASE_NOTES.md
- 321. By Marcus Tomlinson
-
Bump version
- 322. By Marcus Tomlinson
-
Merge devel
- 323. By Marcus Tomlinson
-
Merged devel
- 324. By Paweł Stołowski
-
Merged devel changes
Revision history for this message
Robert Bruce Park (robru) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2016-03-31 23:48:56 +0000 |
3 | +++ CMakeLists.txt 2016-06-17 07:24:44 +0000 |
4 | @@ -66,11 +66,11 @@ |
5 | pkg_check_modules(APPARMOR REQUIRED libapparmor REQUIRED) |
6 | pkg_check_modules(LTTNG_UST lttng-ust REQUIRED) |
7 | pkg_check_modules(LIBURCU_BP liburcu-bp REQUIRED) |
8 | -pkg_check_modules(JSONCPP jsoncpp REQUIRED) |
9 | pkg_check_modules(LIBACCOUNTS libaccounts-glib REQUIRED) |
10 | pkg_check_modules(LIBSIGNON libsignon-glib REQUIRED) |
11 | pkg_check_modules(ZMQLIB libzmq REQUIRED) |
12 | pkg_check_modules(NET_CPP net-cpp>=1.2.0 REQUIRED) |
13 | +pkg_check_modules(JSON_GLIB json-glib-1.0 REQUIRED) |
14 | |
15 | find_library(ZMQPPLIB zmqpp) |
16 | if(NOT ZMQPPLIB) |
17 | @@ -140,10 +140,10 @@ |
18 | ) |
19 | |
20 | set(OTHER_INCLUDE_DIRS ${OTHER_INCLUDE_DIRS} ${UNITY_API_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} |
21 | - ${JSONCPP_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS} ${APPARMOR_INCLUDE_DIRS} |
22 | + ${JSON_GLIB_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS} ${APPARMOR_INCLUDE_DIRS} |
23 | ${LIBACCOUNTS_INCLUDE_DIRS} ${LIBSIGNON_INCLUDE_DIRS} ${NET_CPP_INCLUDE_DIRS}) |
24 | set(OTHER_LIBS ${OTHER_LIBS} ${UNITY_API_LDFLAGS} ${APPARMOR_LDFLAGS} ${LIBACCOUNTS_LIBRARIES} |
25 | - ${LIBSIGNON_LIBRARIES} ${Boost_LIBRARIES} ${JSONCPP_LDFLAGS} ${PROCESS_CPP_LDFLAGS} |
26 | + ${LIBSIGNON_LIBRARIES} ${Boost_LIBRARIES} ${JSON_GLIB_LDFLAGS} ${PROCESS_CPP_LDFLAGS} |
27 | ${ZMQPPLIB} ${ZMQLIB_LDFLAGS} ${CAPNPLIB} ${KJLIB} ${DLLIB} ${NET_CPP_LDFLAGS} pthread) |
28 | |
29 | # Standard install paths |
30 | |
31 | === modified file 'RELEASE_NOTES.md' |
32 | --- RELEASE_NOTES.md 2016-04-11 07:58:52 +0000 |
33 | +++ RELEASE_NOTES.md 2016-06-17 07:24:44 +0000 |
34 | @@ -1,6 +1,13 @@ |
35 | Release notes |
36 | ============= |
37 | |
38 | +Changes in version 1.0.6 |
39 | +======================== |
40 | + - Got rid of category header background, as per design (Bug #1446216). |
41 | + - Re-enabled license/copyright test for xenial+. |
42 | + - Removed libjson-cpp and replaced with json-glib based implementation (Bug #1360247). |
43 | + - Fixed Yakkety build. |
44 | + |
45 | Changes in version 1.0.5 |
46 | ======================== |
47 | - Simplify debian/control munging. |
48 | |
49 | === modified file 'debian/VERSION' |
50 | --- debian/VERSION 2016-03-31 23:48:56 +0000 |
51 | +++ debian/VERSION 2016-06-17 07:24:44 +0000 |
52 | @@ -1,1 +1,1 @@ |
53 | -1.0.5 |
54 | +1.0.6 |
55 | |
56 | === modified file 'debian/changelog' |
57 | --- debian/changelog 2016-04-13 09:51:48 +0000 |
58 | +++ debian/changelog 2016-06-17 07:24:44 +0000 |
59 | @@ -1,3 +1,25 @@ |
60 | +unity-scopes-api (1.0.6+16.10.20160520.3-0ubuntu2) UNRELEASED; urgency=medium |
61 | + |
62 | + * Got rid of category header background, as per design (Bug #1446216). |
63 | + * Re-enabled license/copyright test for xenial+. |
64 | + * Removed libjson-cpp and replaced with json-glib based implementation (Bug #1360247). |
65 | + * Fixed Yakkety build. |
66 | + |
67 | + -- Marcus Tomlinson <marcustomlinson@ubuntu> Mon, 23 May 2016 09:54:28 +0200 |
68 | + |
69 | +unity-scopes-api (1.0.6+16.10.20160520.3-0ubuntu1) yakkety; urgency=medium |
70 | + |
71 | + [ CI Train Bot ] |
72 | + * No-change rebuild. |
73 | + |
74 | + -- Marcus Tomlinson <marcus.tomlinson@canonical.com> Fri, 20 May 2016 14:55:39 +0000 |
75 | + |
76 | +unity-scopes-api (1.0.5+16.04.20160413.1-0ubuntu2) yakkety; urgency=medium |
77 | + |
78 | + * No-change rebuild of latest xenial trunk against current archive. |
79 | + |
80 | + -- Łukasz 'sil2100' Zemczak <lukasz.zemczak@ubuntu.com> Thu, 19 May 2016 19:19:30 +0200 |
81 | + |
82 | unity-scopes-api (1.0.5+16.04.20160413.1-0ubuntu1) xenial; urgency=medium |
83 | |
84 | [ Marcus Tomlinson ] |
85 | |
86 | === modified file 'debian/control.in' |
87 | --- debian/control.in 2016-03-16 12:35:22 +0000 |
88 | +++ debian/control.in 2016-06-17 07:24:44 +0000 |
89 | @@ -21,7 +21,7 @@ |
90 | libboost-thread-dev, |
91 | libcapnp-dev (>= 0.4.0), |
92 | libdbustest1-dev, |
93 | - libjsoncpp-dev, |
94 | + libjson-glib-dev, |
95 | liblttng-ust-dev, |
96 | libnet-cpp-dev (>= 1.2.0), |
97 | libprocess-cpp-dev (>= 1.0.1), |
98 | |
99 | === modified file 'doc/tutorial.dox' |
100 | --- doc/tutorial.dox 2016-03-16 12:35:22 +0000 |
101 | +++ doc/tutorial.dox 2016-06-17 07:24:44 +0000 |
102 | @@ -636,6 +636,102 @@ |
103 | call to your `activate()` method. Your implementation of `activate()` should follow the same guidelines as for |
104 | `perform_action()` (except that widget and action identifiers do not apply to result activation). |
105 | |
106 | +\paragraph resultaction Handling result action activation |
107 | + |
108 | +Search results can embed simple action buttons (icons) in their cards. When the user taps an action icon, the scope gets notified and can update |
109 | +the affected result card to reflect the new state. A typical use case for this is to offer "social" actions, such as thumbs up/down buttons. |
110 | + |
111 | +The following snippet demonstrates how two actions can be added to a \link unity::scopes::CategorisedResult CategorisedResult\endlink: |
112 | + |
113 | +\code |
114 | +CategorisedResult res(cat); |
115 | +res.set_uri("myuri"); |
116 | +res.set_title("My Title"); |
117 | + |
118 | +// Add result actions |
119 | +VariantBuilder builder; |
120 | +builder.add_tuple({ |
121 | + {"id", Variant("thumbsup")}, |
122 | + {"icon", Variant("thOff")}, |
123 | + {"temporaryIcon", Variant("thOn")}, |
124 | + {"label", Variant("I like it")}, |
125 | +}); |
126 | +builder.add_tuple({ |
127 | + {"id", Variant("flag")}, |
128 | + {"icon", Variant("flag")}, |
129 | + {"temporaryIcon", Variant("flagOn")}, |
130 | + {"label", Variant("Flag this result")}, |
131 | +}); |
132 | +res["social-actions"] = builder.end(); |
133 | +\endcode |
134 | + |
135 | +The attributes of result actions are as follows: |
136 | +<ul> |
137 | +<li>id - unique action identifier that will be reported to the scope. |
138 | +<li>icon - the icon for the action button. |
139 | +<li>temporaryIcon (optional) - defines an icon that will be shown immediately when the user taps the button, before the scope reacts to the action. |
140 | +<li>label - the text shown next to the icon. |
141 | +</ul> |
142 | + |
143 | +To respond to activation of result actions, your scope must implement |
144 | +\link unity::scopes::ScopeBase::activate_result_action ScopeBase::activate_result_action\endlink: |
145 | + |
146 | +\code{.cpp} |
147 | +class MyScope : public ScopeBase |
148 | +{ |
149 | + ... |
150 | + ActivationQueryBase::UPtr activate_result_action(Result const& result, |
151 | + ActionMetadata const& metadata, |
152 | + std::string const& action_id) override; |
153 | + ... |
154 | +} |
155 | +\endcode |
156 | + |
157 | +Like `search()` and `preview()`, `activate_result_action()` is a factory method. It must return an |
158 | +instance that derives from \link unity::scopes::ActivationQueryBase ActivationQueryBase\endlink. |
159 | +Your derived class must implement the \link unity::scopes::ActivationQueryBase::activate activate()\endlink method, |
160 | +whose job it is to respond to the activation (that is, the user pressing action button). `activate` must return |
161 | +an \link unity::scopes::ActivationResponse ActivationResponse\endlink, which tells the UI how it should |
162 | +behave in response to the result action activation. For result actions the typical and recommended behavior is to update the card |
163 | +for the result whose action was activated. |
164 | + |
165 | +For example, here is how to update the actions of an affected card in response to a "thumbsup" action, so that tapping the "thumbsup" action button replaces that |
166 | +button with "thumbsdown": |
167 | + |
168 | +\code{.cpp} |
169 | +class MyActivation : public ActivationQueryBase |
170 | +{ |
171 | + MyActivation(Result const& result, unity::scopes::ActionMetadata const& metadata, std::string const& action_id) : |
172 | + ActivationQueryBase(result, metadata, action_id) |
173 | + { |
174 | + } |
175 | + |
176 | + virtual ActivationResponse activate() override |
177 | + { |
178 | + if (action_id() == "thumbsup") |
179 | + { |
180 | + // ... update backend data for 'thumbs up' action ... |
181 | + |
182 | + // get the affect result and update it |
183 | + Result updatedRes(result()); |
184 | + VariantBuilder builder; |
185 | + builder.add_tuple({ |
186 | + {"id", Variant("thumbsdown")}, |
187 | + {"icon", Variant("thOn")}, |
188 | + {"temporaryIcon", Variant("thOff")}, |
189 | + {"label", Variant("I don't like it")}, |
190 | + }); |
191 | + builder.add_tuple({ ... }) |
192 | + updatedRes["social-actions"] = builder.end(); |
193 | + return ActivationResponse(updatedRes); |
194 | + } |
195 | + |
196 | + if (action_id() == "thumbsdown") |
197 | + ... |
198 | + } |
199 | +}; |
200 | +\endcode |
201 | + |
202 | \paragraph export Exporting a scope |
203 | |
204 | Your scope must be compiled into a `.so` shared library and, to be successfully |
205 | @@ -1430,7 +1526,6 @@ |
206 | ForegroundColor = default text color (defaults to theme-provided foreground color) |
207 | BackgroundColor = color of scope background (default is transparent) |
208 | ShapeImages = whether to use Ubuntu-shape for all cards and artwork (defaults to true) |
209 | - CategoryHeaderBackground = background scheme of the results categories |
210 | PreviewButtonColor = color of preview buttons (defaults to theme-provided color) |
211 | LogoOverlayColor = color for the overlay in scopes overview (defaults to semi-transparent black) |
212 | PageHeader.Logo = image containing scope's logo |
213 | |
214 | === modified file 'include/unity/scopes/internal/JsonCppNode.h' |
215 | --- include/unity/scopes/internal/JsonCppNode.h 2014-11-03 05:31:30 +0000 |
216 | +++ include/unity/scopes/internal/JsonCppNode.h 2016-06-17 07:24:44 +0000 |
217 | @@ -19,9 +19,15 @@ |
218 | #pragma once |
219 | |
220 | #include <unity/scopes/internal/JsonNodeInterface.h> |
221 | -#include <jsoncpp/json/value.h> |
222 | + |
223 | +#include <unity/scopes/internal/gobj_memory.h> |
224 | #include <unity/scopes/Variant.h> |
225 | |
226 | +#pragma GCC diagnostic push |
227 | +#pragma GCC diagnostic ignored "-Wold-style-cast" |
228 | +#include <json-glib/json-glib.h> |
229 | +#pragma GCC diagnostic pop |
230 | + |
231 | namespace unity |
232 | { |
233 | |
234 | @@ -34,10 +40,11 @@ |
235 | class JsonCppNode : public JsonNodeInterface |
236 | { |
237 | public: |
238 | - explicit JsonCppNode(std::string const& json_string = ""); |
239 | - explicit JsonCppNode(const Json::Value& root); |
240 | - explicit JsonCppNode(const Variant& var); |
241 | - ~JsonCppNode(); |
242 | + JsonCppNode(); |
243 | + JsonCppNode(std::string const& json_string); |
244 | + explicit JsonCppNode(JsonNode* root); |
245 | + explicit JsonCppNode(Variant const& var); |
246 | + ~JsonCppNode() = default; |
247 | |
248 | void clear() override; |
249 | void read_json(std::string const& json_string) override; |
250 | @@ -49,8 +56,7 @@ |
251 | NodeType type() const override; |
252 | |
253 | std::string as_string() const override; |
254 | - int as_int() const override; |
255 | - unsigned int as_uint() const override; |
256 | + int64_t as_int() const override; |
257 | double as_double() const override; |
258 | bool as_bool() const override; |
259 | |
260 | @@ -61,9 +67,10 @@ |
261 | JsonNodeInterface::SPtr get_node(unsigned int node_index) const override; |
262 | |
263 | private: |
264 | - static Json::Value from_variant(Variant const& var); |
265 | - static Variant to_variant(Json::Value const &val); |
266 | - Json::Value root_; |
267 | + void init_from_string(std::string const& jscon_string); |
268 | + |
269 | + typedef std::unique_ptr<JsonNode, decltype(&json_node_free)> NodePtr; |
270 | + NodePtr root_; |
271 | }; |
272 | |
273 | } // namespace internal |
274 | |
275 | === modified file 'include/unity/scopes/internal/JsonNodeInterface.h' |
276 | --- include/unity/scopes/internal/JsonNodeInterface.h 2014-11-03 05:31:30 +0000 |
277 | +++ include/unity/scopes/internal/JsonNodeInterface.h 2016-06-17 07:24:44 +0000 |
278 | @@ -42,7 +42,7 @@ |
279 | |
280 | enum NodeType |
281 | { |
282 | - Null, Array, Object, String, Int, UInt, Real, Bool |
283 | + Null, Array, Object, String, Int, Real, Bool |
284 | }; |
285 | |
286 | JsonNodeInterface() = default; |
287 | @@ -58,8 +58,7 @@ |
288 | virtual NodeType type() const = 0; |
289 | |
290 | virtual std::string as_string() const = 0; |
291 | - virtual int as_int() const = 0; |
292 | - virtual unsigned int as_uint() const = 0; |
293 | + virtual int64_t as_int() const = 0; |
294 | virtual double as_double() const = 0; |
295 | virtual bool as_bool() const = 0; |
296 | |
297 | |
298 | === modified file 'include/unity/scopes/internal/JsonSettingsSchema.h' |
299 | --- include/unity/scopes/internal/JsonSettingsSchema.h 2014-11-03 05:31:30 +0000 |
300 | +++ include/unity/scopes/internal/JsonSettingsSchema.h 2016-06-17 07:24:44 +0000 |
301 | @@ -49,7 +49,7 @@ |
302 | void add_location_setting() override; |
303 | |
304 | private: |
305 | - JsonSettingsSchema(std::string const& ini_file); |
306 | + JsonSettingsSchema(std::string const& json_string); |
307 | |
308 | JsonSettingsSchema(); |
309 | |
310 | |
311 | === added file 'include/unity/scopes/internal/gobj_memory.h' |
312 | --- include/unity/scopes/internal/gobj_memory.h 1970-01-01 00:00:00 +0000 |
313 | +++ include/unity/scopes/internal/gobj_memory.h 2016-06-17 07:24:44 +0000 |
314 | @@ -0,0 +1,212 @@ |
315 | +/* |
316 | + * Copyright (C) 2013 Canonical Ltd. |
317 | + * |
318 | + * This program is free software: you can redistribute it and/or modify |
319 | + * it under the terms of the GNU Lesser General Public License version 3 as |
320 | + * published by the Free Software Foundation. |
321 | + * |
322 | + * This program is distributed in the hope that it will be useful, |
323 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
324 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
325 | + * GNU Lesser General Public License for more details. |
326 | + * |
327 | + * You should have received a copy of the GNU Lesser General Public License |
328 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
329 | + * |
330 | + * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> |
331 | + */ |
332 | + |
333 | +#pragma once |
334 | + |
335 | +#include <stdexcept> |
336 | + |
337 | +#pragma GCC diagnostic push |
338 | +#pragma GCC diagnostic ignored "-Wold-style-cast" |
339 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
340 | +#include <glib-object.h> |
341 | + |
342 | +namespace unity |
343 | +{ |
344 | + |
345 | +namespace scopes |
346 | +{ |
347 | + |
348 | +namespace internal |
349 | +{ |
350 | + |
351 | +/** |
352 | + * This class is meant for automatically managing the lifetime of C objects derived |
353 | + * from gobject. Its API perfectly mirrors the API of unique_ptr except that you |
354 | + * can't define your own deleter function as it is always g_object_unref. |
355 | + * |
356 | + * API/ABI stability is not guaranteed. If you need to pass the object across an ABI |
357 | + * boundary, pass the plain gobject. |
358 | + * |
359 | + * This is how you would use gobj_ptr 99% of the time: |
360 | + * |
361 | + * gobj_ptr<GSomeType> o(g_some_type_new(...)); |
362 | + * |
363 | + * More specifically, the object will decrement the gobject reference count |
364 | + * of the object it points to when it goes out of scope. It will never increment it. |
365 | + * Thus you should only assign to it when already holding a reference. gobj_ptr |
366 | + * will then take ownership of that particular reference. |
367 | + * |
368 | + * Floating gobjects can not be put in this container as they are meant to be put |
369 | + * into native gobject aware containers immediately upon construction. Trying to insert |
370 | + * a floating gobject into a gobj_ptr will throw an invalid_argument exception. To |
371 | + * prevent accidental memory leaks, the floating gobject is unreffed in this case. |
372 | + */ |
373 | +template <typename T> |
374 | +class gobj_ptr final |
375 | +{ |
376 | +private: |
377 | + T* u; |
378 | + |
379 | + void validate_float(T* t) |
380 | + { |
381 | + if (t != nullptr && g_object_is_floating(G_OBJECT(t))) |
382 | + { |
383 | + // LCOV_EXCL_START // False negative from gcovr. |
384 | + throw std::invalid_argument("Tried to add a floating gobject into a gobj_ptr."); |
385 | + // LCOV_EXCL_STOP |
386 | + } |
387 | + } |
388 | + |
389 | +public: |
390 | + typedef T element_type; |
391 | + typedef T* pointer; |
392 | + typedef decltype(g_object_unref) deleter_type; |
393 | + |
394 | + constexpr gobj_ptr() noexcept : u(nullptr) |
395 | + { |
396 | + } |
397 | + explicit gobj_ptr(T* t) |
398 | + : u(t) |
399 | + { |
400 | + // What should we do if validate throws? Unreffing unknown objs |
401 | + // is dodgy but not unreffing runs the risk of |
402 | + // memory leaks. Currently unrefs as u is destroyed |
403 | + // when this exception is thrown. |
404 | + validate_float(t); |
405 | + } |
406 | + constexpr gobj_ptr(std::nullptr_t) noexcept : u(nullptr){}; |
407 | + gobj_ptr(gobj_ptr&& o) noexcept |
408 | + { |
409 | + u = o.u; |
410 | + o.u = nullptr; |
411 | + } |
412 | + gobj_ptr(const gobj_ptr& o) |
413 | + : u(nullptr) |
414 | + { |
415 | + *this = o; |
416 | + } |
417 | + gobj_ptr& operator=(const gobj_ptr& o) |
418 | + { |
419 | + if (o.u != nullptr) |
420 | + { |
421 | + g_object_ref(o.u); |
422 | + } |
423 | + reset(o.u); |
424 | + return *this; |
425 | + } |
426 | + ~gobj_ptr() |
427 | + { |
428 | + reset(); |
429 | + } |
430 | + |
431 | + deleter_type& get_deleter() noexcept |
432 | + { |
433 | + return g_object_unref; |
434 | + } |
435 | + deleter_type& get_deleter() const noexcept |
436 | + { |
437 | + return g_object_unref; |
438 | + } |
439 | + |
440 | + void swap(gobj_ptr<T>& o) noexcept |
441 | + { |
442 | + T* tmp = u; |
443 | + u = o.u; |
444 | + o.u = tmp; |
445 | + } |
446 | + void reset(pointer p = pointer()) |
447 | + { |
448 | + if (u != nullptr) |
449 | + { |
450 | + g_object_unref(G_OBJECT(u)); |
451 | + u = nullptr; |
452 | + } |
453 | + // Same throw dilemma as in pointer constructor. |
454 | + u = p; |
455 | + validate_float(p); |
456 | + } |
457 | + |
458 | + T* release() noexcept |
459 | + { |
460 | + T* r = u; |
461 | + u = nullptr; |
462 | + return r; |
463 | + } |
464 | + T* get() const noexcept |
465 | + { |
466 | + return u; |
467 | + } |
468 | + |
469 | + T& operator*() const |
470 | + { |
471 | + return *u; |
472 | + } |
473 | + T* operator->() const noexcept |
474 | + { |
475 | + return u; |
476 | + } |
477 | + explicit operator bool() const noexcept |
478 | + { |
479 | + return u != nullptr; |
480 | + } |
481 | + |
482 | + gobj_ptr& operator=(gobj_ptr&& o) noexcept |
483 | + { |
484 | + reset(); |
485 | + u = o.u; |
486 | + o.u = nullptr; |
487 | + return *this; |
488 | + } |
489 | + gobj_ptr& operator=(std::nullptr_t) noexcept |
490 | + { |
491 | + reset(); |
492 | + return *this; |
493 | + } |
494 | + bool operator==(const gobj_ptr<T>& o) const noexcept |
495 | + { |
496 | + return u == o.u; |
497 | + } |
498 | + bool operator!=(const gobj_ptr<T>& o) const noexcept |
499 | + { |
500 | + return u != o.u; |
501 | + } |
502 | + bool operator<(const gobj_ptr<T>& o) const noexcept |
503 | + { |
504 | + return u < o.u; |
505 | + } |
506 | + bool operator<=(const gobj_ptr<T>& o) const noexcept |
507 | + { |
508 | + return u <= o.u; |
509 | + } |
510 | + bool operator>(const gobj_ptr<T>& o) const noexcept |
511 | + { |
512 | + return u > o.u; |
513 | + } |
514 | + bool operator>=(const gobj_ptr<T>& o) const noexcept |
515 | + { |
516 | + return u >= o.u; |
517 | + } |
518 | +}; |
519 | + |
520 | +} // namespace internal |
521 | + |
522 | +} // namespace scopes |
523 | + |
524 | +} // namespace unity |
525 | + |
526 | +#pragma GCC diagnostic pop |
527 | |
528 | === modified file 'scoperegistry/scoperegistry.cpp' |
529 | --- scoperegistry/scoperegistry.cpp 2015-09-11 07:29:12 +0000 |
530 | +++ scoperegistry/scoperegistry.cpp 2016-06-17 07:24:44 +0000 |
531 | @@ -338,7 +338,6 @@ |
532 | convert_relative_attribute(inner_map, "navigation-background", scope_dir); |
533 | app_attrs["page-header"] = Variant(inner_map); |
534 | } |
535 | - convert_relative_attribute(app_attrs, "category-header-background", scope_dir); |
536 | mi->set_appearance_attributes(app_attrs); |
537 | |
538 | mi->set_scope_directory(scope_dir.native()); |
539 | |
540 | === modified file 'src/scopes/CategoryRenderer.cpp' |
541 | --- src/scopes/CategoryRenderer.cpp 2016-03-08 10:09:42 +0000 |
542 | +++ src/scopes/CategoryRenderer.cpp 2016-06-17 07:24:44 +0000 |
543 | @@ -66,7 +66,7 @@ |
544 | \arg \c card-layout Specifies layout of the individual result cards; possible values: \c "vertical" (default), \c "horizontal" |
545 | \arg \c card-size Size of the result cards; possible values: \c "small", \c "medium" (default), \c "large"; when using <tt>"category-layout": "vertical-journal"</tt> any integer between 12 and 38 |
546 | \arg \c overlay Overlay text data on top of the art; boolean, default false |
547 | -\arg \c collapsed-rows Number of result rows displayed while the category is collapsed; possible values: any non-negative integer, where 0 fully expands the category (only affects grid and vertical journal) |
548 | +\arg \c collapsed-rows Number of result rows displayed while the category is collapsed; possible values: any non-negative integer, where 0 fully expands the category (only affects grid) |
549 | \arg \c card-background Background color for the cards; string; URI in the format \verbatim color:///#rrggbb \endverbatim or \verbatim color:///color_name |
550 | \endverbatim or \verbatim gradient:///#rrggbb/#rrggbb \endverbatim or an image URI (will be stretched) |
551 | \arg \c quick-preview-type The type of media content represented by result cards, for use with inline playback; the only currently supported type is "audio". |
552 | |
553 | === modified file 'src/scopes/PreviewWidget.cpp' |
554 | --- src/scopes/PreviewWidget.cpp 2016-01-18 19:50:19 +0000 |
555 | +++ src/scopes/PreviewWidget.cpp 2016-06-17 07:24:44 +0000 |
556 | @@ -431,15 +431,18 @@ |
557 | \subsection expandable expandable widget |
558 | |
559 | The expandable widget is used to group several widgets into an expandable pane. |
560 | +The expandable widget can be collapsed or uncollapsed. When it's uncollapsed then |
561 | +all the contained widgets are shown. When collapsed, only the first few widgets determined |
562 | +by collapsed-widgets attribute are shown. |
563 | |
564 | List of attributes: |
565 | \arg \c title A string specifying the title |
566 | -\arg \c collapsed-widgets Optional number of collapsed widgets (0 makes all of them visible) |
567 | +\arg \c collapsed-widgets A number of widgets to show when the expandable widget is collapsed (optional). |
568 | |
569 | \code |
570 | PreviewWidget expandable("exp", "expandable"); |
571 | expandable.add_attribute_value("title", Variant("This is an expandable widget")); |
572 | - expandable.add_attribute_value("collapsed-widgets", Variant(0)); |
573 | + expandable.add_attribute_value("collapsed-widgets", Variant(2)); |
574 | |
575 | PreviewWidget w1("w1", "text"); |
576 | w1.add_attribute_value("title", Variant("Subwidget 1")); |
577 | @@ -447,8 +450,12 @@ |
578 | PreviewWidget w2("w2", "text"); |
579 | w2.add_attribute_value("title", Variant("Subwidget 2")); |
580 | w2.add_attribute_value("text", Variant("A text")); |
581 | + PreviewWidget w3("w3", "text"); |
582 | + w3.add_attribute_value("title", Variant("Subwidget 3")); |
583 | + w3.add_attribute_value("text", Variant("A text")); |
584 | expandable.add_widget(w1); |
585 | expandable.add_widget(w2); |
586 | + expandable.add_widget(w3); |
587 | ... |
588 | \endcode |
589 | |
590 | |
591 | === modified file 'src/scopes/internal/JsonCppNode.cpp' |
592 | --- src/scopes/internal/JsonCppNode.cpp 2015-11-02 05:08:08 +0000 |
593 | +++ src/scopes/internal/JsonCppNode.cpp 2016-06-17 07:24:44 +0000 |
594 | @@ -14,316 +14,399 @@ |
595 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
596 | * |
597 | * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
598 | + * Michi Henning <michi.henning@canonical.com> |
599 | */ |
600 | |
601 | #include <unity/scopes/internal/JsonCppNode.h> |
602 | + |
603 | #include <unity/UnityExceptions.h> |
604 | -#include <jsoncpp/json/reader.h> |
605 | -#include <jsoncpp/json/writer.h> |
606 | -#include <sstream> |
607 | |
608 | +using namespace std; |
609 | using namespace unity::scopes; |
610 | using namespace unity::scopes::internal; |
611 | |
612 | -JsonCppNode::JsonCppNode(std::string const& json_string) |
613 | -{ |
614 | - if (!json_string.empty()) |
615 | - { |
616 | - read_json(json_string); |
617 | - } |
618 | -} |
619 | - |
620 | -JsonCppNode::JsonCppNode(const Json::Value& root) |
621 | - : root_(root) |
622 | -{ |
623 | -} |
624 | - |
625 | -JsonCppNode::JsonCppNode(const Variant& var) |
626 | -{ |
627 | - root_ = from_variant(var); |
628 | -} |
629 | - |
630 | -JsonCppNode::~JsonCppNode() |
631 | -{ |
632 | -} |
633 | - |
634 | -Json::Value JsonCppNode::from_variant(Variant const& var) |
635 | -{ |
636 | +void JsonCppNode::init_from_string(string const& json_string) |
637 | +{ |
638 | + if (json_string.find_first_not_of(" \t\n") == std::string::npos) |
639 | + { |
640 | + throw unity::ResourceException("JsonCppNode(): empty string is not a valid JSON"); |
641 | + } |
642 | + |
643 | + gobj_ptr<JsonParser> parser(json_parser_new()); |
644 | + GError *err = nullptr; |
645 | + if (!json_parser_load_from_data(parser.get(), json_string.c_str(), json_string.size(), &err)) |
646 | + { |
647 | + string msg = string("JsonCppNode(); parse error: ") + err->message; |
648 | + g_error_free(err); |
649 | + throw unity::ResourceException(msg); |
650 | + } |
651 | + root_.reset(json_node_copy(json_parser_get_root(parser.get()))); |
652 | +} |
653 | + |
654 | +JsonCppNode::JsonCppNode() |
655 | + : root_(json_node_alloc(), json_node_free) |
656 | +{ |
657 | + json_node_init_null(root_.get()); |
658 | +} |
659 | + |
660 | +JsonCppNode::JsonCppNode(string const& json_string) |
661 | + : JsonCppNode() |
662 | +{ |
663 | + init_from_string(json_string); |
664 | +} |
665 | + |
666 | +JsonCppNode::JsonCppNode(JsonNode* node) |
667 | + : root_(json_node_copy(node), json_node_free) |
668 | +{ |
669 | +} |
670 | + |
671 | +namespace |
672 | +{ |
673 | + |
674 | +// Allocates a new node for each value. Caller is responsible for deallocating the root node. |
675 | + |
676 | +JsonNode* variant_to_node(Variant const& var) |
677 | +{ |
678 | + unique_ptr<JsonNode, decltype(&json_node_free)> node_guard(json_node_alloc(), json_node_free); |
679 | + auto node = node_guard.get(); |
680 | switch (var.which()) |
681 | { |
682 | + case Variant::Type::Null: |
683 | + json_node_init_null(node); |
684 | + break; |
685 | + case Variant::Type::Array: |
686 | + { |
687 | + unique_ptr<JsonArray, decltype(&json_array_unref)> array(json_array_new(), json_array_unref); |
688 | + for (auto const& v : var.get_array()) |
689 | + { |
690 | + json_array_add_element(array.get(), variant_to_node(v)); |
691 | + } |
692 | + json_node_init_array(node, array.get()); |
693 | + break; |
694 | + } |
695 | + case Variant::Type::Dict: |
696 | + { |
697 | + unique_ptr<JsonObject, decltype(&json_object_unref)> object(json_object_new(), json_object_unref); |
698 | + for (auto const& v : var.get_dict()) |
699 | + { |
700 | + json_object_set_member(object.get(), v.first.c_str(), variant_to_node(v.second)); |
701 | + } |
702 | + json_node_set_object(node, object.get()); |
703 | + break; |
704 | + } |
705 | + case Variant::Type::String: |
706 | + json_node_init_string(node, var.get_string().c_str()); |
707 | + break; |
708 | case Variant::Type::Int: |
709 | - return Json::Value(var.get_int()); |
710 | + json_node_init_int(node, int64_t(var.get_int())); |
711 | + break; |
712 | case Variant::Type::Int64: |
713 | - return Json::Value(static_cast<Json::Int64>(var.get_int64_t())); |
714 | + json_node_init_int(node, var.get_int64_t()); |
715 | + break; |
716 | + case Variant::Type::Double: |
717 | + json_node_init_double(node, var.get_double()); |
718 | + break; |
719 | case Variant::Type::Bool: |
720 | - return Json::Value(var.get_bool()); |
721 | - case Variant::Type::String: |
722 | - return Json::Value(var.get_string()); |
723 | - case Variant::Type::Double: |
724 | - return Json::Value(var.get_double()); |
725 | - case Variant::Type::Dict: |
726 | - { |
727 | - Json::Value val(Json::ValueType::objectValue); |
728 | - for (auto const& v: var.get_dict()) |
729 | - { |
730 | - val[v.first] = from_variant(v.second); |
731 | - } |
732 | - return val; |
733 | - } |
734 | - case Variant::Type::Array: |
735 | - { |
736 | - Json::Value val(Json::ValueType::arrayValue); |
737 | - for (auto const& v: var.get_array()) |
738 | - { |
739 | - val.append(from_variant(v)); |
740 | - } |
741 | - return val; |
742 | - } |
743 | - case Variant::Type::Null: |
744 | - return Json::Value(Json::ValueType::nullValue); |
745 | + { |
746 | + json_node_init_boolean(node, var.get_bool()); |
747 | + break; |
748 | + } |
749 | default: |
750 | - { |
751 | - std::ostringstream s; |
752 | - s << "JsonCppNode::from_variant(): unsupported variant type "; |
753 | - s << static_cast<int>(var.which()); |
754 | - throw unity::LogicException(s.str()); |
755 | - } |
756 | + { |
757 | + abort(); // LCOV_EXCL_LINE // Impossible |
758 | + } |
759 | } |
760 | -} |
761 | - |
762 | -Variant JsonCppNode::to_variant(Json::Value const& value) |
763 | -{ |
764 | - switch (value.type()) |
765 | + return node_guard.release(); |
766 | +} |
767 | + |
768 | +} // namespace |
769 | + |
770 | +JsonCppNode::JsonCppNode(Variant const& var) |
771 | + : root_(variant_to_node(var), json_node_free) |
772 | +{ |
773 | +} |
774 | + |
775 | +#pragma GCC diagnostic push |
776 | +#pragma GCC diagnostic ignored "-Wold-style-cast" |
777 | + |
778 | +namespace |
779 | +{ |
780 | + |
781 | +Variant node_to_variant(JsonNode* node); // Mutual recursion, need forward declaration. |
782 | + |
783 | +extern "C" |
784 | +void add_to_array(JsonArray* /* array */, guint /* index */, JsonNode* element_node, gpointer user_data) |
785 | +{ |
786 | + VariantArray* va = reinterpret_cast<VariantArray*>(user_data); |
787 | + va->push_back(node_to_variant(element_node)); |
788 | +} |
789 | + |
790 | +extern "C" |
791 | +void add_to_map(JsonObject* /* object */, gchar const* member_name, JsonNode* member_node, gpointer user_data) |
792 | +{ |
793 | + VariantMap* vm = reinterpret_cast<VariantMap*>(user_data); |
794 | + (*vm)[member_name] = node_to_variant(member_node); |
795 | +} |
796 | + |
797 | +Variant node_to_variant(JsonNode* node) |
798 | +{ |
799 | + switch (json_node_get_node_type(node)) |
800 | { |
801 | - case Json::ValueType::nullValue: |
802 | + case JSON_NODE_NULL: |
803 | return Variant::null(); |
804 | - case Json::ValueType::arrayValue: |
805 | - { |
806 | - VariantArray arr; |
807 | - for (unsigned int i=0; i<value.size(); ++i) |
808 | - { |
809 | - arr.push_back(to_variant(value[i])); |
810 | - } |
811 | - return Variant(arr); |
812 | - } |
813 | - case Json::ValueType::objectValue: |
814 | - { |
815 | - VariantMap var; |
816 | - for (auto const& m: value.getMemberNames()) |
817 | - { |
818 | - var[m] = to_variant(value[m]); |
819 | - } |
820 | - return Variant(var); |
821 | - } |
822 | - case Json::ValueType::stringValue: |
823 | - return Variant(value.asString()); |
824 | - case Json::ValueType::intValue: |
825 | - case Json::ValueType::uintValue: |
826 | - // this can throw std::runtime_error from jsoncpp if unsigned int to int conversion is not possible |
827 | - if (value.isInt()) |
828 | - { |
829 | - return Variant(value.asInt()); |
830 | - } |
831 | - return Variant(static_cast<int64_t>(value.asInt64())); |
832 | - case Json::ValueType::realValue: |
833 | - return Variant(value.asDouble()); |
834 | - case Json::ValueType::booleanValue: |
835 | - return Variant(value.asBool()); |
836 | + case JSON_NODE_ARRAY: |
837 | + { |
838 | + VariantArray va; |
839 | + auto array = json_node_get_array(node); |
840 | + json_array_foreach_element(array, add_to_array, &va); |
841 | + return Variant(va); |
842 | + } |
843 | + case JSON_NODE_OBJECT: |
844 | + { |
845 | + VariantMap vm; |
846 | + auto object = json_node_get_object(node); |
847 | + json_object_foreach_member(object, add_to_map, &vm); |
848 | + return Variant(vm); |
849 | + } |
850 | + case JSON_NODE_VALUE: |
851 | + { |
852 | + switch (json_node_get_value_type(node)) |
853 | + { |
854 | + case G_TYPE_STRING: |
855 | + return Variant(string(json_node_get_string(node))); |
856 | + case G_TYPE_INT64: |
857 | + { |
858 | + // HACK: If the value fits into a 32-bit int, return an Int |
859 | + // variant. Otherwise, return an Int64 variant. |
860 | + int64_t val64 = json_node_get_int(node); |
861 | + if (val64 < INT32_MIN || val64 > INT32_MAX) |
862 | + { |
863 | + return Variant(val64); |
864 | + } |
865 | + int32_t val32 = val64; |
866 | + return Variant(val32); |
867 | + } |
868 | + case G_TYPE_DOUBLE: |
869 | + return Variant(json_node_get_double(node)); |
870 | + case G_TYPE_BOOLEAN: |
871 | + return Variant(bool(json_node_get_boolean(node))); |
872 | + default: |
873 | + abort(); // LCOV_EXCL_LINE // Impossible |
874 | + } |
875 | + } |
876 | default: |
877 | - { |
878 | - std::ostringstream s; |
879 | - s << "JsonCppNode::to_variant(): unsupported json type "; |
880 | - s << static_cast<int>(value.type()); |
881 | - throw unity::LogicException(s.str()); |
882 | - } |
883 | + abort(); // LCOV_EXCL_LINE // Impossible |
884 | } |
885 | } |
886 | |
887 | +} // namespace |
888 | + |
889 | Variant JsonCppNode::to_variant() const |
890 | { |
891 | - return to_variant(root_); |
892 | + return node_to_variant(root_.get()); |
893 | } |
894 | |
895 | void JsonCppNode::clear() |
896 | { |
897 | - root_.clear(); |
898 | -} |
899 | - |
900 | -void JsonCppNode::read_json(std::string const& json_string) |
901 | -{ |
902 | - Json::Reader reader; |
903 | - clear(); |
904 | - |
905 | - if (!reader.parse(json_string, root_)) |
906 | - { |
907 | - throw unity::ResourceException("Failed to parse json string: " + reader.getFormattedErrorMessages()); |
908 | - } |
909 | -} |
910 | - |
911 | -std::string JsonCppNode::to_json_string() const |
912 | -{ |
913 | - Json::FastWriter writer; |
914 | - return writer.write(root_); |
915 | + json_node_init_null(root_.get()); |
916 | +} |
917 | + |
918 | +void JsonCppNode::read_json(string const& json_string) |
919 | +{ |
920 | + init_from_string(json_string); |
921 | +} |
922 | + |
923 | +string JsonCppNode::to_json_string() const |
924 | +{ |
925 | + gobj_ptr<JsonGenerator> generator(json_generator_new()); |
926 | + json_generator_set_root(generator.get(), root_.get()); |
927 | + |
928 | + gsize len; |
929 | + unique_ptr<gchar, decltype(&g_free)> data(json_generator_to_data(generator.get(), &len), g_free); |
930 | + string result(data.get(), len); |
931 | + result += '\n'; |
932 | + return result; |
933 | } |
934 | |
935 | int JsonCppNode::size() const |
936 | { |
937 | - return root_.size(); |
938 | -} |
939 | - |
940 | -std::vector<std::string> JsonCppNode::member_names() const |
941 | -{ |
942 | - if (root_.type() != Json::objectValue) |
943 | + switch (json_node_get_node_type(root_.get())) |
944 | + { |
945 | + case JSON_NODE_ARRAY: |
946 | + { |
947 | + auto array = json_node_get_array(root_.get()); |
948 | + return json_array_get_length(array); |
949 | + } |
950 | + case JSON_NODE_OBJECT: |
951 | + { |
952 | + auto object = json_node_get_object(root_.get()); |
953 | + return json_object_get_size(object); |
954 | + } |
955 | + default: |
956 | + return 0; |
957 | + } |
958 | +} |
959 | + |
960 | +namespace |
961 | +{ |
962 | + |
963 | +extern "C" |
964 | +void add_name(JsonObject* /* object */, gchar const* member_name, JsonNode* /* member_node */, gpointer user_data) |
965 | +{ |
966 | + vector<string>* names = reinterpret_cast<vector<string>*>(user_data); |
967 | + names->push_back(member_name); |
968 | +} |
969 | + |
970 | +} |
971 | + |
972 | +vector<string> JsonCppNode::member_names() const |
973 | +{ |
974 | + if (!JSON_NODE_HOLDS_OBJECT(root_.get())) |
975 | { |
976 | throw unity::LogicException("Root node is not an object"); |
977 | } |
978 | - return root_.getMemberNames(); |
979 | + |
980 | + vector<string> names; |
981 | + auto object = json_node_get_object(root_.get()); |
982 | + json_object_foreach_member(object, add_name, &names); |
983 | + return names; |
984 | } |
985 | |
986 | JsonNodeInterface::NodeType JsonCppNode::type() const |
987 | { |
988 | - switch (root_.type()) |
989 | + switch (json_node_get_node_type(root_.get())) |
990 | { |
991 | - case Json::nullValue: |
992 | + case JSON_NODE_NULL: |
993 | return Null; |
994 | - case Json::arrayValue: |
995 | + case JSON_NODE_ARRAY: |
996 | return Array; |
997 | - case Json::objectValue: |
998 | + case JSON_NODE_OBJECT: |
999 | return Object; |
1000 | - case Json::stringValue: |
1001 | - return String; |
1002 | - case Json::intValue: |
1003 | - return Int; |
1004 | - case Json::uintValue: |
1005 | - return UInt; |
1006 | - case Json::realValue: |
1007 | - return Real; |
1008 | - case Json::booleanValue: |
1009 | - return Bool; |
1010 | + case JSON_NODE_VALUE: |
1011 | + { |
1012 | + switch (json_node_get_value_type(root_.get())) |
1013 | + { |
1014 | + case G_TYPE_STRING: |
1015 | + return String; |
1016 | + case G_TYPE_INT64: |
1017 | + return Int; |
1018 | + case G_TYPE_DOUBLE: |
1019 | + return Real; |
1020 | + case G_TYPE_BOOLEAN: |
1021 | + return Bool; |
1022 | + default: |
1023 | + abort(); // LCOV_EXCL_LINE // Impossible |
1024 | + } |
1025 | + } |
1026 | default: |
1027 | - break; |
1028 | + abort(); // LCOV_EXCL_LINE // Impossible |
1029 | } |
1030 | |
1031 | - return Null; |
1032 | + abort(); // LCOV_EXCL_LINE |
1033 | } |
1034 | |
1035 | -std::string JsonCppNode::as_string() const |
1036 | +string JsonCppNode::as_string() const |
1037 | { |
1038 | - if (!root_.isConvertibleTo(Json::stringValue)) |
1039 | + if (JSON_NODE_HOLDS_NULL(root_.get())) |
1040 | + { |
1041 | + return string(); |
1042 | + } |
1043 | + if (!JSON_NODE_HOLDS_VALUE(root_.get()) || json_node_get_value_type(root_.get()) != G_TYPE_STRING) |
1044 | { |
1045 | throw unity::LogicException("Node does not contain a string value"); |
1046 | } |
1047 | |
1048 | - return root_.asString(); |
1049 | + return string(json_node_get_string(root_.get())); |
1050 | } |
1051 | |
1052 | -int JsonCppNode::as_int() const |
1053 | +int64_t JsonCppNode::as_int() const |
1054 | { |
1055 | - if (!root_.isConvertibleTo(Json::intValue)) |
1056 | + if (!JSON_NODE_HOLDS_VALUE(root_.get()) || json_node_get_value_type(root_.get()) != G_TYPE_INT64) |
1057 | { |
1058 | throw unity::LogicException("Node does not contain an int value"); |
1059 | } |
1060 | |
1061 | - return root_.asInt(); |
1062 | -} |
1063 | - |
1064 | -unsigned int JsonCppNode::as_uint() const |
1065 | -{ |
1066 | - if (!root_.isConvertibleTo(Json::uintValue)) |
1067 | - { |
1068 | - throw unity::LogicException("Node does not contain a unsigned int value"); |
1069 | - } |
1070 | - |
1071 | - return root_.asUInt(); |
1072 | + return json_node_get_int(root_.get()); |
1073 | } |
1074 | |
1075 | double JsonCppNode::as_double() const |
1076 | { |
1077 | - if (!root_.isConvertibleTo(Json::realValue)) |
1078 | + if (!JSON_NODE_HOLDS_VALUE(root_.get()) || json_node_get_value_type(root_.get()) != G_TYPE_DOUBLE) |
1079 | { |
1080 | throw unity::LogicException("Node does not contain a double value"); |
1081 | } |
1082 | |
1083 | - return root_.asDouble(); |
1084 | + return json_node_get_double(root_.get()); |
1085 | } |
1086 | |
1087 | bool JsonCppNode::as_bool() const |
1088 | { |
1089 | - if (!root_.isConvertibleTo(Json::booleanValue)) |
1090 | + if (!JSON_NODE_HOLDS_VALUE(root_.get()) || json_node_get_value_type(root_.get()) != G_TYPE_BOOLEAN) |
1091 | { |
1092 | throw unity::LogicException("Node does not contain a bool value"); |
1093 | } |
1094 | |
1095 | - return root_.asBool(); |
1096 | + return json_node_get_boolean(root_.get()); |
1097 | } |
1098 | |
1099 | -bool JsonCppNode::has_node(std::string const& node_name) const |
1100 | +#pragma GCC diagnostic pop |
1101 | + |
1102 | +bool JsonCppNode::has_node(string const& node_name) const |
1103 | { |
1104 | - if (!root_) |
1105 | + if (JSON_NODE_HOLDS_NULL(root_.get())) |
1106 | { |
1107 | throw unity::LogicException("Current node is empty"); |
1108 | } |
1109 | |
1110 | - if (root_.type() != Json::objectValue) |
1111 | + if (!JSON_NODE_HOLDS_OBJECT(root_.get())) |
1112 | { |
1113 | throw unity::LogicException("Root node is not an object"); |
1114 | } |
1115 | |
1116 | - return root_.isMember(node_name); |
1117 | + return json_object_has_member(json_node_get_object(root_.get()), node_name.c_str()); |
1118 | } |
1119 | |
1120 | JsonNodeInterface::SPtr JsonCppNode::get_node() const |
1121 | { |
1122 | - if (!root_) |
1123 | + if (JSON_NODE_HOLDS_NULL(root_.get())) |
1124 | { |
1125 | throw unity::LogicException("Current node is empty"); |
1126 | } |
1127 | |
1128 | - return std::make_shared<JsonCppNode>(root_); |
1129 | + return make_shared<JsonCppNode>(root_.get()); |
1130 | } |
1131 | |
1132 | -JsonNodeInterface::SPtr JsonCppNode::get_node(std::string const& node_name) const |
1133 | +JsonNodeInterface::SPtr JsonCppNode::get_node(string const& node_name) const |
1134 | { |
1135 | - if (!root_) |
1136 | - { |
1137 | - throw unity::LogicException("Current node is empty"); |
1138 | - } |
1139 | - |
1140 | - if (root_.type() != Json::objectValue) |
1141 | - { |
1142 | - throw unity::LogicException("Root node is not an object"); |
1143 | - } |
1144 | - if (!root_.isMember(node_name)) |
1145 | + if (!has_node(node_name)) |
1146 | { |
1147 | throw unity::LogicException("Node " + node_name + " does not exist"); |
1148 | } |
1149 | |
1150 | - const Json::Value& value_node = root_[node_name]; |
1151 | - return std::make_shared<JsonCppNode>(value_node); |
1152 | + auto object = json_node_get_object(root_.get()); |
1153 | + auto member = json_object_get_member(object, node_name.c_str()); |
1154 | + return make_shared<JsonCppNode>(member); |
1155 | } |
1156 | |
1157 | JsonNodeInterface::SPtr JsonCppNode::get_node(unsigned int node_index) const |
1158 | { |
1159 | - if (!root_) |
1160 | + if (JSON_NODE_HOLDS_NULL(root_.get())) |
1161 | { |
1162 | throw unity::LogicException("Current node is empty"); |
1163 | } |
1164 | |
1165 | - if (root_.type() != Json::arrayValue) |
1166 | + if (!JSON_NODE_HOLDS_ARRAY(root_.get())) |
1167 | { |
1168 | throw unity::LogicException("Root node is not an array"); |
1169 | } |
1170 | - else if (node_index >= root_.size()) |
1171 | - { |
1172 | - throw unity::LogicException("Invalid array index"); |
1173 | - } |
1174 | - |
1175 | - const Json::Value& value_node = root_[node_index]; |
1176 | - |
1177 | - if (!value_node) |
1178 | - { |
1179 | - throw unity::LogicException("Node " + std::to_string(node_index) + " does not exist"); |
1180 | - } |
1181 | - |
1182 | - return std::make_shared <JsonCppNode> (value_node); |
1183 | + |
1184 | + auto array = json_node_get_array(root_.get()); |
1185 | + auto size = json_array_get_length(array); |
1186 | + if (node_index >= size) |
1187 | + { |
1188 | + throw unity::LogicException("Invalid array index: " + to_string(node_index)); |
1189 | + } |
1190 | + |
1191 | + auto element = json_array_get_element(array, node_index); |
1192 | + return make_shared<JsonCppNode>(element); |
1193 | } |
1194 | |
1195 | === modified file 'src/scopes/internal/JsonSettingsSchema.cpp' |
1196 | --- src/scopes/internal/JsonSettingsSchema.cpp 2015-03-02 03:59:01 +0000 |
1197 | +++ src/scopes/internal/JsonSettingsSchema.cpp 2016-06-17 07:24:44 +0000 |
1198 | @@ -19,10 +19,10 @@ |
1199 | #include <unity/scopes/internal/JsonSettingsSchema.h> |
1200 | |
1201 | #include <unity/scopes/internal/DfltConfig.h> |
1202 | +#include <unity/scopes/internal/JsonCppNode.h> |
1203 | |
1204 | #include <boost/algorithm/string/predicate.hpp> |
1205 | #include <boost/filesystem.hpp> |
1206 | -#include <jsoncpp/json/json.h> |
1207 | #include <unity/UnityExceptions.h> |
1208 | |
1209 | #include <set> |
1210 | @@ -52,7 +52,7 @@ |
1211 | public: |
1212 | NONCOPYABLE(Setting); |
1213 | |
1214 | - Setting(Json::Value const& v); |
1215 | + Setting(Variant const& v); |
1216 | Setting(string const& id, |
1217 | string const& type, |
1218 | string const& display_name, |
1219 | @@ -68,13 +68,13 @@ |
1220 | |
1221 | private: |
1222 | |
1223 | - Json::Value get_mandatory(Json::Value const& v, Json::StaticString const& key, Json::ValueType expected_type) const; |
1224 | - void set_default_value(Json::Value const& v, Type expected_type); |
1225 | - Variant get_bool_default(Json::Value const& v) const; |
1226 | - Variant get_enum_default(Json::Value const& v); |
1227 | - Variant get_double_default(Json::Value const& v) const; |
1228 | - Variant get_string_default(Json::Value const& v) const; |
1229 | - void set_enumerators(Json::Value const& v); |
1230 | + Variant get_mandatory(Variant const& v, string const& key, Variant::Type expected_type) const; |
1231 | + void set_default_value(Variant const& v, Type expected_type); |
1232 | + Variant get_bool_default(Variant const& v) const; |
1233 | + Variant get_enum_default(Variant const& v); |
1234 | + Variant get_double_default(Variant const& v) const; |
1235 | + Variant get_string_default(Variant const& v) const; |
1236 | + void set_enumerators(Variant const& v); |
1237 | |
1238 | string id_; |
1239 | string type_; |
1240 | @@ -90,32 +90,32 @@ |
1241 | { "string", Setting::StringT }, |
1242 | }; |
1243 | |
1244 | -Setting::Setting(Json::Value const& v) |
1245 | +Setting::Setting(Variant const& v) |
1246 | { |
1247 | - assert(v.isObject()); |
1248 | - |
1249 | - static auto const id_key = Json::StaticString("id"); |
1250 | - static auto const type_key = Json::StaticString("type"); |
1251 | - static auto const display_name_key = Json::StaticString("displayName"); |
1252 | - |
1253 | - id_ = get_mandatory(v, id_key, Json::stringValue).asString(); |
1254 | + assert(v.which() == Variant::Type::Dict); |
1255 | + |
1256 | + static string const id_key = "id"; |
1257 | + static string const type_key = "type"; |
1258 | + static string const display_name_key = "displayName"; |
1259 | + |
1260 | + id_ = get_mandatory(v, id_key, Variant::Type::String).get_string(); |
1261 | if (id_.empty()) |
1262 | { |
1263 | - throw ResourceException(string("JsonSettingsSchema(): invalid empty \"") + id_key.c_str() + "\" definition"); |
1264 | + throw ResourceException(string("JsonSettingsSchema(): invalid empty \"") + id_key + "\" definition"); |
1265 | } |
1266 | |
1267 | - auto v_type = get_mandatory(v, type_key, Json::stringValue); |
1268 | - string type_string = v_type.asString(); |
1269 | + auto v_type = get_mandatory(v, type_key, Variant::Type::String); |
1270 | + string type_string = v_type.get_string(); |
1271 | auto const it = VALID_TYPES.find(type_string); |
1272 | if (it == VALID_TYPES.end()) |
1273 | { |
1274 | - throw ResourceException(string("JsonSettingsSchema(): invalid \"") + type_key.c_str() + "\" setting: \"" |
1275 | - + type_string + "\", " "id = \"" + id_ + "\""); |
1276 | + throw ResourceException(string("JsonSettingsSchema(): invalid \"") + type_key + "\" definition: \"" |
1277 | + + type_string + "\", " "id = \"" + id_ + "\""); |
1278 | } |
1279 | type_ = it->first; |
1280 | set_default_value(v, it->second); |
1281 | |
1282 | - display_name_ = get_mandatory(v, display_name_key, Json::stringValue).asString(); |
1283 | + display_name_ = get_mandatory(v, display_name_key, Variant::Type::String).get_string(); |
1284 | } |
1285 | |
1286 | Setting::Setting(string const& id, |
1287 | @@ -131,11 +131,7 @@ |
1288 | assert(!id.empty()); |
1289 | |
1290 | auto const it = VALID_TYPES.find(type); |
1291 | - if (it == VALID_TYPES.end()) |
1292 | - { |
1293 | - throw ResourceException(string("JsonSettingsSchema(): invalid \"type\" definition: \"") |
1294 | - + type + "\", setting = \"" + id_ + "\""); |
1295 | - } |
1296 | + assert(it != VALID_TYPES.end()); |
1297 | type_ = it->first; |
1298 | } |
1299 | |
1300 | @@ -158,35 +154,33 @@ |
1301 | return Variant(schema); |
1302 | } |
1303 | |
1304 | -Json::Value Setting::get_mandatory(Json::Value const& v, |
1305 | - Json::StaticString const& key, |
1306 | - Json::ValueType expected_type) const |
1307 | +Variant Setting::get_mandatory(Variant const& v, string const& key, Variant::Type expected_type) const |
1308 | { |
1309 | - assert(v.isObject()); |
1310 | - auto val = v[key]; |
1311 | - if (val.isNull()) |
1312 | + assert(v.which() == Variant::Type::Dict); |
1313 | + auto val = v.get_dict()[key]; |
1314 | + if (val.is_null()) |
1315 | { |
1316 | - throw ResourceException(string("JsonSettingsSchema(): missing \"") + key.c_str() + "\" definition" |
1317 | - + (!id_.empty() ? ", id = \"" + id_ + "\"" : string())); |
1318 | + throw ResourceException(string("JsonSettingsSchema(): missing \"") + key + "\" definition" |
1319 | + + (!id_.empty() ? ", id = \"" + id_ + "\"" : string())); |
1320 | } |
1321 | - if (val.type() != expected_type) |
1322 | + if (val.which() != expected_type) |
1323 | { |
1324 | - throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + key.c_str() + "\" definition, " |
1325 | - + "id = \"" + id_ + "\""); |
1326 | + throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + key |
1327 | + + "\" definition, " + "id = \"" + id_ + "\""); |
1328 | } |
1329 | return val; |
1330 | } |
1331 | |
1332 | -static auto const parameters_key = Json::StaticString("parameters"); |
1333 | +static string const parameters_key = "parameters"; |
1334 | |
1335 | -void Setting::set_default_value(Json::Value const& v, Type expected_type) |
1336 | +void Setting::set_default_value(Variant const& v, Type expected_type) |
1337 | { |
1338 | - auto v_param = v[parameters_key]; |
1339 | - if (v_param.isNull()) |
1340 | + auto v_param = v.get_dict()[parameters_key]; |
1341 | + if (v_param.is_null()) |
1342 | { |
1343 | return; |
1344 | } |
1345 | - else if (!v_param.isObject()) |
1346 | + else if (v_param.which() != Variant::Type::Dict) |
1347 | { |
1348 | throw ResourceException("JsonSettingsSchema(): expected value of type object for \"parameters\", id = \"" + id_ + "\""); |
1349 | } |
1350 | @@ -219,124 +213,120 @@ |
1351 | } |
1352 | } |
1353 | |
1354 | -static auto const dflt_key = Json::StaticString("defaultValue"); |
1355 | - |
1356 | -Variant Setting::get_bool_default(Json::Value const& v) const |
1357 | -{ |
1358 | - if (v.isNull()) // No "parameters" key |
1359 | - { |
1360 | - return Variant(); |
1361 | - } |
1362 | - auto v_dflt = v[dflt_key]; |
1363 | - if (v_dflt.isNull()) |
1364 | - { |
1365 | - return Variant(); // No "defaultValue" key |
1366 | - } |
1367 | - if (!v_dflt.isBool()) |
1368 | - { |
1369 | - throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key.c_str() |
1370 | - + "\" definition, id = \"" + id_ + "\""); |
1371 | - } |
1372 | - return Variant(v_dflt.asBool()); |
1373 | -} |
1374 | - |
1375 | -Variant Setting::get_double_default(Json::Value const& v) const |
1376 | -{ |
1377 | - if (v.isNull()) // No "parameters" key |
1378 | - { |
1379 | - return Variant(); |
1380 | - } |
1381 | - auto v_dflt = v[dflt_key]; |
1382 | - if (v_dflt.isNull()) |
1383 | - { |
1384 | - return Variant(); // No "defaultValue" key |
1385 | - } |
1386 | - if (!v_dflt.isNumeric()) |
1387 | - { |
1388 | - throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key.c_str() |
1389 | - + "\" definition, id = \"" + id_ + "\""); |
1390 | - } |
1391 | - return Variant(v_dflt.asDouble()); |
1392 | -} |
1393 | - |
1394 | -Variant Setting::get_enum_default(Json::Value const& v) |
1395 | -{ |
1396 | - assert(v.isObject()); |
1397 | - |
1398 | - if (v.isNull()) // No "parameters" key |
1399 | - { |
1400 | - throw ResourceException(string("JsonSettingsSchema(): missing \"") + parameters_key.c_str() |
1401 | - + "\" definition, id = \"" + id_ + "\""); |
1402 | - } |
1403 | - auto v_dflt = v[dflt_key]; |
1404 | - if (v_dflt.isNull()) |
1405 | - { |
1406 | - return Variant(); // No "defaultValue" key |
1407 | - } |
1408 | - if (!v_dflt.isInt()) |
1409 | - { |
1410 | - throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key.c_str() |
1411 | - + "\" definition, id = \"" + id_ + "\""); |
1412 | - } |
1413 | - |
1414 | - static auto const values_key = Json::StaticString("values"); |
1415 | - |
1416 | - auto v_vals = v[values_key]; |
1417 | - if (!v_vals.isArray()) |
1418 | - { |
1419 | - throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + values_key.c_str() |
1420 | - + "\" definition, id = \"" + id_ + "\""); |
1421 | - } |
1422 | - if (v_vals.size() < 1) |
1423 | - { |
1424 | - throw ResourceException(string("JsonSettingsSchema(): invalid empty \"") + values_key.c_str() |
1425 | - + "\" definition, id = \"" + id_ + "\""); |
1426 | +static string const dflt_key = "defaultValue"; |
1427 | + |
1428 | +Variant Setting::get_bool_default(Variant const& v) const |
1429 | +{ |
1430 | + assert(!v.is_null()); |
1431 | + |
1432 | + auto v_dflt = v.get_dict()[dflt_key]; |
1433 | + if (v_dflt.is_null()) |
1434 | + { |
1435 | + return Variant(); // No "defaultValue" key |
1436 | + } |
1437 | + if (v_dflt.which() != Variant::Type::Bool) |
1438 | + { |
1439 | + throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key |
1440 | + + "\" definition, id = \"" + id_ + "\""); |
1441 | + } |
1442 | + return v_dflt; |
1443 | +} |
1444 | + |
1445 | +Variant Setting::get_double_default(Variant const& v) const |
1446 | +{ |
1447 | + assert(!v.is_null()); |
1448 | + |
1449 | + auto v_dflt = v.get_dict()[dflt_key]; |
1450 | + if (v_dflt.is_null()) |
1451 | + { |
1452 | + return Variant(); // No "defaultValue" key |
1453 | + } |
1454 | + switch (v_dflt.which()) |
1455 | + { |
1456 | + case Variant::Type::Int: |
1457 | + return Variant(double(v_dflt.get_int())); |
1458 | + case Variant::Type::Int64: |
1459 | + return Variant(double(v_dflt.get_int64_t())); |
1460 | + case Variant::Type::Double: |
1461 | + return v_dflt; |
1462 | + default: |
1463 | + throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key |
1464 | + + "\" definition, id = \"" + id_ + "\""); |
1465 | + } |
1466 | +} |
1467 | + |
1468 | +Variant Setting::get_enum_default(Variant const& v) |
1469 | +{ |
1470 | + assert(v.which() == Variant::Type::Dict); |
1471 | + |
1472 | + auto v_dflt = v.get_dict()[dflt_key]; |
1473 | + if (v_dflt.is_null()) |
1474 | + { |
1475 | + return Variant(); // No "defaultValue" key |
1476 | + } |
1477 | + if (v_dflt.which() != Variant::Type::Int) |
1478 | + { |
1479 | + throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key |
1480 | + + "\" definition, id = \"" + id_ + "\""); |
1481 | + } |
1482 | + |
1483 | + static string const values_key = "values"; |
1484 | + |
1485 | + auto v_vals = v.get_dict()[values_key]; |
1486 | + if (v_vals.which() != Variant::Type::Array) |
1487 | + { |
1488 | + throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + values_key |
1489 | + + "\" definition, id = \"" + id_ + "\""); |
1490 | + } |
1491 | + if (v_vals.get_array().size() == 0) |
1492 | + { |
1493 | + throw ResourceException(string("JsonSettingsSchema(): invalid empty \"") + values_key |
1494 | + + "\" definition, id = \"" + id_ + "\""); |
1495 | } |
1496 | |
1497 | set_enumerators(v_vals); |
1498 | |
1499 | - auto val = v_dflt.asInt(); |
1500 | - if (val < 0 || val >= static_cast<int>(v_vals.size())) |
1501 | + auto val = v_dflt.get_int(); |
1502 | + if (val < 0 || val >= static_cast<int>(v_vals.get_array().size())) |
1503 | { |
1504 | - throw ResourceException(string("JsonSettingsSchema(): \"") + dflt_key.c_str() |
1505 | - + "\" out of range, id = \"" + id_ + "\""); |
1506 | + throw ResourceException(string("JsonSettingsSchema(): \"") + dflt_key |
1507 | + + "\" out of range, id = \"" + id_ + "\""); |
1508 | } |
1509 | - return Variant(v_dflt.asInt()); |
1510 | + return v_dflt; |
1511 | } |
1512 | |
1513 | -Variant Setting::get_string_default(Json::Value const& v) const |
1514 | +Variant Setting::get_string_default(Variant const& v) const |
1515 | { |
1516 | - if (v.isNull()) // No "parameters" key |
1517 | - { |
1518 | - return Variant(); |
1519 | - } |
1520 | - auto v_dflt = v[dflt_key]; |
1521 | - if (v_dflt.isNull()) |
1522 | + assert(!v.is_null()); |
1523 | + |
1524 | + auto v_dflt = v.get_dict()[dflt_key]; |
1525 | + if (v_dflt.is_null()) |
1526 | { |
1527 | return Variant(); // No "defaultValue" key |
1528 | } |
1529 | - if (!v_dflt.isString()) |
1530 | + if (v_dflt.which() != Variant::Type::String) |
1531 | { |
1532 | - throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key.c_str() |
1533 | - + "\" definition, id = \"" + id_ + "\""); |
1534 | + throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key |
1535 | + + "\" definition, id = \"" + id_ + "\""); |
1536 | } |
1537 | - return Variant(v_dflt.asString()); |
1538 | + return v_dflt; |
1539 | } |
1540 | |
1541 | -void Setting::set_enumerators(Json::Value const& v) |
1542 | +void Setting::set_enumerators(Variant const& v) |
1543 | { |
1544 | - assert(v.isArray()); |
1545 | + assert(v.which() == Variant::Type::Array); |
1546 | |
1547 | set<string> enums_seen; |
1548 | |
1549 | - for (unsigned i = 0; i < v.size(); ++i) |
1550 | + VariantArray va = v.get_array(); |
1551 | + for (unsigned i = 0; i < va.size(); ++i) |
1552 | { |
1553 | - Json::Value enumerator = v[i]; |
1554 | - if (!enumerator.isString()) |
1555 | + Variant enumerator = v.get_array()[i]; |
1556 | + if (enumerator.which() != Variant::Type::String) |
1557 | { |
1558 | throw ResourceException(string("JsonSettingsSchema(): invalid enumerator type, id = \"") + id_ + "\""); |
1559 | } |
1560 | - string enum_str = enumerator.asString(); |
1561 | + string enum_str = enumerator.get_string(); |
1562 | if (enum_str.empty()) |
1563 | { |
1564 | throw ResourceException(string("JsonSettingsSchema(): invalid empty enumerator, id = \"") + id_ + "\""); |
1565 | @@ -347,7 +337,7 @@ |
1566 | + "\", id = \"" + id_ + "\""); |
1567 | } |
1568 | enums_seen.insert(enum_str); |
1569 | - enumerators_.emplace_back(Variant(enum_str)); |
1570 | + enumerators_.emplace_back(enumerator); |
1571 | } |
1572 | } |
1573 | |
1574 | @@ -367,39 +357,36 @@ |
1575 | { |
1576 | try |
1577 | { |
1578 | - Json::Value root; |
1579 | - Json::Reader reader; |
1580 | - if (!reader.parse(json_string, root)) |
1581 | - { |
1582 | - throw ResourceException("JsonSettingsSchema(): cannot parse schema: " + reader.getFormattedErrorMessages()); |
1583 | - } |
1584 | - |
1585 | - if (!root.isArray()) |
1586 | - { |
1587 | - root = root["settings"]; |
1588 | - } |
1589 | - if (root.isNull()) |
1590 | - { |
1591 | - throw ResourceException("JsonSettingsSchema(): missing \"settings\" definition"); |
1592 | - } |
1593 | - if (!root.isArray()) |
1594 | - { |
1595 | - throw ResourceException("JsonSettingsSchema(): value \"settings\" must be an array"); |
1596 | - } |
1597 | + JsonCppNode::SPtr root = make_shared<JsonCppNode>(json_string); |
1598 | + |
1599 | + if (root->type() != JsonNodeInterface::Array) |
1600 | + { |
1601 | + if (root->type() != JsonNodeInterface::Object || !root->has_node("settings")) |
1602 | + { |
1603 | + throw ResourceException("JsonSettingsSchema(): missing \"settings\" definition"); |
1604 | + } |
1605 | + root = root->get_node("settings"); |
1606 | + if (root->type() != JsonNodeInterface::Array) |
1607 | + { |
1608 | + throw ResourceException("JsonSettingsSchema(): value \"settings\" must be an array"); |
1609 | + } |
1610 | + } |
1611 | + |
1612 | set<string> seen_settings; |
1613 | - for (unsigned i = 0; i < root.size(); ++i) |
1614 | + for (int i = 0; i < root->size(); ++i) |
1615 | { |
1616 | - Setting s(root[i]); |
1617 | + Setting s(root->get_node(i)->to_variant()); |
1618 | if (starts_with(s.id(), "internal.")) |
1619 | { |
1620 | - throw ResourceException(string("JsonSettingsSchema(): invalid key \"") + s.id() + "\" prefixed with \"internal.\""); |
1621 | + throw ResourceException(string("JsonSettingsSchema(): invalid key \"") + s.id() |
1622 | + + "\" prefixed with \"internal.\""); |
1623 | } |
1624 | if (seen_settings.find(s.id()) != seen_settings.end()) |
1625 | { |
1626 | throw ResourceException("JsonSettingsSchema(): duplicate definition, id = \"" + s.id() + "\""); |
1627 | } |
1628 | + seen_settings.insert(s.id()); |
1629 | definitions_.push_back(s.to_schema_definition()); |
1630 | - seen_settings.insert(s.id()); |
1631 | } |
1632 | } |
1633 | catch (ResourceException const&) |
1634 | |
1635 | === modified file 'src/scopes/internal/Logger.cpp' |
1636 | --- src/scopes/internal/Logger.cpp 2016-02-22 05:00:23 +0000 |
1637 | +++ src/scopes/internal/Logger.cpp 2016-06-17 07:24:44 +0000 |
1638 | @@ -41,10 +41,10 @@ |
1639 | static array<string, 5> const severities = {{"INFO", "WARNING", "ERROR", "FATAL", "TRACE"}}; |
1640 | |
1641 | static array<pair<string, LoggerChannel>, int(LoggerChannel::LastChannelEnum_)> const channel_names = |
1642 | -{ |
1643 | +{ { |
1644 | pair<string, LoggerChannel>{"", LoggerChannel::DefaultChannel}, |
1645 | pair<string, LoggerChannel>{"IPC", LoggerChannel::IPC} |
1646 | -}; |
1647 | +} }; |
1648 | |
1649 | } // namespace |
1650 | |
1651 | |
1652 | === modified file 'src/scopes/internal/RuntimeImpl.cpp' |
1653 | --- src/scopes/internal/RuntimeImpl.cpp 2016-02-22 14:16:26 +0000 |
1654 | +++ src/scopes/internal/RuntimeImpl.cpp 2016-06-17 07:24:44 +0000 |
1655 | @@ -366,7 +366,7 @@ |
1656 | string settings_schema = scope_dir.native() + "/" + scope_id_ + "-settings.ini"; |
1657 | |
1658 | boost::system::error_code ec; |
1659 | - if (boost::filesystem::exists(settings_schema, ec)) |
1660 | + if (boost::filesystem::exists(settings_schema, ec) && boost::filesystem::file_size(settings_schema) > 0) |
1661 | { |
1662 | shared_ptr<SettingsDB> db(SettingsDB::create_from_ini_file(settings_db, settings_schema)); |
1663 | scope_base->p->set_settings_db(db); |
1664 | |
1665 | === modified file 'src/scopes/internal/ScopeConfig.cpp' |
1666 | --- src/scopes/internal/ScopeConfig.cpp 2015-07-17 09:03:33 +0000 |
1667 | +++ src/scopes/internal/ScopeConfig.cpp 2016-06-17 07:24:44 +0000 |
1668 | @@ -67,7 +67,6 @@ |
1669 | const string fg_color_key = "ForegroundColor"; |
1670 | const string bg_color_key = "BackgroundColor"; |
1671 | const string shape_images_key = "ShapeImages"; |
1672 | - const string category_header_bg_key = "CategoryHeaderBackground"; |
1673 | const string preview_button_color_key = "PreviewButtonColor"; |
1674 | const string logo_overlay_color_key = "LogoOverlayColor"; |
1675 | const string pageheader_logo_key = "PageHeader.Logo"; |
1676 | @@ -317,7 +316,6 @@ |
1677 | fg_color_key, |
1678 | bg_color_key, |
1679 | shape_images_key, |
1680 | - category_header_bg_key, |
1681 | preview_button_color_key, |
1682 | logo_overlay_color_key, |
1683 | pageheader_logo_key, |
1684 | |
1685 | === modified file 'src/scopes/internal/smartscopes/SmartScopesClient.cpp' |
1686 | --- src/scopes/internal/smartscopes/SmartScopesClient.cpp 2016-02-25 11:40:06 +0000 |
1687 | +++ src/scopes/internal/smartscopes/SmartScopesClient.cpp 2016-06-17 07:24:44 +0000 |
1688 | @@ -592,6 +592,11 @@ |
1689 | |
1690 | void SmartScopesClient::handle_line(std::string const& json, PreviewReplyHandler const& handler) |
1691 | { |
1692 | + if (json.empty()) |
1693 | + { |
1694 | + return; |
1695 | + } |
1696 | + |
1697 | JsonNodeInterface::SPtr root_node; |
1698 | JsonNodeInterface::SPtr child_node; |
1699 | { |
1700 | @@ -640,6 +645,11 @@ |
1701 | |
1702 | void SmartScopesClient::handle_line(std::string const& json, SearchReplyHandler& handler) |
1703 | { |
1704 | + if (json.empty()) |
1705 | + { |
1706 | + return; |
1707 | + } |
1708 | + |
1709 | JsonNodeInterface::SPtr root_node; |
1710 | JsonNodeInterface::SPtr child_node; |
1711 | |
1712 | |
1713 | === modified file 'src/scopes/internal/zmq_middleware/StopPublisher.cpp' |
1714 | --- src/scopes/internal/zmq_middleware/StopPublisher.cpp 2014-11-18 07:04:04 +0000 |
1715 | +++ src/scopes/internal/zmq_middleware/StopPublisher.cpp 2016-06-17 07:24:44 +0000 |
1716 | @@ -121,7 +121,7 @@ |
1717 | s.set(zmqpp::socket_option::linger, 0); |
1718 | s.connect(endpoint_); |
1719 | s.subscribe(""); |
1720 | - return move(s); |
1721 | + return s; |
1722 | } |
1723 | } |
1724 | } |
1725 | |
1726 | === modified file 'src/scopes/testing/ScopeMetadataBuilder.cpp' |
1727 | --- src/scopes/testing/ScopeMetadataBuilder.cpp 2015-02-22 22:27:09 +0000 |
1728 | +++ src/scopes/testing/ScopeMetadataBuilder.cpp 2016-06-17 07:24:44 +0000 |
1729 | @@ -212,9 +212,7 @@ |
1730 | if (p->is_aggregator) |
1731 | impl->set_is_aggregator(*p->is_aggregator); |
1732 | |
1733 | - return unity::scopes::internal::ScopeMetadataImpl::create( |
1734 | - std::move( |
1735 | - std::unique_ptr<internal::ScopeMetadataImpl>{impl})); |
1736 | + return unity::scopes::internal::ScopeMetadataImpl::create(std::unique_ptr<internal::ScopeMetadataImpl>{impl}); |
1737 | } |
1738 | |
1739 | /// @endcond |
1740 | |
1741 | === modified file 'test/copyright/check_copyright.sh' |
1742 | --- test/copyright/check_copyright.sh 2015-11-13 06:33:11 +0000 |
1743 | +++ test/copyright/check_copyright.sh 2016-06-17 07:24:44 +0000 |
1744 | @@ -31,13 +31,7 @@ |
1745 | [ $# -lt 1 ] && usage |
1746 | [ $# -gt 2 ] && usage |
1747 | |
1748 | -# TODO: Temporary hack to work around broken licensecheck on xenial. Remove this once that is fixed. |
1749 | -distro=$(lsb_release -c -s) |
1750 | -[ "$distro" = "xenial" ] && { |
1751 | - exit 0 |
1752 | -} |
1753 | - |
1754 | -ignore_pat="\\.sci$" |
1755 | +ignore_pat="\\.sci$|.bzr|debian|tsan-suppress|valgrind-suppress|RELEASE_NOTES.md|partnerid|suppressions|README|_clang-format|TODO|CONFIGFILES|astyle-config|no_.*_cache|\\.txt$|\\.in$|\\.ini$|\\.xml$|\\.json$|\\.swp$|\\.gz$|\\.service$|\\.map$|\\.dox$|\\.html$|ParseArguments\\.cmake" |
1756 | |
1757 | # |
1758 | # We don't use the -i option of licensecheck to add ignore_dir to the pattern because Jenkins creates directories |
1759 | |
1760 | === modified file 'test/gtest/scopes/Registry/Registry_test.cpp' |
1761 | --- test/gtest/scopes/Registry/Registry_test.cpp 2015-07-06 13:47:54 +0000 |
1762 | +++ test/gtest/scopes/Registry/Registry_test.cpp 2016-06-17 07:24:44 +0000 |
1763 | @@ -122,7 +122,6 @@ |
1764 | EXPECT_EQ("fg_color", attrs["foreground-color"].get_string()); |
1765 | EXPECT_EQ("bg_color", attrs["background-color"].get_string()); |
1766 | EXPECT_TRUE(attrs["shape-images"].get_bool()); |
1767 | - EXPECT_EQ(TEST_SCOPE_A_PATH "/cat_header_bg_scheme", attrs["category-header-background"].get_string()); |
1768 | EXPECT_EQ("preview_button_color", attrs["preview-button-color"].get_string()); |
1769 | EXPECT_EQ("overlay_color", attrs["logo-overlay-color"].get_string()); |
1770 | auto page_hdr = attrs["page-header"].get_dict(); |
1771 | |
1772 | === modified file 'test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in' |
1773 | --- test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in 2014-12-03 09:25:10 +0000 |
1774 | +++ test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in 2016-06-17 07:24:44 +0000 |
1775 | @@ -16,7 +16,6 @@ |
1776 | ForegroundColor = fg_color |
1777 | BackgroundColor = bg_color |
1778 | ShapeImages = true |
1779 | -CategoryHeaderBackground = cat_header_bg_scheme |
1780 | PreviewButtonColor = preview_button_color |
1781 | LogoOverlayColor = overlay_color |
1782 | PageHeader.Logo = some_url |
1783 | |
1784 | === modified file 'test/gtest/scopes/internal/CMakeLists.txt' |
1785 | --- test/gtest/scopes/internal/CMakeLists.txt 2016-02-22 00:19:46 +0000 |
1786 | +++ test/gtest/scopes/internal/CMakeLists.txt 2016-06-17 07:24:44 +0000 |
1787 | @@ -1,6 +1,7 @@ |
1788 | add_subdirectory(CategoryRegistry) |
1789 | add_subdirectory(ConfigBase) |
1790 | add_subdirectory(DynamicLoader) |
1791 | +add_subdirectory(gobj_ptr) |
1792 | add_subdirectory(IniSettingsSchema) |
1793 | add_subdirectory(JsonNode) |
1794 | add_subdirectory(JsonSettingsSchema) |
1795 | |
1796 | === modified file 'test/gtest/scopes/internal/JsonNode/JsonNode_test.cpp' |
1797 | --- test/gtest/scopes/internal/JsonNode/JsonNode_test.cpp 2015-11-02 03:42:05 +0000 |
1798 | +++ test/gtest/scopes/internal/JsonNode/JsonNode_test.cpp 2016-06-17 07:24:44 +0000 |
1799 | @@ -43,6 +43,35 @@ |
1800 | JsonNodeInterface::SPtr root_node_; |
1801 | }; |
1802 | |
1803 | +TEST_F(JsonNodeTest, basic) |
1804 | +{ |
1805 | + try |
1806 | + { |
1807 | + JsonCppNode node(""); |
1808 | + FAIL(); |
1809 | + } |
1810 | + catch (unity::ResourceException const&) |
1811 | + { |
1812 | + } |
1813 | + |
1814 | + EXPECT_EQ(0, root_node_->size()); |
1815 | + EXPECT_EQ(JsonNodeInterface::Null, root_node_->type()); |
1816 | + |
1817 | + auto json = root_node_->to_json_string(); |
1818 | + EXPECT_EQ("null\n", json); |
1819 | + |
1820 | + root_node_->read_json("42"); |
1821 | + EXPECT_EQ(JsonNodeInterface::Int, root_node_->type()); |
1822 | + auto n = root_node_->get_node(); |
1823 | + EXPECT_EQ(42, n->as_int()); |
1824 | + |
1825 | + EXPECT_THROW(root_node_->read_json(""), unity::ResourceException); |
1826 | + EXPECT_THROW(root_node_->read_json(" "), unity::ResourceException); |
1827 | + |
1828 | + root_node_->clear(); |
1829 | + EXPECT_EQ(JsonNodeInterface::Null, root_node_->type()); |
1830 | +} |
1831 | + |
1832 | TEST_F(JsonNodeTest, flat_values) |
1833 | { |
1834 | std::string json_string = R"({ |
1835 | @@ -170,23 +199,45 @@ |
1836 | |
1837 | TEST_F(JsonNodeTest, from_variant) |
1838 | { |
1839 | - VariantArray va({Variant(1), Variant(2), Variant(true)}); |
1840 | - VariantMap vm; |
1841 | - vm["foo"] = "bar"; |
1842 | - vm["baz"] = 1; |
1843 | - vm["boo"] = 2.0f; |
1844 | - vm["zee"] = true; |
1845 | - vm["wee"] = Variant(va); |
1846 | - |
1847 | - Variant var(vm); |
1848 | - JsonCppNode node(var); |
1849 | - EXPECT_EQ("bar", node.get_node("foo")->as_string()); |
1850 | - EXPECT_EQ(1, node.get_node("baz")->as_int()); |
1851 | - EXPECT_TRUE(node.get_node("boo")->as_double() - 2.0f < 0.00001f); |
1852 | - EXPECT_TRUE(node.get_node("zee")->as_bool()); |
1853 | - EXPECT_EQ(1, node.get_node("wee")->get_node(0)->as_int()); |
1854 | - EXPECT_EQ(2, node.get_node("wee")->get_node(1)->as_int()); |
1855 | - EXPECT_TRUE(node.get_node("wee")->get_node(2)->as_bool()); |
1856 | + { |
1857 | + VariantArray va({Variant(1), Variant(2), Variant(true)}); |
1858 | + VariantMap vm; |
1859 | + vm["foo"] = "bar"; |
1860 | + vm["baz"] = 1; |
1861 | + vm["boo"] = 2.0f; |
1862 | + vm["zee"] = true; |
1863 | + vm["wee"] = Variant(va); |
1864 | + |
1865 | + Variant var(vm); |
1866 | + JsonCppNode node(var); |
1867 | + EXPECT_EQ(JsonNodeInterface::Object, node.type()); |
1868 | + EXPECT_EQ("bar", node.get_node("foo")->as_string()); |
1869 | + EXPECT_EQ(JsonNodeInterface::String, node.get_node("foo")->type()); |
1870 | + EXPECT_EQ(1, node.get_node("baz")->as_int()); |
1871 | + EXPECT_EQ(JsonNodeInterface::Real, node.get_node("boo")->type()); |
1872 | + EXPECT_TRUE(node.get_node("boo")->as_double() - 2.0f < 0.00001f); |
1873 | + EXPECT_EQ(JsonNodeInterface::Bool, node.get_node("zee")->type()); |
1874 | + EXPECT_TRUE(node.get_node("zee")->as_bool()); |
1875 | + EXPECT_EQ(JsonNodeInterface::Array, node.get_node("wee")->type()); |
1876 | + EXPECT_EQ(1, node.get_node("wee")->get_node(0)->as_int()); |
1877 | + EXPECT_EQ(2, node.get_node("wee")->get_node(1)->as_int()); |
1878 | + EXPECT_TRUE(node.get_node("wee")->get_node(2)->as_bool()); |
1879 | + } |
1880 | + |
1881 | + { |
1882 | + Variant var(1); |
1883 | + JsonCppNode node(var); |
1884 | + EXPECT_EQ(1, node.to_variant().get_int()); |
1885 | + } |
1886 | + |
1887 | + { |
1888 | + Variant var(2147483648); // > 2^31 - 1 |
1889 | + JsonCppNode node(var); |
1890 | + EXPECT_EQ(2147483648, node.to_variant().get_int64_t()); |
1891 | + } |
1892 | + |
1893 | + JsonCppNode null_node((Variant())); |
1894 | + EXPECT_EQ(JsonNodeInterface::Null, null_node.type()); |
1895 | } |
1896 | |
1897 | TEST_F(JsonNodeTest, to_variant) |
1898 | @@ -206,4 +257,89 @@ |
1899 | EXPECT_EQ("foo", arr[2].get_string()); |
1900 | } |
1901 | |
1902 | +TEST_F(JsonNodeTest, exceptions) |
1903 | +{ |
1904 | + EXPECT_THROW(JsonCppNode("syntax error"), unity::ResourceException); |
1905 | + |
1906 | + try |
1907 | + { |
1908 | + JsonCppNode().member_names(); |
1909 | + FAIL(); |
1910 | + } |
1911 | + catch (unity::LogicException const& e) |
1912 | + { |
1913 | + EXPECT_STREQ("unity::LogicException: Root node is not an object", e.what()); |
1914 | + } |
1915 | + |
1916 | + try |
1917 | + { |
1918 | + JsonCppNode().has_node("x"); |
1919 | + FAIL(); |
1920 | + } |
1921 | + catch (unity::LogicException const& e) |
1922 | + { |
1923 | + EXPECT_STREQ("unity::LogicException: Current node is empty", e.what()); |
1924 | + } |
1925 | + |
1926 | + try |
1927 | + { |
1928 | + JsonCppNode("42").as_string(); |
1929 | + FAIL(); |
1930 | + } |
1931 | + catch (unity::LogicException const& e) |
1932 | + { |
1933 | + EXPECT_STREQ("unity::LogicException: Node does not contain a string value", e.what()); |
1934 | + } |
1935 | + |
1936 | + try |
1937 | + { |
1938 | + JsonCppNode("true").as_double(); |
1939 | + FAIL(); |
1940 | + } |
1941 | + catch (unity::LogicException const& e) |
1942 | + { |
1943 | + EXPECT_STREQ("unity::LogicException: Node does not contain a double value", e.what()); |
1944 | + } |
1945 | + |
1946 | + try |
1947 | + { |
1948 | + JsonCppNode("true").as_int(); |
1949 | + FAIL(); |
1950 | + } |
1951 | + catch (unity::LogicException const& e) |
1952 | + { |
1953 | + EXPECT_STREQ("unity::LogicException: Node does not contain an int value", e.what()); |
1954 | + } |
1955 | + |
1956 | + try |
1957 | + { |
1958 | + JsonCppNode("3.14").as_bool(); |
1959 | + FAIL(); |
1960 | + } |
1961 | + catch (unity::LogicException const& e) |
1962 | + { |
1963 | + EXPECT_STREQ("unity::LogicException: Node does not contain a bool value", e.what()); |
1964 | + } |
1965 | + |
1966 | + try |
1967 | + { |
1968 | + JsonCppNode().get_node(25); |
1969 | + FAIL(); |
1970 | + } |
1971 | + catch (unity::LogicException const& e) |
1972 | + { |
1973 | + EXPECT_STREQ("unity::LogicException: Current node is empty", e.what()); |
1974 | + } |
1975 | + |
1976 | + try |
1977 | + { |
1978 | + JsonCppNode().get_node(); |
1979 | + FAIL(); |
1980 | + } |
1981 | + catch (unity::LogicException const& e) |
1982 | + { |
1983 | + EXPECT_STREQ("unity::LogicException: Current node is empty", e.what()); |
1984 | + } |
1985 | +} |
1986 | + |
1987 | } // namespace |
1988 | |
1989 | === modified file 'test/gtest/scopes/internal/JsonSettingsSchema/JsonSettingsSchema_test.cpp' |
1990 | --- test/gtest/scopes/internal/JsonSettingsSchema/JsonSettingsSchema_test.cpp 2015-01-13 11:44:33 +0000 |
1991 | +++ test/gtest/scopes/internal/JsonSettingsSchema/JsonSettingsSchema_test.cpp 2016-06-17 07:24:44 +0000 |
1992 | @@ -22,7 +22,6 @@ |
1993 | #include <unity/util/FileIO.h> |
1994 | |
1995 | #include <gtest/gtest.h> |
1996 | -#include <jsoncpp/json/json.h> |
1997 | |
1998 | using namespace unity; |
1999 | using namespace unity::scopes; |
2000 | @@ -153,6 +152,41 @@ |
2001 | EXPECT_EQ(Variant(), defs[10].get_dict()["defaultValue"]); |
2002 | } |
2003 | |
2004 | +TEST(JsonSettingsSchema, integer_sizes) |
2005 | +{ |
2006 | + char const* schema = R"delimiter( |
2007 | + { |
2008 | + "settings": |
2009 | + [ |
2010 | + { |
2011 | + "id": "double_temp", |
2012 | + "displayName": "floating-point default", |
2013 | + "type": "number", |
2014 | + "parameters": { |
2015 | + "defaultValue": 3.14 |
2016 | + } |
2017 | + }, |
2018 | + { |
2019 | + "id": "too_old", |
2020 | + "displayName": "won't fit into 32 bits", |
2021 | + "type": "number", |
2022 | + "parameters": { |
2023 | + "defaultValue": 2147483648 |
2024 | + } |
2025 | + } |
2026 | + ] |
2027 | + } |
2028 | + )delimiter"; |
2029 | + |
2030 | + auto s = JsonSettingsSchema::create(schema); |
2031 | + |
2032 | + auto defs = s->definitions(); |
2033 | + EXPECT_EQ(2, defs.size()); |
2034 | + |
2035 | + EXPECT_EQ(3.14, defs[0].get_dict()["defaultValue"].get_double()); |
2036 | + EXPECT_EQ(2147483648, defs[1].get_dict()["defaultValue"].get_double()); |
2037 | +} |
2038 | + |
2039 | TEST(JsonSettingsSchema, exceptions) |
2040 | { |
2041 | try |
2042 | @@ -162,9 +196,7 @@ |
2043 | } |
2044 | catch (ResourceException const& e) |
2045 | { |
2046 | - EXPECT_STREQ("unity::ResourceException: JsonSettingsSchema(): cannot parse schema: * Line 1, Column 1\n" |
2047 | - " Syntax error: value, object or array expected.\n", |
2048 | - e.what()); |
2049 | + EXPECT_STREQ("unity::ResourceException: JsonCppNode(): empty string is not a valid JSON", e.what()); |
2050 | } |
2051 | |
2052 | try |
2053 | @@ -335,7 +367,7 @@ |
2054 | } |
2055 | catch (ResourceException const& e) |
2056 | { |
2057 | - EXPECT_STREQ("unity::ResourceException: JsonSettingsSchema(): invalid \"type\" setting: " |
2058 | + EXPECT_STREQ("unity::ResourceException: JsonSettingsSchema(): invalid \"type\" definition: " |
2059 | "\"no_such_type\", id = \"x\"", |
2060 | e.what()); |
2061 | } |
2062 | |
2063 | === modified file 'test/gtest/scopes/internal/SettingsDB/SettingsDB_test.cpp' |
2064 | --- test/gtest/scopes/internal/SettingsDB/SettingsDB_test.cpp 2015-11-26 05:48:01 +0000 |
2065 | +++ test/gtest/scopes/internal/SettingsDB/SettingsDB_test.cpp 2016-06-17 07:24:44 +0000 |
2066 | @@ -22,6 +22,7 @@ |
2067 | |
2068 | #include <unity/UnityExceptions.h> |
2069 | |
2070 | +#include <boost/algorithm/string.hpp> |
2071 | #include <boost/regex.hpp> // Use Boost implementation until http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 is fixed. |
2072 | #include <gtest/gtest.h> |
2073 | #include <fcntl.h> |
2074 | @@ -321,10 +322,9 @@ |
2075 | } |
2076 | catch (ResourceException const& e) |
2077 | { |
2078 | - EXPECT_STREQ("unity::ResourceException: SettingsDB::create_from_json_string(): cannot parse schema, db = unused:\n" |
2079 | - " unity::ResourceException: JsonSettingsSchema(): cannot parse schema: * Line 1, Column 1\n" |
2080 | - " Syntax error: value, object or array expected.\n", |
2081 | - e.what()); |
2082 | + EXPECT_TRUE(boost::starts_with(e.what(), |
2083 | + "unity::ResourceException: SettingsDB::create_from_json_string(): cannot parse " |
2084 | + "schema, db = unused:")) << e.what(); |
2085 | } |
2086 | |
2087 | try |
2088 | |
2089 | === added directory 'test/gtest/scopes/internal/gobj_ptr' |
2090 | === added file 'test/gtest/scopes/internal/gobj_ptr/CMakeLists.txt' |
2091 | --- test/gtest/scopes/internal/gobj_ptr/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
2092 | +++ test/gtest/scopes/internal/gobj_ptr/CMakeLists.txt 2016-06-17 07:24:44 +0000 |
2093 | @@ -0,0 +1,3 @@ |
2094 | +add_executable(gobj_ptr_test gobj_ptr_test.cpp) |
2095 | +target_link_libraries(gobj_ptr_test ${TESTLIBS}) |
2096 | +add_test(gobj_ptr gobj_ptr_test) |
2097 | |
2098 | === added file 'test/gtest/scopes/internal/gobj_ptr/gobj_ptr_test.cpp' |
2099 | --- test/gtest/scopes/internal/gobj_ptr/gobj_ptr_test.cpp 1970-01-01 00:00:00 +0000 |
2100 | +++ test/gtest/scopes/internal/gobj_ptr/gobj_ptr_test.cpp 2016-06-17 07:24:44 +0000 |
2101 | @@ -0,0 +1,208 @@ |
2102 | +/* |
2103 | + * Copyright (C) 2013 Canonical Ltd. |
2104 | + * |
2105 | + * This program is free software: you can redistribute it and/or modify |
2106 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2107 | + * published by the Free Software Foundation. |
2108 | + * |
2109 | + * This program is distributed in the hope that it will be useful, |
2110 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2111 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2112 | + * GNU Lesser General Public License for more details. |
2113 | + * |
2114 | + * You should have received a copy of the GNU Lesser General Public License |
2115 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2116 | + * |
2117 | + * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> |
2118 | + */ |
2119 | + |
2120 | +#pragma GCC diagnostic push |
2121 | +#pragma GCC diagnostic ignored "-Wold-style-cast" |
2122 | +#pragma GCC diagnostic ignored "-Wcast-qual" |
2123 | + |
2124 | +#include <unity/scopes/internal/gobj_memory.h> |
2125 | +#include <glib-object.h> |
2126 | +#include <gtest/gtest.h> |
2127 | + |
2128 | +using namespace std; |
2129 | +using namespace unity::scopes::internal; |
2130 | + |
2131 | +TEST(Gobj_ptr, trivial) |
2132 | +{ |
2133 | + gobj_ptr<GObject> basic(G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr))); |
2134 | + EXPECT_TRUE(bool(basic)); |
2135 | + EXPECT_TRUE(G_IS_OBJECT(basic.get())); |
2136 | +} |
2137 | + |
2138 | +TEST(Gobj_ptr, compare) |
2139 | +{ |
2140 | + GObject* o1 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2141 | + GObject* o2 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2142 | + if (o1 > o2) |
2143 | + { |
2144 | + std::swap(o1, o2); |
2145 | + } |
2146 | + ASSERT_TRUE(o1 < o2); |
2147 | + gobj_ptr<GObject> u1(o1); |
2148 | + gobj_ptr<GObject> u2(o2); |
2149 | + |
2150 | + EXPECT_TRUE(!(u1 == nullptr)); |
2151 | + EXPECT_TRUE(u1 != nullptr); |
2152 | + EXPECT_TRUE(u1 != u2); |
2153 | + EXPECT_TRUE(!(u1 == u2)); |
2154 | + EXPECT_TRUE(u1 < u2); |
2155 | + EXPECT_TRUE(!(u2 < u1)); |
2156 | + EXPECT_TRUE(!(u1 == u2)); |
2157 | + EXPECT_TRUE(!(u2 == u1)); |
2158 | + EXPECT_TRUE(u1 <= u2); |
2159 | + EXPECT_TRUE(!(u2 <= u1)); |
2160 | +} |
2161 | + |
2162 | +// This is its own thing due to need to avoid double release. |
2163 | + |
2164 | +TEST(Gobj_ptr, equality) |
2165 | +{ |
2166 | + GObject* o = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2167 | + gobj_ptr<GObject> u1(o); |
2168 | + g_object_ref(o); |
2169 | + gobj_ptr<GObject> u2(o); |
2170 | + EXPECT_TRUE(u1 == u2); |
2171 | + EXPECT_TRUE(u2 == u1); |
2172 | + EXPECT_TRUE(!(u1 != u2)); |
2173 | + EXPECT_TRUE(!(u2 != u1)); |
2174 | +} |
2175 | + |
2176 | +TEST(Gobj_ptr, release) |
2177 | +{ |
2178 | + GObject* o = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2179 | + gobj_ptr<GObject> u(o); |
2180 | + EXPECT_TRUE(u != nullptr); |
2181 | + EXPECT_TRUE(u.get() != nullptr); |
2182 | + EXPECT_TRUE(o == u.release()); |
2183 | + EXPECT_TRUE(!u); |
2184 | + EXPECT_TRUE(u.get() == nullptr); |
2185 | + g_object_unref(o); |
2186 | +} |
2187 | + |
2188 | +TEST(Gobj_ptr, refcount) |
2189 | +{ |
2190 | + GObject* o = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2191 | + EXPECT_EQ(1, o->ref_count); |
2192 | + g_object_ref(o); |
2193 | + |
2194 | + { |
2195 | + EXPECT_EQ(2, o->ref_count); |
2196 | + gobj_ptr<GObject> u(o); |
2197 | + EXPECT_EQ(2, o->ref_count); |
2198 | + // Now it dies and refcount is reduced. |
2199 | + } |
2200 | + |
2201 | + EXPECT_EQ(1, o->ref_count); |
2202 | + g_object_unref(o); |
2203 | +} |
2204 | + |
2205 | +TEST(Gobj_ptr, copy) |
2206 | +{ |
2207 | + GObject* o = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2208 | + gobj_ptr<GObject> u(o); |
2209 | + EXPECT_EQ(1, u->ref_count); |
2210 | + gobj_ptr<GObject> u2(u); |
2211 | + EXPECT_EQ(2, u->ref_count); |
2212 | + gobj_ptr<GObject> u3 = u2; |
2213 | + EXPECT_EQ(3, u->ref_count); |
2214 | + u3.reset(); |
2215 | + u2.reset(); |
2216 | + EXPECT_EQ(1, u->ref_count); |
2217 | +} |
2218 | + |
2219 | +TEST(Gobj_ptr, swap) |
2220 | +{ |
2221 | + GObject* o1 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2222 | + GObject* o2 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2223 | + gobj_ptr<GObject> u1(o1); |
2224 | + gobj_ptr<GObject> u2(o2); |
2225 | + |
2226 | + u1.swap(u2); |
2227 | + EXPECT_EQ(o2, u1.get()); |
2228 | + EXPECT_EQ(o1, u2.get()); |
2229 | + |
2230 | + std::swap(u1, u2); |
2231 | + EXPECT_EQ(o1, u1.get()); |
2232 | + EXPECT_EQ(o2, u2.get()); |
2233 | +} |
2234 | + |
2235 | +TEST(Gobj_ptr, floating) |
2236 | +{ |
2237 | + GObject* o = G_OBJECT(g_object_new(G_TYPE_INITIALLY_UNOWNED, nullptr)); |
2238 | + try |
2239 | + { |
2240 | + gobj_ptr<GObject> u(o); |
2241 | + FAIL(); |
2242 | + } |
2243 | + catch (const invalid_argument& c) |
2244 | + { |
2245 | + EXPECT_EQ("Tried to add a floating gobject into a gobj_ptr.", string(c.what())); |
2246 | + } |
2247 | + // Object accepted after sinking. |
2248 | + g_object_ref_sink(o); |
2249 | + gobj_ptr<GObject> u(o); |
2250 | +} |
2251 | + |
2252 | +TEST(Gobj_ptr, move) |
2253 | +{ |
2254 | + GObject* o1 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2255 | + GObject* o2 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2256 | + g_object_ref(o1); |
2257 | + gobj_ptr<GObject> u1(o1); |
2258 | + gobj_ptr<GObject> u2(o2); |
2259 | + u1 = std::move(u2); |
2260 | + EXPECT_TRUE(u1.get() == o2); |
2261 | + EXPECT_TRUE(!u2); |
2262 | + EXPECT_TRUE(o1->ref_count == 1); |
2263 | + g_object_unref(o1); |
2264 | +} |
2265 | + |
2266 | +TEST(Gobj_ptr, null) |
2267 | +{ |
2268 | + GObject* o1 = NULL; |
2269 | + GObject* o3 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2270 | + gobj_ptr<GObject> u1(o1); |
2271 | + gobj_ptr<GObject> u2(nullptr); |
2272 | + gobj_ptr<GObject> u3(o3); |
2273 | + |
2274 | + EXPECT_TRUE(!u1); |
2275 | + EXPECT_TRUE(!u2); |
2276 | + u3 = nullptr; |
2277 | + EXPECT_TRUE(!u3); |
2278 | +} |
2279 | + |
2280 | +TEST(Gobj_ptr, reset) |
2281 | +{ |
2282 | + GObject* o1 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2283 | + GObject* o2 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); |
2284 | + gobj_ptr<GObject> u(o1); |
2285 | + |
2286 | + u.reset(o2); |
2287 | + EXPECT_EQ(o2, u.get()); |
2288 | + u.reset(nullptr); |
2289 | + EXPECT_TRUE(!u); |
2290 | +} |
2291 | + |
2292 | +TEST(Gobj_ptr, sizeoftest) |
2293 | +{ |
2294 | + EXPECT_EQ(sizeof(GObject*), sizeof(gobj_ptr<GObject>)); |
2295 | +} |
2296 | + |
2297 | +TEST(Gobj_ptr, deleter) |
2298 | +{ |
2299 | + gobj_ptr<GObject> u1; |
2300 | + EXPECT_TRUE(g_object_unref == u1.get_deleter()); |
2301 | +} |
2302 | + |
2303 | +int main(int argc, char** argv) |
2304 | +{ |
2305 | + ::testing::InitGoogleTest(&argc, argv); |
2306 | + return RUN_ALL_TESTS(); |
2307 | +} |
2308 | + |
2309 | +#pragma GCC diagnostic pop |
2310 | |
2311 | === modified file 'test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp' |
2312 | --- test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp 2016-02-29 15:57:12 +0000 |
2313 | +++ test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp 2016-06-17 07:24:44 +0000 |
2314 | @@ -130,13 +130,41 @@ |
2315 | EXPECT_EQ(nullptr, scopes[2].art); |
2316 | EXPECT_FALSE(scopes[2].invisible); |
2317 | EXPECT_EQ(nullptr, scopes[2].appearance); |
2318 | - EXPECT_EQ("[{\"displayName\":\"Location\",\"id\":\"location\",\"parameters\":{\"defaultValue\":" |
2319 | - "\"London\"},\"type\":\"string\"},{\"displayName\":\"Temperature Units\",\"id\":" |
2320 | - "\"unitTemp\",\"parameters\":{\"defaultValue\":1,\"values\":[\"Celsius\",\"Fahrenheit" |
2321 | - "\"]},\"type\":\"list\"},{\"displayName\":\"Age\",\"id\":\"age\",\"parameters\":{" |
2322 | - "\"defaultValue\":23},\"type\":\"number\"},{\"displayName\":\"Enabled\",\"id\":" |
2323 | - "\"enabled\",\"parameters\":{\"defaultValue\":true},\"type\":\"boolean\"}]\n", |
2324 | - *scopes[2].settings); |
2325 | + { |
2326 | + JsonCppNode node(*scopes[2].settings); |
2327 | + Variant v = node.to_variant(); |
2328 | + |
2329 | + VariantMap vm = v.get_array()[0].get_dict(); |
2330 | + EXPECT_EQ("Location", vm["displayName"].get_string()); |
2331 | + EXPECT_EQ("location", vm["id"].get_string()); |
2332 | + EXPECT_EQ("string", vm["type"].get_string()); |
2333 | + VariantMap params = vm["parameters"].get_dict(); |
2334 | + EXPECT_EQ("London", params["defaultValue"].get_string()); |
2335 | + |
2336 | + vm = v.get_array()[1].get_dict(); |
2337 | + EXPECT_EQ("Temperature Units", vm["displayName"].get_string()); |
2338 | + EXPECT_EQ("unitTemp", vm["id"].get_string()); |
2339 | + EXPECT_EQ("list", vm["type"].get_string()); |
2340 | + params = vm["parameters"].get_dict(); |
2341 | + EXPECT_EQ(1, params["defaultValue"].get_int()); |
2342 | + VariantArray choices = params["values"].get_array(); |
2343 | + EXPECT_EQ("Celsius", choices[0].get_string()); |
2344 | + EXPECT_EQ("Fahrenheit", choices[1].get_string()); |
2345 | + |
2346 | + vm = v.get_array()[2].get_dict(); |
2347 | + EXPECT_EQ("Age", vm["displayName"].get_string()); |
2348 | + EXPECT_EQ("age", vm["id"].get_string()); |
2349 | + EXPECT_EQ("number", vm["type"].get_string()); |
2350 | + params = vm["parameters"].get_dict(); |
2351 | + EXPECT_EQ(23, params["defaultValue"].get_int()); |
2352 | + |
2353 | + vm = v.get_array()[3].get_dict(); |
2354 | + EXPECT_EQ("Enabled", vm["displayName"].get_string()); |
2355 | + EXPECT_EQ("enabled", vm["id"].get_string()); |
2356 | + EXPECT_EQ("boolean", vm["type"].get_string()); |
2357 | + params = vm["parameters"].get_dict(); |
2358 | + EXPECT_TRUE(params["defaultValue"].get_bool()); |
2359 | + } |
2360 | ASSERT_EQ(4, scopes[2].keywords.size()); |
2361 | EXPECT_NE(scopes[2].keywords.end(), scopes[2].keywords.find("music")); |
2362 | EXPECT_NE(scopes[2].keywords.end(), scopes[2].keywords.find("video")); |
2363 | @@ -392,10 +420,30 @@ |
2364 | EXPECT_EQ("widget_id_C", columns[2][2][0]); |
2365 | |
2366 | ASSERT_EQ(3u, widgets.size()); |
2367 | - |
2368 | - EXPECT_EQ("{\"id\":\"widget_id_A\",\"text\":\"First widget.\",\"title\":\"Widget A\",\"type\":\"text\"}\n", widgets[0]); |
2369 | - EXPECT_EQ("{\"id\":\"widget_id_B\",\"text\":\"Second widget.\",\"title\":\"Widget B\",\"type\":\"text\"}\n", widgets[1]); |
2370 | - EXPECT_EQ("{\"id\":\"widget_id_C\",\"text\":\"Third widget.\",\"title\":\"Widget C\",\"type\":\"text\"}\n", widgets[2]); |
2371 | + { |
2372 | + auto json = widgets[0]; |
2373 | + JsonCppNode node(json); |
2374 | + EXPECT_EQ("widget_id_A", node.get_node("id")->as_string()); |
2375 | + EXPECT_EQ("First widget.", node.get_node("text")->as_string()); |
2376 | + EXPECT_EQ("Widget A", node.get_node("title")->as_string()); |
2377 | + EXPECT_EQ("text", node.get_node("type")->as_string()); |
2378 | + } |
2379 | + { |
2380 | + auto json = widgets[1]; |
2381 | + JsonCppNode node(json); |
2382 | + EXPECT_EQ("widget_id_B", node.get_node("id")->as_string()); |
2383 | + EXPECT_EQ("Second widget.", node.get_node("text")->as_string()); |
2384 | + EXPECT_EQ("Widget B", node.get_node("title")->as_string()); |
2385 | + EXPECT_EQ("text", node.get_node("type")->as_string()); |
2386 | + } |
2387 | + { |
2388 | + auto json = widgets[2]; |
2389 | + JsonCppNode node(json); |
2390 | + EXPECT_EQ("widget_id_C", node.get_node("id")->as_string()); |
2391 | + EXPECT_EQ("Third widget.", node.get_node("text")->as_string()); |
2392 | + EXPECT_EQ("Widget C", node.get_node("title")->as_string()); |
2393 | + EXPECT_EQ("text", node.get_node("type")->as_string()); |
2394 | + } |
2395 | } |
2396 | |
2397 | TEST_F(SmartScopesClientTest, consecutive_searches) |
Changelog nitpick inline.