Merge lp:~compiz-team/compiz/compiz.fix_1063617.6 into lp:compiz/0.9.9

Proposed by Sam Spilsbury
Status: Merged
Approved by: Sam Spilsbury
Approved revision: 3493
Merged at revision: 3491
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1063617.6
Merge into: lp:compiz/0.9.9
Diff against target: 913 lines (+645/-109)
5 files modified
compizconfig/libcompizconfig/include/ccs.h (+14/-3)
compizconfig/libcompizconfig/src/compiz.cpp (+0/-55)
compizconfig/libcompizconfig/src/main.c (+129/-50)
compizconfig/libcompizconfig/tests/CMakeLists.txt (+2/-1)
compizconfig/libcompizconfig/tests/compizconfig_test_ccs_setting.cpp (+500/-0)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1063617.6
Reviewer Review Type Date Requested Status
Sam Spilsbury Approve
PS Jenkins bot (community) continuous-integration Approve
Daniel van Vugt Approve
Review via email: mp+136664@code.launchpad.net

Commit message

Provide infrastructure for testing the ccsSet* functions

Provide infrastructure for testing value containers.

It will be useful for later tests to be able to specify a value and allow
the use of templates to automatically create a CCSValue for those. These value
containers handle the tricky issues around how those values have their
lifecycles managed, as every value needs a valid parent setting in order
to be destroyed properly (as type information is stored in the parent
setting).

ContainNormal and ContainList are convenience functions which forward
to NormalValueContainer and ListValueContainer.

NormalValueContainer will wrap a normal "raw" value and provide a means to
construct a CCSValue on-demand and a way to get the raw value.

ListValueContainer will wrap a normal "raw" value as the first member of
a CCSSettingValueList, safely wrap that in a SettingValueListWrapper and
then provde a means to construct a CCSValue from that on-demand and a way
to get the raw CCSSettingValueList.

Both use RawValueCopy in order to handle internal value copy semantics
properly.

RawValueCopy returns a copy of the "raw" value (i.e. not another
CCSSettingValue), doing deep copies as appropriate. It is implemented
as a series of template specializations to handle some of the various
pointer types, such as const char * and CCSSettingValueList.

Also provide SetWithDisallowedValue template + specializations

It will be useful in future to provide methods in the tests to set a
value which would otherwise be disallowed because it is out of range for
a particular type. The actual out-of-range error varies between the
types, so we need to provide some specializations for some of the
different types

Also expose ccsCopyInfo and separate ccsCopyValueInto from ccsCopyValue. The
latter returns a newly allocated copy of the value, the former deep-

There was a bug in ccsCopyInfo which caused the copy-from info to be
overwritten with the copy-to info. That was fixed.

There are no tests at present. The testing framework for this will be
quite similar to what we need to test settings, and will be adapted for
that purpose in testing this code.

Description of the change

This branch is effectively just compiz.fix_1063617.2 , compiz.fix_1063617.4 and compiz.fix_1063617.5 all merged together with ccsSettingDefaultImplNew moved to main.c (due to a linker error)

