libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRNMap.cpp
Go to the documentation of this file.
1 /* Copyright 2006-2016 Yann LEYDIER, CoReNum, INSA-Lyon, ENS-Lyon
2  *
3  * This file is part of libcrn.
4  *
5  * libcrn is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser 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  * libcrn 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 Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libcrn. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: CRNMap.cpp
19  * \author Yann LEYDIER
20  */
21 
22 #include <CRNData/CRNMap.h>
23 #include <CRNException.h>
24 #include <CRNData/CRNVector.h>
25 #include <CRNData/CRNDataFactory.h>
26 #include <CRNIO/CRNIO.h>
27 #include <CRNi18n.h>
28 using namespace crn;
29 
34 Map::Map() = default;
35 
39 Map::~Map() = default;
40 
41 Map::Map(const Map &other)
42 {
43  for (const auto &p : other)
44  data.emplace(p.first, Clone(*p.second));
45 }
46 
47 Map& Map::operator=(const Map &other)
48 {
49  data.clear();
50  for (const auto &p : other)
51  data.emplace(p.first, Clone(*p.second));
52  return *this;
53 }
54 
61 SObject Map::Get(const String &s)
62 {
63  auto it = Find(s);
64  if (it == end())
65  return nullptr;
66  else
67  return it->second;
68 }
69 
76 SCObject Map::Get(const String &s) const
77 {
78  auto it = Find(s);
79  if (it == end())
80  return nullptr;
81  else
82  return it->second;
83 }
84 
85 
92 void Map::Set(const String &key, SObject value)
93 {
94  data[key] = value;
95 }
96 
104 void Map::Remove(const String &key)
105 {
106  if (!data.erase(key))
107  throw ExceptionNotFound(_("Key not found"));
108 }
109 
117 void Map::Remove(const SObject &obj)
118 {
119  for (auto it = begin(); it != end(); ++it)
120  if (it->second == obj)
121  {
122  Remove(it->first);
123  return;
124  }
125  throw ExceptionNotFound(_("Object not found."));
126 }
127 
136 {
137  if (it == end())
138  throw ExceptionDomain(_("Invalid iterator."));
139  data.erase(it);
140 }
141 
152 void Map::Remove(iterator first, iterator end_)
153 {
154  // cannot begin with end()
155  if (first == end())
156  throw ExceptionDomain(_("First iterator is end()."));
157  // null range
158  if (first == end_)
159  throw ExceptionInvalidArgument(_("First and end iterators are equal."));
160  // if end is end()
161  if (end_ == end())
162  {
163  data.erase(first, end_);
164  }
165  // if end is not the end() of the map, check that it is really after first
166  for (auto tmp = first; tmp != end(); ++tmp)
167  {
168  if (tmp == end_)
169  {
170  data.erase(first, end_);
171  return;
172  }
173  }
174  throw ExceptionInvalidArgument(_("End iterator is before first."));
175 }
176 
177 /*****************************************************************************/
188 {
189  if (el.GetValue() != "Map")
190  {
191  throw ExceptionInvalidArgument(StringUTF8("void Map::Deserialize(xml::Element *el): ") +
192  _("Wrong XML element."));
193  }
194  Clear();
195  for (xml::Element te = el.BeginElement(); te != el.EndElement(); ++te)
196  {
197  try
198  {
199  SObject d = DataFactory::CreateData(te);
200  const StringUTF8 key = te.GetAttribute<StringUTF8>("key");
201  data[key] = d;
202  }
203  catch (std::exception &e)
204  {
205  // XXX throw?
206  CRNWarning(String(U"void Map::Deserialize(xml::Element &el): ") +
207  String(_("Cannot deserialize: ")) + te.GetValue() + String(_(" because ")) + e.what());
208  }
209  }
210 }
211 
212 /*****************************************************************************/
221 {
222  xml::Element el(parent.PushBackElement("Map"));
223  for (const auto & elem : *this)
224  {
225  xml::Element te = crn::Serialize(*elem.second, el);
226  te.SetAttribute("key", elem.first.CStr());
227  }
228 
229  return el;
230 }
231 
236 std::set<String> Map::GetKeys() const
237 {
238  std::set<String> keys;
239  for (const auto & elem : *this)
240  {
241  keys.insert(elem.first);
242  }
243  return keys;
244 }
245 
251 {
252  if (data.empty())
253  {
254  return U"";
255  }
256  return data.begin()->first;
257 }
258 
264 {
265  if (data.empty())
266  {
267  return U"";
268  }
269  return data.rbegin()->first;
270 }
271 
277 void Map::Swap(Map &other) noexcept
278 {
279  data.swap(other.data);
280 }
281 
282 void Map::Load(const Path &fname)
283 {
284  auto xdoc = xml::Document(fname); // may throw
285  auto root = xdoc.GetRoot();
286  if (!root)
287  throw ExceptionNotFound{StringUTF8("void Map::Load(const Path &): ") +
288  _("Cannot find root element.")};
289  auto el = root.GetFirstChildElement();
290  Deserialize(el); // may throw
291 }
292 
293 void Map::Save(const Path &fname) const
294 {
295  auto doc = xml::Document{};
296  auto root = doc.PushBackElement("ComplexObject");
297  Serialize(root);
298  doc.Save(fname);
299 }
300 
303  Cloner::Register<Map>();
305 
306 
xml::Element Serialize(const Object &obj, xml::Element &parent)
Writes an object to XML if possible.
Definition: CRNObject.cpp:110
String FirstKey() const
Returns the first (lowest) key.
Definition: CRNMap.cpp:250
void Clear() noexcept
Empties the map.
Definition: CRNMap.h:83
iterator Find(const String &key)
Returns an iterator to a specific key.
Definition: CRNMap.h:90
XML element.
Definition: CRNXml.h:135
#define _(String)
Definition: CRNi18n.h:51
XML document.
Definition: CRNXml.h:429
void Set(const String &key, SObject value)
Sets a value for a key with constraints check.
Definition: CRNMap.cpp:92
Element PushBackElement(const StringUTF8 &name)
Adds an element at the end of the children list.
Definition: CRNXml.cpp:1087
void Deserialize(xml::Element &el)
Reads from an XML node if applicable.
Definition: CRNMap.cpp:187
static UObject CreateData(xml::Element &el)
Creates and initializes a SObject from an XML element.
#define CRNWarning(x)
Definition: CRNIO.h:145
void Remove(const String &key)
Removes an element (safe)
Definition: CRNMap.cpp:104
void Load(const Path &fname)
Definition: CRNMap.cpp:282
Element BeginElement()
Gets the first child element.
Definition: CRNXml.h:174
#define CRN_END_CLASS_CONSTRUCTOR(classname)
Defines a class constructor.
Definition: CRNObject.h:198
void Swap(Map &other) noexcept
Swaps contents with another map.
Definition: CRNMap.cpp:277
A UTF32 character string class.
Definition: CRNString.h:61
std::map< String, SObject >::iterator iterator
iterator on the contents of the container
Definition: CRNMap.h:72
void Save(const Path &fname) const
Definition: CRNMap.cpp:293
A generic domain error.
Definition: CRNException.h:83
Map()
Default constructor.
String LastKey() const
Returns the last (greatest) key.
Definition: CRNMap.cpp:263
A convenience class for file paths.
Definition: CRNPath.h:39
iterator begin()
Returns an iterator to the first element.
Definition: CRNMap.h:86
xml::Element Serialize(xml::Element &parent) const
Dumps to an XML node if applicable.
Definition: CRNMap.cpp:220
#define CRN_DATA_FACTORY_REGISTER(elemname, classname)
Registers a class to the data factory.
virtual StringUTF8 GetValue() const
Gets the content of the node.
Definition: CRNXml.cpp:171
void SetAttribute(const StringUTF8 &name, const StringUTF8 &value)
Sets the value of an attribute.
Definition: CRNXml.cpp:595
SObject Get(const String &s)
Returns an object from index or nullptr if inexistent.
Definition: CRNMap.cpp:61
Data map class.
Definition: CRNMap.h:42
A character string class.
Definition: CRNStringUTF8.h:49
UObject Clone(const Object &obj)
Clones an object if possible.
Definition: CRNObject.cpp:35
iterator end()
Returns an iterator after the last element.
Definition: CRNMap.h:88
Element PushBackElement(const StringUTF8 &name)
Adds an element at the end of the children list.
Definition: CRNXml.cpp:355
Map & operator=(const Map &other)
Definition: CRNMap.cpp:47
Element EndElement()
Gets a null node.
Definition: CRNXml.h:176
virtual ~Map() override
Destructor.
Invalid argument error (e.g.: nullptr pointer)
Definition: CRNException.h:107
std::set< String > GetKeys() const
Returns all keys.
Definition: CRNMap.cpp:236
#define CRN_BEGIN_CLASS_CONSTRUCTOR(classname)
Defines a class constructor.
Definition: CRNObject.h:185
An item was not found in a container.
Definition: CRNException.h:95