tobicore  7.0.0
 All Classes Functions Variables Typedefs Enumerator Friends Groups Pages
ICSerializerRapid.cpp
1 /*
2  Copyright (C) 2009-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
3  Michele Tavella <michele.tavella@epfl.ch>
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "ICSerializerRapid.hpp"
20 #include <tobicore/TCException.hpp>
21 #include <tobicore/TCTools.hpp>
22 #include <iostream>
23 #include <tobicore/rapidxml.hpp>
24 #include <tobicore/rapidxml_print.hpp>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <vector>
28 
29 #ifdef __BORLANDC__
30 using namespace std;
31 #endif
32 using namespace rapidxml;
33 
34 
35 ICSerializerRapid::ICSerializerRapid(ICMessage* const message, const bool indent,
36  const bool declaration)
37  : ICSerializer(message) {
38  this->_indent = indent;
39  this->_declaration = declaration;
40 }
41 
43 }
44 
45 std::string* ICSerializerRapid::Serialize(std::string* buffer) {
46  if(buffer == NULL)
47  return NULL;
48  if(ICSerializer::message == NULL)
49  throw TCException("iC message not set, cannot serialize");
50 
51  buffer->clear();
52 
53  // XML document and buffers
54  xml_document<> doc;
55  std::string xml_as_string;
56  std::string xml_no_indent;
57 
58  // XML declaration
59  if(this->_declaration) {
60  xml_node<>* decl = doc.allocate_node(node_declaration);
61  decl->append_attribute(doc.allocate_attribute("version", "1.0"));
62  decl->append_attribute(doc.allocate_attribute("encoding", "utf-8"));
63  doc.append_node(decl);
64  }
65 
66  // Convert frame number to char array
67  char cacheFidx[16];
68  TCTools::itoa(ICSerializer::message->GetBlockIdx(), cacheFidx);
69 
70  // Same thing with timestamp and reference
71  std::string timestamp, reference;
72  ICSerializer::message->absolute.Get(&timestamp);
73  ICSerializer::message->relative.Get(&reference);
74 
75  // Root node
76  xml_node<>* root = doc.allocate_node(node_element, ICMESSAGE_ROOTNODE);
77  root->append_attribute(doc.allocate_attribute(ICMESSAGE_VERSIONNODE,
78  ICMESSAGE_VERSION));
79  root->append_attribute(doc.allocate_attribute(ICMESSAGE_FRAMENODE,
80  cacheFidx));
81  root->append_attribute(doc.allocate_attribute(ICMESSAGE_TIMESTAMPNODE,
82  timestamp.c_str()));
83  root->append_attribute(doc.allocate_attribute(ICMESSAGE_REFERENCENODE,
84  reference.c_str()));
85  doc.append_node(root);
86 
87  // Root node
88  ICClassifier* cptr = NULL;
89  ICClass* kptr = NULL;
92 
93  char* ptr_vtype = NULL;
94  char* ptr_ltype = NULL;
95  xml_node<>* cnode = NULL;
96  xml_node<>* knode = NULL;
97 
98  // Loop over classifiers
99  while(cit != ICSerializer::message->classifiers.End()) {
100  cptr = (*cit).second;
101  cnode = doc.allocate_node(node_element, ICMESSAGE_CLASSISIFERNODE);
102  cnode->append_attribute(doc.allocate_attribute(ICMESSAGE_NAMENODE,
103  cptr->GetChName()));
104  cnode->append_attribute(doc.allocate_attribute(ICMESSAGE_DESCNODE,
105  cptr->GetChDescription()));
106  root->append_node(cnode);
107 
108  // Attribute: Value Type
109  switch(cptr->GetValueType()) {
111  ptr_vtype = (char*)ICTYPES_ENTRY_UNDEF;
112  break;
114  ptr_vtype = (char*)ICTYPES_ENTRY_PROB;
115  break;
117  ptr_vtype = (char*)ICTYPES_ENTRY_DIST;
118  break;
120  ptr_vtype = (char*)ICTYPES_ENTRY_CLBL;
121  break;
123  ptr_vtype = (char*)ICTYPES_ENTRY_RCOE;
124  break;
125  }
126  cnode->append_attribute(doc.allocate_attribute(ICMESSAGE_VTYPENODE,
127  ptr_vtype));
128 
129  // Attribute: Label Type
130  switch(cptr->GetLabelType()) {
132  ptr_ltype = (char*)ICTYPES_LABEL_CLASS;
133  break;
135  ptr_ltype = (char*)ICTYPES_LABEL_UNDEF;
136  break;
138  ptr_ltype = (char*)ICTYPES_LABEL_BIOSIG;
139  break;
141  ptr_ltype = (char*)ICTYPES_LABEL_CUSTOM;
142  break;
143  }
144  cnode->append_attribute(doc.allocate_attribute(ICMESSAGE_LTYPENODE,
145  ptr_ltype));
146 
147  // Loop over classes
148  kit = cptr->classes.Begin();
149  while(kit != cptr->classes.End()) {
150  kptr = (*kit).second;
151  knode = doc.allocate_node(node_element, ICMESSAGE_CLASSNODE,
152  kptr->GetChValue());
153  knode->append_attribute(doc.allocate_attribute(ICMESSAGE_LABELNODE,
154  kptr->GetChLabel()));
155  cnode->append_node(knode);
156 
157  // Next class
158  ++kit;
159  }
160  // Next classifier
161  ++cit;
162  }
163 
164  if(this->_indent)
165  print(std::back_inserter(*buffer), doc);
166  else
167  print(std::back_inserter(*buffer), doc, print_no_indenting);
168  return buffer;
169 }
170 
171 std::string* ICSerializerRapid::Deserialize(std::string* const buffer) {
172  bool initialize = ICSerializer::message->classifiers.Empty();
173 
174  xml_document<> doc;
175  std::string cache;
176  std::vector<char> xml_copy(buffer->begin(), buffer->end());
177  xml_copy.push_back('\0');
178  doc.parse<parse_declaration_node | parse_no_data_nodes>(&xml_copy[0]);
179 
180  /* Trasverse to root node */
181  xml_node<>* rootnode = doc.first_node(ICMESSAGE_ROOTNODE);
182  if(rootnode == NULL) {
183  throw TCException("iC root node not found",
184  #ifdef _WIN32
185  __FUNCSIG__
186  #else
187  __PRETTY_FUNCTION__
188  #endif
189  );
190  }
191 
192  /* Check version */
193  cache = rootnode->first_attribute(ICMESSAGE_VERSIONNODE)->value();
194  if(cache.compare(ICMESSAGE_VERSION) != 0) {
195  std::string info("iC version mismatch: ");
196  info.append(ICMESSAGE_VERSION);
197  info.append("/");
198  info.append(cache);
199  throw TCException(info,
200  #ifdef _WIN32
201  __FUNCSIG__
202  #else
203  __PRETTY_FUNCTION__
204  #endif
205  );
206  }
207 
208  /* Get frame number */
209  cache = rootnode->first_attribute(ICMESSAGE_FRAMENODE)->value();
210  ICSerializer::message->SetBlockIdx(atol(cache.c_str()));
211 
212  // Get timestamp
213  cache = rootnode->first_attribute(ICMESSAGE_TIMESTAMPNODE)->value();
215  cache = rootnode->first_attribute(ICMESSAGE_REFERENCENODE)->value();
217 
218  /* Define classifier and class nodes */
219  xml_node<>* cnode = NULL;
220  xml_node<>* knode = NULL;
221 
222  ICClassifier* cptr = NULL;
223  ICClass* kptr = NULL;
224 
225  /* Trasverse classifier nodes */
226  cnode = rootnode->first_node(ICMESSAGE_CLASSISIFERNODE);
227  while(cnode != NULL) {
228  std::string cname, cdesc, tvtype, tltype;
229  ICVtype cvtype;
230  ICLtype cltype;
231 
232  /* Get name, description, value and label types */
233  cname = cnode->first_attribute(ICMESSAGE_NAMENODE)->value();
234  if(initialize) {
235  cdesc = cnode->first_attribute(ICMESSAGE_DESCNODE)->value();
236  tvtype = cnode->first_attribute(ICMESSAGE_VTYPENODE)->value();
237  tltype = cnode->first_attribute(ICMESSAGE_LTYPENODE)->value();
238 
239  /* Convert value and label types */
240  cvtype = ICClassifier::ValueType(tvtype);
241  cltype = ICClassifier::LabelType(tltype);
242 
243  /* Create classifier */
244  if(ICSerializer::message->classifiers.Has(cname) == true)
245  return NULL;
246 
247  cptr = new ICClassifier(cname, cdesc, cvtype, cltype);
249  } else
250  cptr = ICSerializer::message->classifiers.Get(cname);
251 
252  /* Trasverse class nodes */
253  knode = cnode->first_node(ICMESSAGE_CLASSNODE);
254  while(knode != NULL) {
255  std::string klabel =
256  knode->first_attribute(ICMESSAGE_LABELNODE)->value();
257  std::string tvalue = knode->value();
258 
259  if(initialize) {
260  if(cptr->classes.Has(klabel) == true)
261  return NULL;
262  kptr = new ICClass(klabel, (ICValue)atof(tvalue.c_str()));
263  cptr->classes.Add(kptr);
264  } else
265  cptr->classes.Get(klabel)->SetValue(TCTools::atof(tvalue.c_str()));
266 
267  /* Next class node */
268  knode = knode->next_sibling(ICMESSAGE_CLASSNODE);
269  }
270 
271  /* Next classifier node */
272  cnode = cnode->next_sibling(ICMESSAGE_CLASSISIFERNODE);
273  }
274  return buffer;
275 }