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 STRINGKEYMAP_H
10 #define 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 
19 namespace classdesc
20 {
23  template <class T>
24  struct StringKeyMap: public std::map<std::string, T> {};
25 
26  template <class T>
27  void json_pack_stringKeyMap(json_pack_t& j,const string& d, const StringKeyMap<T>& a)
28  {
29  try
30  {
31  json_spirit::mValue& parent=json_find(j,head(d));
32  if (parent.type()!=json_spirit::obj_type)
33  throw json_pack_error("attempt to pack an array member into a non-object");
34  else
35  {
36  typename StringKeyMap<T>::const_iterator i=a.begin();
37  for (; i!=a.end(); ++i)
38  json_pack(j,d+"."+i->first, i->second);
39  }
40  }
41  catch (json_pack_error&)
42  {
43  if (j.throw_on_error) throw;
44  }
45  }
46 
47  template <class T>
48  void json_unpack_stringKeyMap(json_pack_t& j,const string& d, StringKeyMap<T>& a)
49  {
50  try
51  {
52  const json_spirit::mValue& val=json_find(j,d);
53  if (val.type()!=json_spirit::obj_type)
54  throw json_pack_error("%s is not an array",d.c_str());
55  else
56  {
57  const json_spirit::mObject& arr=val.get_obj();
58  for (json_spirit::mObject::const_iterator i=arr.begin(); i!=arr.end(); ++i)
59  json_unpack(j,d+"."+i->first,a[i->first]);
60  }
61  }
62  catch (json_pack_error&)
63  {
64  if (j.throw_on_error) throw;
65  }
66  }
67 
68  template <class T>
69  void xsd_generate(xsd_generate_t& g, const string& d, const StringKeyMap<T>& a)
70  {
71  std::ostringstream os;
72  // element name is given by the type name
73  string eName=typeName<T>().c_str();
74  eName=eName.substr(0,eName.find('<')); //trim off any template args
75  // strip leading namespace and qualifiers
76  const char *el=eName.c_str()+eName.length();
77  while (el!=eName.c_str() && *(el-1)!=' ' && *(el-1)!=':') el--;
78 
79  string type=transformTypeName(typeName<StringKeyMap<T> >());
80  os << " <xs:complexType name=\"" << type << "\">\n";
81  os << " <xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">\n";
82  // There doesn't seem to be any way of specifying the element type
83  // here without also constraining the element name!
84  // os << " <xs:element name=\".*\" type=\""<<xsd_typeName<T>()<<"\"/>\n";
85  os << " <xs:any processContents=\"lax\"/>\n";
86  os << " </xs:sequence>\n";
87  os << " </xs:complexType>\n";
88  g.addMember(tail(d), xsd_typeName<StringKeyMap<T> >());
89  g.defineType(type, os.str());
90  g.addDependency(type, xsd_typeName<T>());
91  // ensure that the value type as a definition also
92  xsd_generate(g,"",T());
93 
94  }
95 }
96 
97 using classdesc::xsd_generate;
98 
99 namespace classdesc_access
100 {
101  namespace cd=classdesc;
102 
103  template <class T>
104  struct access_json_pack<classdesc::StringKeyMap<T> >
105  {
106  template <class U>
107  void operator()(cd::json_pack_t& j,const cd::string& d,U& x)
108  {json_pack_stringKeyMap(j,d,x);}
109  };
110 
111  template <class T>
112  struct access_json_unpack<classdesc::StringKeyMap<T> >
113  {
114  void operator()(cd::json_unpack_t& j,const cd::string& d,cd::StringKeyMap<T>& x)
115  {json_unpack_stringKeyMap(j,d,x);}
116  void operator()(cd::json_unpack_t& j,const cd::string& d,const cd::StringKeyMap<T>& x)
117  {}
118  };
119 
120  template <class T>
121  struct access_xml_pack<classdesc::StringKeyMap<T> >
122  {
123  template <class U>
124  void operator()(cd::xml_pack_t& x,const cd::string& d,U& arg)
125  {
126  cd::xml_pack_t::Tag tag(x,d);
127  for (typename cd::StringKeyMap<T>::const_iterator i=arg.begin();
128  i!=arg.end(); ++i)
129  ::xml_pack(x,d+"."+i->first,i->second);
130  }
131  };
132 
133  template <class T>
134  struct access_xml_unpack<classdesc::StringKeyMap<T> >
135  {
136  template <class U>
137  void operator()(cd::xml_unpack_t& x,const cd::string& d,U& arg)
138  {
139  for (cd::xml_unpack_t::ContentMap::const_iterator i=x.firstToken(d);
140  i!=x.endToken(d); ++i)
141  {
142  std::string key=i->first;
143  size_t p=i->first.rfind('.');
144  if (p!=std::string::npos) key=key.substr(p);
145  ::xml_unpack(x,i->first,arg[key]);
146  }
147  }
148  };
149 
150 }
151 
152 
153 #ifdef _CLASSDESC
154 #pragma omit json_pack classdesc::StringKeyMap
155 #pragma omit json_unpack classdesc::StringKeyMap
156 #pragma omit xml_pack classdesc::StringKeyMap
157 #pragma omit xml_unpack classdesc::StringKeyMap
158 #pragma omit xsd_generate classdesc::StringKeyMap
159 #endif
160 #include "stringKeyMap.cd"
161 #endif
Definition: json_pack_base.h:43
void addDependency(const string &type, const string &dependency)
add a dependency between type and dependency (XSD qualifed name)
Definition: xsd_generate_base.h:99
XML serialisation descriptor.
void json_pack(json_pack_t &o, const string &d, T &a)
forward declare generic json operations
Definition: json_pack_epilogue.h:53
Definition: classdesc_access.h:23
Definition: classdesc_access.h:26
bool throw_on_error
enable exceptions on error conditions
Definition: json_pack_base.h:46
void addMember(const string &name, const string &memberType)
add an attribute name with XSD type memberType
Definition: xsd_generate_base.h:65
Definition: xml_unpack_base.h:268
Definition: classdesc_access.h:25
Definition: xml_pack_base.h:49
Definition: json_pack_base.h:20
ContentMap::const_iterator firstToken(const std::string &prefix) const
first token starting with prefix
Definition: xml_unpack_base.h:321
void defineType(const string &type, const string &def)
add a complete XSD definition for type
Definition: xsd_generate_base.h:145
Contains definitions related to classdesc functionality.
Definition: arrays.h:2514
XML deserialisation descriptor.
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition: accessor.h:55
json_spirit::mValue & json_find(json_spirit::mValue &x, std::string name)
find an object named by name within the json object x
Definition: json_pack_base.h:73
Definition: stringKeyMap.h:24
Definition: classdesc_access.h:24
Definition: xsd_generate_base.h:20