This is about preparing a fix for (LP: #1063617).

(LP: #1063617) is really complicated. The problem is that there is a feedback loop between integrated keys and normal keys which can cause the integrated keys to read from normal keys which will be out of date or incorrect because they were never updated.

A part of that problem is that we need to have more information in the backends as to why setting a key to a particular value failed or succeeded.

Provide infrastructure for testing the ccsSet* functions

Provide infrastructure for testing value containers.

It will be useful for later tests to be able to specify a value and allow
the use of templates to automatically create a CCSValue for those. These value
containers handle the tricky issues around how those values have their
lifecycles managed, as every value needs a valid parent setting in order
to be destroyed properly (as type information is stored in the parent
setting).

ContainNormal and ContainList are convenience functions which forward
to NormalValueContainer and ListValueContainer.

NormalValueContainer will wrap a normal "raw" value and provide a means to
construct a CCSValue on-demand and a way to get the raw value.

ListValueContainer will wrap a normal "raw" value as the first member of
a CCSSettingValueList, safely wrap that in a SettingValueListWrapper and
then provde a means to construct a CCSValue from that on-demand and a way
to get the raw CCSSettingValueList.

Both use RawValueCopy in order to handle internal value copy semantics
properly.

RawValueCopy returns a copy of the "raw" value (i.e. not another
CCSSettingValue), doing deep copies as appropriate. It is implemented
as a series of template specializations to handle some of the various
pointer types, such as const char * and CCSSettingValueList.

Also provide SetWithDisallowedValue template + specializations

It will be useful in future to provide methods in the tests to set a
value which would otherwise be disallowed because it is out of range for
a particular type. The actual out-of-range error varies between the
types, so we need to provide some specializations for some of the
different types

Also expose ccsCopyInfo and separate ccsCopyValueInto from ccsCopyValue. The
latter returns a newly allocated copy of the value, the former deep-

There was a bug in ccsCopyInfo which caused the copy-from info to be
overwritten with the copy-to info. That was fixed.

There are no tests at present. The testing framework for this will be
quite similar to what we need to test settings, and will be adapted for
that purpose in testing this code.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Verified it builds, runs and passes tests.

I assume I don't need to review it again as I've reviewed the branches that make it up already.

review: Approve
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Yep, thanks.

On Thu, Nov 29, 2012 at 2:33 PM, Daniel van Vugt
<email address hidden> wrote:
> Review: Approve
>
> Verified it builds, runs and passes tests.

BTW, we have CI for that :)

>
> I assume I don't need to review it again as I've reviewed the branches that make it up already.
> --
> https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1063617.6/+merge/136664
> Your team Compiz Maintainers is subscribed to branch lp:compiz.

--
Sam Spilsbury

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

No we don't have CI for all that. Jenkins doesn't "run" the code and test it manually like I did.

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Fair point, but it does build it, run the unit tests and memcheck
them. I assumed that's what you meant by "passes tests"

I use coverage tools to ensure that those tests exercise as much as
the code I have changed as possible, so that we don't need to do tons
of manual testing on every single branch.

Speaking of which, why do we still not have coverage reports in jenkins.

On Thu, Nov 29, 2012 at 4:03 PM, Daniel van Vugt
<email address hidden> wrote:
> No we don't have CI for all that. Jenkins doesn't "run" the code and test it manually like I did.
> --
> https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1063617.6/+merge/136664
> Your team Compiz Maintainers is subscribed to branch lp:compiz.

--
Sam Spilsbury

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Sam Spilsbury (smspillaz) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'compizconfig/libcompizconfig/include/ccs.h'
2--- compizconfig/libcompizconfig/include/ccs.h 2012-11-27 03:59:26 +0000
3+++ compizconfig/libcompizconfig/include/ccs.h 2012-11-29 07:57:18 +0000
4@@ -722,6 +722,8 @@
5 void ccsFreeSetting (CCSSetting *setting);
6 void ccsFreeGroup (CCSGroup *group);
7 void ccsFreeSubGroup (CCSSubGroup *subGroup);
8+void ccsCleanupSettingInfo (CCSSettingInfo *info,
9+ CCSSettingType type);
10 void ccsFreeSettingValue (CCSSettingValue *value);
11 void ccsFreeSettingValueWithType (CCSSettingValue *v,
12 CCSSettingType type);
13@@ -792,9 +794,18 @@
14
15 /* Deep copy setting value */
16 CCSSettingValue *
17-ccsCopyValue (CCSSettingValue *orig,
18- CCSSettingType type,
19- CCSSettingInfo *info);
20+ccsCopyValue (const CCSSettingValue *orig,
21+ CCSSettingType type,
22+ CCSSettingInfo *info);
23+Bool
24+ccsCopyValueInto (const CCSSettingValue *from,
25+ CCSSettingValue *to,
26+ CCSSettingType type,
27+ CCSSettingInfo *info);
28+
29+/* Deep copy setting info */
30+void
31+ccsCopyInfo (const CCSSettingInfo *from, CCSSettingInfo *to, CCSSettingType type);
32
33 /* Converts an array of data items to a setting value list. Behaves similar
34 to ccsGetListFromStringArray */
35
36=== modified file 'compizconfig/libcompizconfig/src/compiz.cpp'
37--- compizconfig/libcompizconfig/src/compiz.cpp 2012-11-24 11:18:52 +0000
38+++ compizconfig/libcompizconfig/src/compiz.cpp 2012-11-29 07:57:18 +0000
39@@ -658,61 +658,6 @@
40 }
41 }
42
43-CCSSetting *
44-ccsSettingDefaultImplNew (CCSPlugin *plugin,
45- const char *name,
46- CCSSettingType type,
47- const char *shortDesc,
48- const char *longDesc,
49- const char *hints,
50- const char *group,
51- const char *subGroup,
52- CCSSettingDefaultValueInitializerFunc valueInit,
53- void *valueInitData,
54- CCSSettingInfoInitializerFunc infoInit,
55- void *infoInitData,
56- CCSObjectAllocationInterface *ai,
57- const CCSInterfaceTable *interfaces)
58-{
59- CCSSetting *setting = (CCSSetting *) calloc (1, sizeof (CCSSetting));
60-
61- if (!setting)
62- return NULL;
63-
64- ccsObjectInit (setting, ai);
65-
66- CCSSettingPrivate *sPrivate = (CCSSettingPrivate *) (*ai->calloc_) (ai->allocator, 1, sizeof (CCSSettingPrivate));
67-
68- if (!sPrivate)
69- {
70- free (setting);
71- return NULL;
72- }
73-
74- ccsObjectSetPrivate (setting, (CCSPrivate *) sPrivate);
75- ccsObjectAddInterface (setting, (CCSInterface *) interfaces->settingInterface, GET_INTERFACE_TYPE (CCSSettingInterface));
76- ccsSettingRef (setting);
77-
78- sPrivate->parent = plugin;
79- sPrivate->isDefault = TRUE;
80- sPrivate->name = strdup (name);
81-
82- sPrivate->shortDesc = strdup (shortDesc);
83- sPrivate->longDesc = strdup (longDesc);
84- sPrivate->group = strdup (group);
85- sPrivate->hints = strdup (hints);
86- sPrivate->subGroup = strdup (subGroup);
87-
88- sPrivate->type = type;
89- sPrivate->value = &sPrivate->defaultValue;
90- sPrivate->defaultValue.parent = setting;
91-
92- (*infoInit) (type, &sPrivate->info, infoInitData);
93- (*valueInit) (type, &sPrivate->info, &sPrivate->defaultValue, valueInitData);
94-
95- return setting;
96-}
97-
98 static void
99 addOptionForPluginPB (CCSPlugin * plugin,
100 const char * name,
101
102=== modified file 'compizconfig/libcompizconfig/src/main.c'
103--- compizconfig/libcompizconfig/src/main.c 2012-11-24 10:01:33 +0000
104+++ compizconfig/libcompizconfig/src/main.c 2012-11-29 07:57:18 +0000
105@@ -800,6 +800,29 @@
106 free (p);
107 }
108
109+void
110+ccsCleanupSettingInfo (CCSSettingInfo *info,
111+ CCSSettingType type)
112+{
113+ switch (type)
114+ {
115+ case TypeInt:
116+ ccsIntDescListFree (info->forInt.desc, TRUE);
117+ break;
118+ case TypeString:
119+ ccsStrRestrictionListFree (info->forString.restriction, TRUE);
120+ break;
121+ case TypeList:
122+ if (info->forList.listType == TypeInt)
123+ ccsIntDescListFree (info->forList.listInfo->
124+ forInt.desc, TRUE);
125+ free (info->forList.listInfo);
126+ break;
127+ default:
128+ break;
129+ }
130+}
131+
132 static void
133 ccsFreeSettingDefault (CCSSetting *s)
134 {
135@@ -812,30 +835,13 @@
136 free (sPrivate->subGroup);
137 free (sPrivate->hints);
138
139- switch (sPrivate->type)
140- {
141- case TypeInt:
142- ccsIntDescListFree (sPrivate->info.forInt.desc, TRUE);
143- break;
144- case TypeString:
145- ccsStrRestrictionListFree (sPrivate->info.forString.restriction, TRUE);
146- break;
147- case TypeList:
148- if (sPrivate->info.forList.listType == TypeInt)
149- ccsIntDescListFree (sPrivate->info.forList.listInfo->
150- forInt.desc, TRUE);
151- free (sPrivate->info.forList.listInfo);
152- //ccsSettingValueListFree (sPrivate->value->value.asList, TRUE);
153- break;
154- default:
155- break;
156- }
157-
158 if (&sPrivate->defaultValue != sPrivate->value)
159 {
160 ccsFreeSettingValue (sPrivate->value);
161 }
162
163+ ccsCleanupSettingInfo (&sPrivate->info, sPrivate->type);
164+
165 ccsFreeSettingValue (&sPrivate->defaultValue);
166
167 ccsObjectFinalize (s);
168@@ -1819,10 +1825,10 @@
169 return TRUE;
170 }
171
172-static void
173-copyInfo (CCSSettingInfo *from, CCSSettingInfo *to, CCSSettingType type)
174+void
175+ccsCopyInfo (const CCSSettingInfo *from, CCSSettingInfo *to, CCSSettingType type)
176 {
177- memcpy (from, to, sizeof (CCSSettingInfo));
178+ memcpy (to, from, sizeof (CCSSettingInfo));
179
180 switch (type)
181 {
182@@ -1896,7 +1902,7 @@
183 {
184 to->forList.listInfo = calloc (1, sizeof (CCSSettingInfo));
185
186- copyInfo (from->forList.listInfo, to->forList.listInfo, from->forList.listType);
187+ ccsCopyInfo (from->forList.listInfo, to->forList.listInfo, from->forList.listType);
188 }
189
190 break;
191@@ -1997,7 +2003,7 @@
192 }
193
194 copyValue (&fromPrivate->defaultValue, &toPrivate->defaultValue);
195- copyInfo (&fromPrivate->info, &toPrivate->info, fromPrivate->type);
196+ ccsCopyInfo (&fromPrivate->info, &toPrivate->info, fromPrivate->type);
197
198 toPrivate->defaultValue.parent = to;
199 toPrivate->privatePtr = NULL;
200@@ -2468,63 +2474,81 @@
201 return TRUE;
202 }
203
204-CCSSettingValue *
205-ccsCopyValue (CCSSettingValue *orig,
206- CCSSettingType type,
207- CCSSettingInfo *info)
208+Bool
209+ccsCopyValueInto (const CCSSettingValue *from,
210+ CCSSettingValue *to,
211+ CCSSettingType type,
212+ CCSSettingInfo *info)
213 {
214- CCSSettingValue *value = calloc (1, sizeof (CCSSettingValue));
215-
216- if (!value)
217- return NULL;
218-
219- value->refCount = 1;
220- value->parent = orig->parent;
221- value->isListChild = orig->isListChild;
222-
223- CCSSettingType vType = value->isListChild ? info->forList.listType : type;
224+ to->parent = from->parent;
225+ to->isListChild = from->isListChild;
226+
227+ CCSSettingType vType = to->isListChild ? info->forList.listType : type;
228
229 switch (vType)
230 {
231 case TypeInt:
232- value->value.asInt = orig->value.asInt;
233+ to->value.asInt = from->value.asInt;
234 break;
235 case TypeBool:
236- value->value.asBool = orig->value.asBool;
237+ to->value.asBool = from->value.asBool;
238 break;
239 case TypeFloat:
240- value->value.asFloat = orig->value.asFloat;
241+ to->value.asFloat = from->value.asFloat;
242 break;
243 case TypeString:
244- value->value.asString = strdup (orig->value.asString);
245+ to->value.asString = strdup (from->value.asString);
246 break;
247 case TypeMatch:
248- value->value.asMatch = strdup (orig->value.asMatch);
249+ to->value.asMatch = strdup (from->value.asMatch);
250 break;
251 case TypeKey:
252- memcpy (&value->value.asKey, &orig->value.asKey,
253+ memcpy (&to->value.asKey, &from->value.asKey,
254 sizeof (CCSSettingKeyValue));
255 break;
256 case TypeButton:
257- memcpy (&value->value.asButton, &orig->value.asButton,
258+ memcpy (&to->value.asButton, &from->value.asButton,
259 sizeof (CCSSettingButtonValue));
260 break;
261 case TypeEdge:
262- value->value.asEdge = orig->value.asEdge;
263+ to->value.asEdge = from->value.asEdge;
264 break;
265 case TypeBell:
266- value->value.asBell = orig->value.asBell;
267+ to->value.asBell = from->value.asBell;
268 break;
269 case TypeColor:
270- memcpy (&value->value.asColor, &orig->value.asColor,
271+ memcpy (&to->value.asColor, &from->value.asColor,
272 sizeof (CCSSettingColorValue));
273 break;
274+ case TypeList:
275+ assert (from->parent != NULL);
276+ to->value.asList = ccsCopyList (from->value.asList, from->parent);
277 default:
278- free (value);
279- return NULL;
280+ ccsError ("unexpected setting type in ccsCopyValueInto");
281+ return FALSE;
282 break;
283 }
284
285+ return TRUE;
286+}
287+
288+CCSSettingValue *
289+ccsCopyValue (const CCSSettingValue *orig,
290+ CCSSettingType type,
291+ CCSSettingInfo *info)
292+{
293+ CCSSettingValue *value = calloc (1, sizeof (CCSSettingValue));
294+
295+ if (!value)
296+ return NULL;
297+
298+ value->refCount = 1;
299+ if (!ccsCopyValueInto (orig, value, type, info))
300+ {
301+ free (value);
302+ return NULL;
303+ }
304+
305 return value;
306 }
307
308@@ -5568,6 +5592,61 @@
309 (*(GET_INTERFACE (CCSIntegratedSettingInterface, setting))->free) (setting);
310 }
311
312+CCSSetting *
313+ccsSettingDefaultImplNew (CCSPlugin *plugin,
314+ const char *name,
315+ CCSSettingType type,
316+ const char *shortDesc,
317+ const char *longDesc,
318+ const char *hints,
319+ const char *group,
320+ const char *subGroup,
321+ CCSSettingDefaultValueInitializerFunc valueInit,
322+ void *valueInitData,
323+ CCSSettingInfoInitializerFunc infoInit,
324+ void *infoInitData,
325+ CCSObjectAllocationInterface *ai,
326+ const CCSInterfaceTable *interfaces)
327+{
328+ CCSSetting *setting = (CCSSetting *) calloc (1, sizeof (CCSSetting));
329+
330+ if (!setting)
331+ return NULL;
332+
333+ ccsObjectInit (setting, ai);
334+
335+ CCSSettingPrivate *sPrivate = (CCSSettingPrivate *) (*ai->calloc_) (ai->allocator, 1, sizeof (CCSSettingPrivate));
336+
337+ if (!sPrivate)
338+ {
339+ free (setting);
340+ return NULL;
341+ }
342+
343+ ccsObjectSetPrivate (setting, (CCSPrivate *) sPrivate);
344+ ccsObjectAddInterface (setting, (CCSInterface *) interfaces->settingInterface, GET_INTERFACE_TYPE (CCSSettingInterface));
345+ ccsSettingRef (setting);
346+
347+ sPrivate->parent = plugin;
348+ sPrivate->isDefault = TRUE;
349+ sPrivate->name = strdup (name);
350+
351+ sPrivate->shortDesc = strdup (shortDesc);
352+ sPrivate->longDesc = strdup (longDesc);
353+ sPrivate->group = strdup (group);
354+ sPrivate->hints = strdup (hints);
355+ sPrivate->subGroup = strdup (subGroup);
356+
357+ sPrivate->type = type;
358+ sPrivate->value = &sPrivate->defaultValue;
359+ sPrivate->defaultValue.parent = setting;
360+
361+ (*infoInit) (type, &sPrivate->info, infoInitData);
362+ (*valueInit) (type, &sPrivate->info, &sPrivate->defaultValue, valueInitData);
363+
364+ return setting;
365+}
366+
367 /* CCSSharedIntegratedSettingInfo implementation */
368
369 typedef struct _CCSSharedIntegratedSettingInfoPrivate CCSSharedIntegratedSettingInfoPrivate;
370
371=== modified file 'compizconfig/libcompizconfig/tests/CMakeLists.txt'
372--- compizconfig/libcompizconfig/tests/CMakeLists.txt 2012-09-29 14:33:53 +0000
373+++ compizconfig/libcompizconfig/tests/CMakeLists.txt 2012-11-29 07:57:18 +0000
374@@ -113,7 +113,8 @@
375 compizconfig
376 compizconfig_ccs_context_mock
377 compizconfig_ccs_plugin_mock
378- compizconfig_ccs_setting_mock)
379+ compizconfig_ccs_setting_mock
380+ compizconfig_ccs_list_wrapper)
381
382 target_link_libraries (compizconfig_test_ccs_text_file
383 ${GTEST_BOTH_LIBRARIES}
384
385=== modified file 'compizconfig/libcompizconfig/tests/compizconfig_test_ccs_setting.cpp'
386--- compizconfig/libcompizconfig/tests/compizconfig_test_ccs_setting.cpp 2012-11-24 11:18:52 +0000
387+++ compizconfig/libcompizconfig/tests/compizconfig_test_ccs_setting.cpp 2012-11-29 07:57:18 +0000
388@@ -26,14 +26,21 @@
389 #include <boost/make_shared.hpp>
390 #include <boost/function.hpp>
391
392+#include <X11/Xlib.h>
393+
394 #include <ccs.h>
395
396 #include "compizconfig_ccs_setting_mock.h"
397 #include "compizconfig_ccs_plugin_mock.h"
398+#include "compizconfig_ccs_list_wrapper.h"
399+
400+namespace cci = compiz::config::impl;
401+namespace cc = compiz::config;
402
403 using ::testing::_;
404 using ::testing::Return;
405 using ::testing::InSequence;
406+using ::testing::ReturnNull;
407
408 TEST(CCSSettingTest, TestMock)
409 {
410@@ -134,6 +141,11 @@
411
412 namespace
413 {
414+
415+typedef boost::shared_ptr <CCSSettingInfo> CCSSettingInfoPtr;
416+typedef boost::shared_ptr <CCSSettingValue> CCSSettingValuePtr;
417+typedef boost::shared_ptr <CCSSetting> CCSSettingPtr;
418+
419 class MockInitializerFuncs
420 {
421 public:
422@@ -250,3 +262,491 @@
423 EXPECT_EQ (ccsSettingGetParent (setting.get ()),
424 plugin.get ());
425 }
426+
427+namespace
428+{
429+
430+/* Used to copy different raw values */
431+template <typename SettingValueType>
432+class CopyRawValueBase
433+{
434+ public:
435+
436+ CopyRawValueBase (const SettingValueType &value) :
437+ mValue (value)
438+ {
439+ }
440+
441+ protected:
442+
443+ const SettingValueType &mValue;
444+};
445+
446+template <typename SettingValueType>
447+class CopyRawValue :
448+ public CopyRawValueBase <SettingValueType>
449+{
450+ public:
451+
452+ typedef SettingValueType ReturnType;
453+ typedef CopyRawValueBase <SettingValueType> Parent;
454+
455+ CopyRawValue (const SettingValueType &value) :
456+ CopyRawValueBase <SettingValueType> (value)
457+ {
458+ }
459+
460+ SettingValueType operator () ()
461+ {
462+ return Parent::mValue;
463+ }
464+};
465+
466+template <>
467+class CopyRawValue <const char *> :
468+ public CopyRawValueBase <const char *>
469+{
470+ public:
471+
472+ typedef const char * ReturnType;
473+ typedef CopyRawValueBase <const char *> Parent;
474+
475+ CopyRawValue (const char * value) :
476+ CopyRawValueBase <const char *> (value)
477+ {
478+ }
479+
480+ ReturnType operator () ()
481+ {
482+ /* XXX: Valgrind complains here that mValue is uninitialized, but
483+ * verification using gdb confirms that isn't true */
484+ return strdup (Parent::mValue);
485+ }
486+};
487+
488+template <>
489+class CopyRawValue <cci::SettingValueListWrapper::Ptr> :
490+ public CopyRawValueBase <cci::SettingValueListWrapper::Ptr>
491+{
492+ public:
493+
494+ typedef CCSSettingValueList ReturnType;
495+ typedef CopyRawValueBase <cci::SettingValueListWrapper::Ptr> Parent;
496+
497+ CopyRawValue (const cci::SettingValueListWrapper::Ptr &value) :
498+ CopyRawValueBase <cci::SettingValueListWrapper::Ptr> (value)
499+ {
500+ }
501+
502+ ReturnType operator () ()
503+ {
504+ return ccsCopyList (*Parent::mValue,
505+ Parent::mValue->setting ().get ());
506+ }
507+};
508+
509+CCSSettingValue *
510+NewCCSSettingValue ()
511+{
512+ CCSSettingValue *value =
513+ reinterpret_cast <CCSSettingValue *> (
514+ calloc (1, sizeof (CCSSettingValue)));
515+
516+ value->refCount = 1;
517+
518+ return value;
519+}
520+
521+template <typename SettingValueType>
522+CCSSettingValue *
523+RawValueToCCSValue (const SettingValueType &value)
524+{
525+ typedef typename CopyRawValue <SettingValueType>::ReturnType UnionType;
526+
527+ CCSSettingValue *settingValue = NewCCSSettingValue ();
528+ UnionType *unionMember =
529+ reinterpret_cast <UnionType *> (&settingValue->value);
530+
531+ *unionMember = (CopyRawValue <SettingValueType> (value)) ();
532+
533+ return settingValue;
534+}
535+
536+template <typename SettingValueType>
537+CCSSettingValuePtr
538+RawValueToListValue (const SettingValueType &value)
539+{
540+ return ListValueToSettingValueList (RawValueToCCSValue (value));
541+}
542+
543+class ContainedValueGenerator
544+{
545+ private:
546+
547+ const CCSSettingValuePtr &
548+ InitializedSpawnedValue (const CCSSettingValuePtr &value,
549+ CCSSettingType type,
550+ const CCSSettingInfoPtr &info)
551+ {
552+ const CCSSettingPtr &setting (GetSetting (type, info));
553+ value->parent = setting.get ();
554+ mContainedValues.push_back (value);
555+
556+ return mContainedValues.back ();
557+ }
558+
559+ public:
560+
561+ template <typename SettingValueType>
562+ const CCSSettingValuePtr &
563+ SpawnValueForInfoAndType (const SettingValueType &rawValue,
564+ CCSSettingType type,
565+ const CCSSettingInfoPtr &info)
566+ {
567+
568+ CCSSettingValuePtr value (AutoDestroy (RawValueToCCSValue <SettingValueType> (rawValue),
569+ ccsSettingValueUnref));
570+
571+ return InitializedSpawnedValue (value, type, info);
572+ }
573+
574+ const CCSSettingPtr &
575+ GetSetting (CCSSettingType type,
576+ const CCSSettingInfoPtr &info)
577+ {
578+ if (!mSetting)
579+ SetupMockSetting (type, info);
580+
581+ return mSetting;
582+ }
583+
584+ private:
585+
586+ void SetupMockSetting (CCSSettingType type,
587+ const CCSSettingInfoPtr &info)
588+ {
589+ mSetting = AutoDestroy (ccsMockSettingNew (),
590+ ccsSettingUnref);
591+
592+ CCSSettingGMock *settingMock =
593+ reinterpret_cast <CCSSettingGMock *> (
594+ ccsObjectGetPrivate (mSetting.get ()));
595+
596+ EXPECT_CALL (*settingMock, getType ())
597+ .WillRepeatedly (Return (type));
598+
599+ EXPECT_CALL (*settingMock, getInfo ())
600+ .WillRepeatedly (Return (info.get ()));
601+
602+ EXPECT_CALL (*settingMock, getDefaultValue ())
603+ .WillRepeatedly (ReturnNull ());
604+ }
605+
606+ /* This must always be before the value
607+ * as the values hold a weak reference to
608+ * it */
609+ CCSSettingPtr mSetting;
610+ std::vector <CCSSettingValuePtr> mContainedValues;
611+
612+};
613+
614+/* ValueContainer Interface */
615+template <typename SettingValueType>
616+class ValueContainer
617+{
618+ public:
619+
620+ typedef boost::shared_ptr <ValueContainer> Ptr;
621+
622+ virtual const SettingValueType &
623+ getRawValue (CCSSettingType type,
624+ const CCSSettingInfoPtr &info) = 0;
625+ virtual const CCSSettingValuePtr &
626+ getContainedValue (CCSSettingType type,
627+ const CCSSettingInfoPtr &info) = 0;
628+};
629+
630+class NormalValueContainerBase
631+{
632+ protected:
633+
634+ ContainedValueGenerator mContainedValueGenerator;
635+ CCSSettingValuePtr mContainedValue;
636+};
637+
638+template <typename SettingValueType>
639+class NormalValueContainer :
640+ public NormalValueContainerBase,
641+ public ValueContainer <SettingValueType>
642+{
643+ public:
644+
645+ NormalValueContainer (const SettingValueType &value) :
646+ mRawValue (value)
647+ {
648+ }
649+
650+ const SettingValueType &
651+ getRawValue (CCSSettingType type,
652+ const CCSSettingInfoPtr &info)
653+ {
654+ return mRawValue;
655+ }
656+
657+ const CCSSettingValuePtr &
658+ getContainedValue (CCSSettingType type,
659+ const CCSSettingInfoPtr &info)
660+ {
661+ if (!mContainedValue)
662+ mContainedValue = mContainedValueGenerator.SpawnValueForInfoAndType (mRawValue,
663+ type,
664+ info);
665+
666+ return mContainedValue;
667+ }
668+
669+ private:
670+
671+ const SettingValueType &mRawValue;
672+};
673+
674+template <typename SettingValueType>
675+typename NormalValueContainer <SettingValueType>::Ptr
676+ContainNormal (const SettingValueType &value)
677+{
678+ return boost::make_shared <NormalValueContainer <SettingValueType> > (value);
679+}
680+
681+class ListValueContainerBase :
682+ public ValueContainer <CCSSettingValueList>
683+{
684+ protected:
685+
686+ const CCSSettingValuePtr &
687+ getContainedValue (CCSSettingType type,
688+ const CCSSettingInfoPtr &info)
689+ {
690+ if (!mContainedWrapper)
691+ {
692+ const cci::SettingValueListWrapper::Ptr &wrapper (SetupWrapper (type, info));
693+
694+ mContainedWrapper =
695+ mContainedValueGenerator.SpawnValueForInfoAndType (wrapper,
696+ type,
697+ info);
698+ }
699+
700+ return mContainedWrapper;
701+ }
702+
703+ const CCSSettingValueList &
704+ getRawValue (CCSSettingType type,
705+ const CCSSettingInfoPtr &info)
706+ {
707+ const cci::SettingValueListWrapper::Ptr &wrapper (SetupWrapper (type, info));
708+
709+ return *wrapper;
710+ }
711+
712+ cci::SettingValueListWrapper::Ptr mWrapper;
713+
714+ /* ccsFreeSettingValue has an implicit
715+ * dependency on mWrapper (CCSSettingValue -> CCSSetting ->
716+ * CCSSettingInfo -> cci::SettingValueListWrapper), these should
717+ * be kept after mWrapper here */
718+ ContainedValueGenerator mContainedValueGenerator;
719+ CCSSettingValuePtr mContainedWrapper;
720+
721+ private:
722+
723+ const cci::SettingValueListWrapper::Ptr &
724+ SetupWrapper (CCSSettingType type,
725+ const CCSSettingInfoPtr &info)
726+ {
727+ if (!mWrapper)
728+ {
729+ const CCSSettingPtr &setting (mContainedValueGenerator.GetSetting (type, info));
730+ CCSSettingValue *value = GetValueForListWrapper ();
731+
732+ value->parent = setting.get ();
733+ value->isListChild = TRUE;
734+ mWrapper.reset (new cci::SettingValueListWrapper (NULL,
735+ cci::Deep,
736+ type,
737+ info,
738+ setting));
739+ mWrapper->append (value);
740+ }
741+
742+ return mWrapper;
743+ }
744+
745+ virtual CCSSettingValue * GetValueForListWrapper () = 0;
746+};
747+
748+template <typename SettingValueType>
749+class ListValueContainer :
750+ public ListValueContainerBase
751+{
752+ public:
753+
754+ ListValueContainer (const SettingValueType &value) :
755+ mRawChildValue (value)
756+ {
757+ }
758+
759+ private:
760+
761+ CCSSettingValue * GetValueForListWrapper ()
762+ {
763+ return RawValueToCCSValue (mRawChildValue);
764+ }
765+
766+ const SettingValueType &mRawChildValue;
767+};
768+
769+template <typename SettingValueType>
770+typename ValueContainer <CCSSettingValueList>::Ptr
771+ContainList (const SettingValueType &value)
772+{
773+ return boost::make_shared <ListValueContainer <SettingValueType> > (value);
774+}
775+
776+template <typename SettingValueType>
777+struct SettingMutators
778+{
779+ typedef Bool (*SetFunction) (CCSSetting *setting,
780+ SettingValueType data,
781+ Bool);
782+ typedef Bool (*GetFunction) (CCSSetting *setting,
783+ SettingValueType *);
784+};
785+
786+class SetWithDisallowedValueBase
787+{
788+ protected:
789+
790+ SetWithDisallowedValueBase (const CCSSettingPtr &setting,
791+ const CCSSettingInfoPtr &info) :
792+ mSetting (setting),
793+ mInfo (info)
794+ {
795+ }
796+
797+ CCSSettingPtr mSetting;
798+ CCSSettingInfoPtr mInfo;
799+};
800+
801+template <typename SettingValueType>
802+class SetWithDisallowedValueTemplatedBase :
803+ public SetWithDisallowedValueBase
804+{
805+ protected:
806+
807+ typedef typename SettingMutators <SettingValueType>::SetFunction SetFunction;
808+
809+ SetWithDisallowedValueTemplatedBase (SetFunction setFunction,
810+ const CCSSettingPtr &setting,
811+ const CCSSettingInfoPtr &info) :
812+ SetWithDisallowedValueBase (setting, info),
813+ mSetFunction (setFunction)
814+ {
815+ }
816+
817+ SetFunction mSetFunction;
818+};
819+
820+template <typename SettingValueType>
821+class SetWithDisallowedValue :
822+ public SetWithDisallowedValueTemplatedBase <SettingValueType>
823+{
824+ public:
825+
826+ typedef typename SettingMutators <SettingValueType>::SetFunction SetFunction;
827+
828+ SetWithDisallowedValue (SetFunction setFunction,
829+ const CCSSettingPtr &setting,
830+ const CCSSettingInfoPtr &info) :
831+ SetWithDisallowedValueTemplatedBase <SettingValueType> (setFunction, setting, info)
832+ {
833+ }
834+
835+ Bool operator () ()
836+ {
837+ return FALSE;
838+ }
839+};
840+
841+template <>
842+class SetWithDisallowedValue <int> :
843+ public SetWithDisallowedValueTemplatedBase <int>
844+{
845+ public:
846+
847+ typedef typename SettingMutators <int>::SetFunction SetFunction;
848+ typedef SetWithDisallowedValueTemplatedBase <int> Parent;
849+
850+ SetWithDisallowedValue (SetFunction setFunction,
851+ const CCSSettingPtr &setting,
852+ const CCSSettingInfoPtr &info) :
853+ SetWithDisallowedValueTemplatedBase <int> (setFunction, setting, info)
854+ {
855+ }
856+
857+ Bool operator () ()
858+ {
859+ return (*Parent::mSetFunction) (Parent::mSetting.get (),
860+ Parent::mInfo->forInt.min - 1,
861+ FALSE);
862+ }
863+};
864+
865+template <>
866+class SetWithDisallowedValue <float> :
867+ public SetWithDisallowedValueTemplatedBase <float>
868+{
869+ public:
870+
871+ typedef typename SettingMutators <float>::SetFunction SetFunction;
872+ typedef SetWithDisallowedValueTemplatedBase <float> Parent;
873+
874+ SetWithDisallowedValue (SetFunction setFunction,
875+ const CCSSettingPtr &setting,
876+ const CCSSettingInfoPtr &info) :
877+ SetWithDisallowedValueTemplatedBase <float> (setFunction, setting, info)
878+ {
879+ }
880+
881+ Bool operator () ()
882+ {
883+ return (*Parent::mSetFunction) (Parent::mSetting.get (),
884+ Parent::mInfo->forFloat.min - 1,
885+ FALSE);
886+ }
887+};
888+
889+template <>
890+class SetWithDisallowedValue <const char *> :
891+ public SetWithDisallowedValueTemplatedBase <const char *>
892+{
893+ public:
894+
895+ typedef typename SettingMutators <const char *>::SetFunction SetFunction;
896+ typedef SetWithDisallowedValueTemplatedBase <const char *> Parent;
897+
898+ SetWithDisallowedValue (SetFunction setFunction,
899+ const CCSSettingPtr &setting,
900+ const CCSSettingInfoPtr &info) :
901+ SetWithDisallowedValueTemplatedBase <const char *> (setFunction, setting, info)
902+ {
903+ }
904+
905+ Bool operator () ()
906+ {
907+ return (*Parent::mSetFunction) (Parent::mSetting.get (),
908+ NULL,
909+ FALSE);
910+ }
911+};
912+
913+}

Subscribers

People subscribed via source and target branches