Classdesc 3.44
stringKeyMap.h
1/*
2 @copyright Russell Standish 2016
3 @author Russell Standish
4 This file is part of Classdesc
5
6 Open source licensed under the MIT license. See LICENSE for details.
7*/
8
9#ifndef CLASSDESC_STRINGKEYMAP_H
10#define CLASSDESC_STRINGKEYMAP_H
11#include <map>
12#include <string>
13#include "classdesc.h"
14#include "json_pack_base.h"
15#include "xml_pack_base.h"
16#include "xml_unpack_base.h"
17#include "xsd_generate_base.h"
18
19namespace classdesc
20{
23 template <class T>
24 struct StringKeyMap: public std::map<std::string, T> {};
25
26 template <class T>
27 struct is_associative_container<classdesc::StringKeyMap<T> >: public true_type {};
28
29 template <class T> struct is_stringKeyMap<classdesc::StringKeyMap<T> >: public true_type {};
30
31}
32
33namespace classdesc
34{
35 template <class T>
36 void convert(StringKeyMap<T>& map, const json_pack_t& j)
37 {if (j.type()!=RESTProcessType::null) j>>map;}
38
39 template <class T>
40 void json_pack_stringKeyMap(json_pack_t& j,const string& d, const StringKeyMap<T>& a)
41 {
42 try
43 {
44 json5_parser::mValue& parent=json_find(j,head(d));
45 if (parent.type()!=json5_parser::obj_type)
46 throw json_pack_error("attempt to pack an array member into a non-object");
47 else
48 {
49 typename StringKeyMap<T>::const_iterator i=a.begin();
50 for (; i!=a.end(); ++i)
51 json_pack(j,d+"."+i->first, i->second);
52 }
53 }
54 catch (json_pack_error&)
55 {
56 if (j.throw_on_error) throw;
57 }
58 }
59
60 template <class T>
61 void json_unpack_stringKeyMap(json_pack_t& j,const string& d, StringKeyMap<T>& a)
62 {
63 try
64 {
65 const json5_parser::mValue& val=json_find(j,d);
66 switch (val.type())
67 {
68 case json5_parser::obj_type:
69 {
70 const json5_parser::mObject& arr=val.get_obj();
71 a.clear();
72 for (json5_parser::mObject::const_iterator i=arr.begin(); i!=arr.end(); ++i)
73 json_unpack(j,d+"."+i->first,a[i->first]);
74 }
75 break;
76 case json5_parser::null_type:
77 a.clear();
78 break;
79 default:
80 throw json_pack_error("%s is not an array",d.c_str());
81 }
82 }
83 catch (json_pack_error&)
84 {
85 if (j.throw_on_error) throw;
86 }
87 }
88
89 template <class T>
90 void xsd_generate(xsd_generate_t& g, const string& d, const StringKeyMap<T>& a)
91 {
92 std::ostringstream os;
93 // element name is given by the type name
94 string eName=typeName<T>().c_str();
95 eName=eName.substr(0,eName.find('<')); //trim off any template args
96 // strip leading namespace and qualifiers
97 const char *el=eName.c_str()+eName.length();
98 while (el!=eName.c_str() && *(el-1)!=' ' && *(el-1)!=':') el--;
99
100 string type=transformTypeName(typeName<StringKeyMap<T> >());
101 os << " <xs:complexType name=\"" << type << "\">\n";
102 os << " <xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">\n";
103 // There doesn't seem to be any way of specifying the element type
104 // here without also constraining the element name!
105 // os << " <xs:element name=\".*\" type=\""<<xsd_typeName<T>()<<"\"/>\n";
106 os << " <xs:any processContents=\"lax\"/>\n";
107 os << " </xs:sequence>\n";
108 os << " </xs:complexType>\n";
109 g.addMember(tail(d), xsd_typeName<StringKeyMap<T> >());
110 g.defineType(type, os.str());
111 g.addDependency(type, xsd_typeName<T>());
112 // ensure that the value type as a definition also
113 xsd_generate(g,"",T());
114
115 }
116}
117
118using classdesc::xsd_generate;
119
120namespace classdesc_access
121{
122 namespace cd=classdesc;
123
124 template <class T>
125 struct access_json_pack<classdesc::StringKeyMap<T> >
126 {
127 template <class U>
128 void operator()(cd::json_pack_t& j,const cd::string& d,U& x)
129 {json_pack_stringKeyMap(j,d,x);}
130 };
131
132 template <class T>
133 struct access_json_unpack<classdesc::StringKeyMap<T> >
134 {
135 void operator()(cd::json_unpack_t& j,const cd::string& d,cd::StringKeyMap<T>& x)
136 {json_unpack_stringKeyMap(j,d,x);}
137 void operator()(cd::json_unpack_t& j,const cd::string& d,const cd::StringKeyMap<T>& x)
138 {}
139 };
140
141 template <class T>
142 struct access_xml_pack<classdesc::StringKeyMap<T> >
143 {
144 template <class U>
145 void operator()(cd::xml_pack_t& x,const cd::string& d,U& arg)
146 {
147 cd::xml_pack_t::Tag tag(x,d);
148 for (typename cd::StringKeyMap<T>::const_iterator i=arg.begin();
149 i!=arg.end(); ++i)
150 ::xml_pack(x,d+"."+i->first,i->second);
151 }
152 };
153
154 template <class T>
155 struct access_xml_unpack<classdesc::StringKeyMap<T> >
156 {
157 template <class U>
158 void operator()(cd::xml_unpack_t& x,const cd::string& d,U& arg)
159 {
160 for (cd::xml_unpack_t::ContentMap::const_iterator i=x.firstToken(d);
161 i!=x.endToken(d); ++i)
162 {
163 std::string key=i->first;
164 size_t p=i->first.rfind('.');
165 if (p!=std::string::npos) key=key.substr(p);
166 ::xml_unpack(x,i->first,arg[key]);
167 }
168 }
169 };
170
171}
172
173
174#ifdef _CLASSDESC
175#pragma omit json_pack classdesc::StringKeyMap
176#pragma omit json_unpack classdesc::StringKeyMap
177#pragma omit xml_pack classdesc::StringKeyMap
178#pragma omit xml_unpack classdesc::StringKeyMap
179#pragma omit xsd_generate classdesc::StringKeyMap
180#endif
181#endif
Definition json_pack_base.h:35
Definition json_pack_base.h:99
Definition xsd_generate_base.h:22
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition classdesc_access.h:20
Contains definitions related to classdesc functionality.
json5_parser::mValue & json_find(json5_parser::mValue &x, std::string name)
find an object named by name within the json object x
Definition json_pack_base.h:228
void json_pack(json_pack_t &o, const string &d, T &a)
forward declare generic json operations
Definition json_pack_epilogue.h:61
Definition stringKeyMap.h:24
determines if T is a standard associative container
Definition classdesc.h:321
true_type if T is a StringKeyMap
Definition classdesc.h:364
Definition json_pack_epilogue.h:92
Definition json_pack_epilogue.h:104
Definition classdesc_access.h:23
Definition classdesc_access.h:24
XML serialisation descriptor.
XML deserialisation descriptor.