SheafSystem  0.0.0.0
name_multimap.cc
Go to the documentation of this file.
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
20 
21 #include "SheafSystem/name_multimap.h"
22 
23 #include "SheafSystem/sheaf_dll_spec.h"
24 #include "SheafSystem/assert_contract.h"
25 #include "SheafSystem/deep_size.h"
26 
27 using namespace std;
28 
29 // =============================================================================
30 // NAME_MULTIMAP FACET
31 // =============================================================================
32 
33 // PUBLIC FUNCTIONS
34 
37 {
38  // Preconditions:
39 
40  // Body:
41 
42  // Nothing to do.
43 
44  // Postconditions:
45 
46  ensure(invariant());
47 
48  // Exit:
49 
50  return;
51 }
52 
55 {
56  // Preconditions:
57 
58  // Body:
59 
60  (*this) = xother;
61 
62  // Postconditions:
63 
64  ensure(invariant());
65  ensure(*this == xother);
66 
67  // Exit:
68 
69  return;
70 }
71 
73 name_multimap(const std::string xnames[], size_type xnames_ub)
74 {
75  // Preconditions:
76 
77  // Body:
78 
79  for(index_type i = 0; i < xnames_ub; ++i)
80  {
81  if(!xnames[i].empty())
82  {
83  _index_to_name_map[i].push_back(xnames[i]);
84  _name_to_index_map[xnames[i]] = i;
85  }
86  }
87 
88  // Postconditions:
89 
90  ensure(invariant());
91  ensure_for_all(i, 0, xnames_ub, !xnames[i].empty() ? name(index_type(i)) == xnames[i] : true);
92 
93  // Exit:
94 
95  return;
96 }
97 
100 {
101  // Preconditions:
102 
103  // Body:
104 
105  // Nothing to do.
106 
107  // Postconditions:
108 
109  // Exit:
110 
111  return;
112 }
113 
114 std::string
116 name(index_type xindex) const
117 {
118  // Preconditions:
119 
120  // Body:
121 
122  index_to_name_map_type::const_iterator map_result =
123  _index_to_name_map.find(xindex);
124 
125  if(map_result != _index_to_name_map.end())
126  {
127  // This index has a name.
128 
129  // Exit
130 
131  return map_result->second.front();
132  }
133  else
134  {
135  // This index has no name.
136 
137  string result; // empty string
138 
139  // Postcondition:
140 
141  ensure(result.empty() == !contains_index(xindex));
142 
143  // Exit
144 
145  return result;
146  }
147 
148 }
149 
150 std::string
152 name(index_type xindex, int xi) const
153 {
154  // Preconditions:
155 
156  // Body:
157 
158  string result;
159 
160  const name_list_type& lnames = all_names(xindex);
161  const_name_iterator litr = lnames.begin();
162  int i = 0;
163  while(litr != lnames.end())
164  {
165  if(i == xi)
166  {
167  result = *litr;
168  break;
169  }
170  ++litr;
171  ++i;
172  }
173 
174  // Postconditions:
175 
176  ensure((!result.empty()) == ((0 <= xi) && (xi < name_ct(xindex))) );
177 
178  // Exit:
179 
180  return result;
181 }
182 
185 all_names(index_type xindex) const
186 {
187  // Preconditions:
188 
189  // Body:
190 
191  static const name_list_type empty_list;
192 
193  const_iterator map_result = _index_to_name_map.find(xindex);
194 
195  const name_list_type& result =
196  (map_result != _index_to_name_map.end()) ? map_result->second : empty_list;
197 
198  // Postconditions:
199 
200  // Exit:
201 
202  return result;
203 }
204 
205 void
207 all_names(index_type xindex, block<std::string>& xresult) const
208 {
209  // Preconditions:
210 
211  // Body:
212 
213  xresult.reserve(4); // Arbitrary; will resize as needed.
214  xresult.set_ct(0);
215 
216  const name_list_type& lnames = all_names(xindex);
217 
218  for(const_name_iterator itr = lnames.begin(); itr != lnames.end(); ++itr)
219  {
220  xresult.push_back(*itr);
221  }
222 
223  // Postconditions:
224 
225  ensure(xresult.ct() == name_ct(xindex));
226 
227  // Exit:
228 
229  return;
230 }
231 
234 index(const std::string& xname) const
235 {
236  index_type result;
237 
238  // Preconditions:
239 
240  require(!xname.empty());
241 
242  // Body:
243 
244  // Lookup the name in the name-to-index map.
245 
246  typedef name_to_index_map_type::const_iterator itr_type;
247 
248  itr_type litr = _name_to_index_map.find(xname);
249 
250  if(litr != _name_to_index_map.end())
251  {
252  // Name is in the map; result is the value of the map.
253 
254  result = litr->second;
255  }
256  else
257  {
258  // Name not in the map; result is invalid.
259 
260  result = invalid_pod_index();
261  }
262 
263  // Postconditions:
264 
265  // Must be unexecutable or create infinite recursion.
266 
267  ensure(unexecutable(is_valid(result) == !contains_name(xname)));
268 
269  // Exit
270 
271  return result;
272 }
273 
274 void
276 put_entry(const entry_type& xentry, bool xunique)
277 {
278  // Preconditions:
279 
280  require(!xentry.second.empty());
281  require(!contains_name(xentry.second));
282 
283  // Body:
284 
285  if(xunique)
286  {
287  // Delete all other entries for this index.
288 
289  delete_index(xentry.first);
290  }
291 
292 
293  _index_to_name_map[xentry.first].push_back(xentry.second);
294  _name_to_index_map[xentry.second] = xentry.first;
295 
296  // Postconditions:
297 
298  ensure(contains_entry(xentry));
299 
300  // Exit
301 }
302 
303 void
305 put_entry(index_type xindex, const std::string& xname, bool xunique)
306 {
307  // Preconditions:
308 
309  require(!xname.empty());
310  require(!contains_name(xname));
311 
312  // Body:
313 
314  entry_type ltmp(xindex, xname);
315  put_entry(ltmp, xunique);
316 
317  // Postconditions:
318 
319  ensure(contains_entry(xindex, xname));
320 
321  // Exit:
322 
323  return;
324 }
325 
326 bool
328 contains_name(const std::string& xname) const
329 {
330  bool result;
331 
332  // Preconditions:
333 
334  require(!xname.empty());
335 
336  // Body:
337 
338  result = _name_to_index_map.find(xname) != _name_to_index_map.end();
339 
340  // Postconditions:
341 
342  // Exit
343 
344  return result;
345 }
346 
347 bool
350 {
351  // Preconditions:
352 
353  // Body:
354 
355  // Postconditions:
356 
357  // Exit:
358 
359  return _index_to_name_map.find(xindex) != _index_to_name_map.end();
360 }
361 
362 bool
364 contains_entry(index_type xindex, const std::string& xname) const
365 {
366  // Preconditions:
367 
368  require(!xname.empty());
369 
370  // Body:
371 
372  bool result;
373 
374  entry_type entry(xindex, xname);
375 
376  result = contains_entry(entry);
377 
378  // Postconditions:
379 
380  // Exit:
381 
382  return result;
383 }
384 
385 bool
387 contains_entry(const entry_type& xentry) const
388 {
389  // Preconditions:
390 
391  require(!xentry.second.empty());
392 
393  // Body:
394 
395  bool result;
396 
397  result = contains_name(xentry.second) && (index(xentry.second) == xentry.first);
398 
399  // Postconditions:
400 
401  // Exit:
402 
403  return result;
404 }
405 
406 void
409 {
410  // Preconditions:
411 
412  // Body:
413 
414  // Remove xindex from the name to index map.
415 
416  const name_list_type& lnames = all_names(xindex);
417 
418  for(const_name_iterator itr = lnames.begin(); itr != lnames.end(); ++itr)
419  {
420  _name_to_index_map.erase(*itr);
421  }
422 
423  // Remove xindex from the index to name map.
424 
425  _index_to_name_map.erase(xindex);
426 
427  // Postcondition
428 
429  ensure(!contains_index(xindex));
430 
431  // Exit
432 
433  return;
434 }
435 
436 void
438 delete_name(const std::string& xname)
439 {
440  // Preconditions:
441 
442  require(!xname.empty());
443 
444  // Find entry in name to index map.
445 
446  name_to_index_map_type::iterator itr = _name_to_index_map.find(xname);
447 
448  if(itr != _name_to_index_map.end())
449  {
450  // Found name to index entry;
451  // find and delete corresponding index to name entry.
452 
453  iterator lindex_entry = _index_to_name_map.find(itr->second);
454  name_list_type& lnames = lindex_entry->second;
455 
456  name_iterator lname_itr = lnames.begin();
457  while(lname_itr != lnames.end())
458  {
459  if((*lname_itr) == xname)
460  {
461  lnames.erase(lname_itr);
462  break;
463  }
464  ++lname_itr;
465  }
466 
467  if(lnames.empty())
468  {
469  // List of names for this index is now empty;
470  // delete the entry.
471 
472  _index_to_name_map.erase(lindex_entry);
473  }
474 
475  // Now erase the name to index entry.
476 
477  _name_to_index_map.erase(itr);
478  }
479 
480  // Postcondition
481 
482  ensure(!contains_name(xname));
483 
484  // Exit
485 
486  return;
487 }
488 
489 void
492 {
493  // cout << endl << "Entering name_multimap::clear." << endl;
494 
495  // Preconditions:
496 
497 
498  // Body:
499 
500  _name_to_index_map.clear();
501  _index_to_name_map.clear();
502 
503  // Postconditions:
504 
505  ensure(empty());
506 
507  // Exit:
508 
509  // cout << "Leaving name_multimap::clear." << endl;
510  return;
511 }
512 
513 bool
515 empty() const
516 {
517  // cout << endl << "Entering name_multimap::empty." << endl;
518 
519  // Preconditions:
520 
521 
522  // Body:
523 
524  bool result = (_name_to_index_map.empty() && _index_to_name_map.empty());
525 
526  // Postconditions:
527 
528 
529  // Exit:
530 
531  // cout << "Leaving name_multimap::empty." << endl;
532  return result;
533 }
534 
535 
536 
539 begin() const
540 {
541  return _index_to_name_map.begin();
542 }
543 
546 end() const
547 {
548  return _index_to_name_map.end();
549 }
550 
551 int
553 ct() const
554 {
555  return _index_to_name_map.size();
556 }
557 
558 void
560 print() const
561 {
562  print(cout, *this);
563 }
564 
565 void
567 print(std::ostream& xos, const name_multimap& xm) const
568 {
569  // Preconditions:
570 
571  // Body:
572 
574  while(itr != xm.end())
575  {
576  xos << "index: " << itr->first << "\tnames: " ;
577 
578  const name_multimap::name_list_type& lnames = itr->second;
579  name_multimap::const_name_iterator name_itr = lnames.begin();
580  while(name_itr != lnames.end())
581  {
582  xos << " \"" << *name_itr << "\"";
583  ++name_itr;
584  }
585  xos << endl;
586  ++itr;
587  }
588 
589  // Postconditions:
590 
591  // Exit:
592 
593  return;
594 }
595 
598 name_ct(const index_type& xindex) const
599 {
600  return all_names(xindex).size();
601 }
602 
603 // PROTECTED FUNCTIONS
604 
605 // PRIVATE FUNCTIONS
606 
607 
608 // ===========================================================
609 // ANY FACET
610 // ===========================================================
611 
612 // PUBLIC FUNCTIONS
613 
616 clone() const
617 {
618  name_multimap* result;
619 
620  // Preconditions:
621 
622  // Body:
623 
624  result = new name_multimap(*this);
625 
626  // Postconditions:
627 
628  ensure(result != 0);
629  ensure(is_same_type(result));
630 
631  // Exit:
632 
633  return result;
634 }
635 
636 bool
638 invariant() const
639 {
640  bool result = true;
641 
642  // Preconditions:
643 
644  // Body:
645 
646  // Must satisfy base class invariant
647 
648  result = result && any::invariant();
649 
650  if(invariant_check())
651  {
652  // Prevent recursive calls to invariant
653 
654  disable_invariant_check();
655 
656  invariance(_index_to_name_map.size() <= _name_to_index_map.size());
657 
658  // Finished, turn invariant checking back on.
659 
660  enable_invariant_check();
661  }
662 
663  // Postconditions:
664 
665  // Exit
666 
667  return result;
668 }
669 
670 bool
672 is_ancestor_of(const any* xother) const
673 {
674 
675  // Preconditions:
676 
677  require(xother != 0);
678 
679  // Body:
680 
681  // True if other conforms to this.
682 
683  bool result = dynamic_cast<const name_multimap*>(xother) != 0;
684 
685  // Postconditions:
686 
687  return result;
688 }
689 
690 bool
692 operator==(const name_multimap& xother)
693 {
694  // Preconditions:
695 
696  // Body:
697 
698  bool result =
699  (_name_to_index_map == xother._name_to_index_map) &&
700  (_index_to_name_map == xother._index_to_name_map);
701 
702  // Postconditions:
703 
704  // Exit
705 
706  return result;
707 }
708 
711 operator=(const name_multimap& xother)
712 {
713 
714  // Preconditions:
715 
716  // Body:
717 
718  _name_to_index_map = xother._name_to_index_map;
719  _index_to_name_map = xother._index_to_name_map;
720 
721  // Postconditions:
722 
723  ensure(invariant());
724  ensure(*this == xother);
725 
726  // Exit
727 
728  return *this;
729 }
730 
731 // PROTECTED FUNCTIONS
732 
733 // PRIVATE FUNCTIONS
734 
735 
736 // ===========================================================
737 // NON-MEMBER FUNCTIONS
738 // ===========================================================
739 
740 ostream&
741 sheaf::
742 operator<<(ostream& xos, const name_multimap& xm)
743 {
744  // Preconditions:
745 
746  // Body:
747 
748  xm.print(xos, xm);
749  return xos;
750 
751  // Postconditions:
752 
753  // Exit:
754 
755  return xos;
756 }
757 
758 size_t
759 sheaf::
760 deep_size(const name_multimap& xp, bool xinclude_shallow)
761 {
762  size_t result;
763 
764  // Preconditions:
765 
766  // Body:
767 
768  result = xinclude_shallow ? sizeof(xp) : 0;
769 
770  // Add the deep size of the data members.
771 
772  typedef name_multimap::index_type index_type;
773 
774  typedef key_deep_size_policy<map<string, index_type> > name_to_index_policy;
775  result += deep_size<string, index_type, name_to_index_policy>
776  (xp._name_to_index_map, false);
777 
778  typedef value_deep_size_policy<map<index_type, list<string> > > index_to_name_policy;
779  result += deep_size<index_type, list<string>, index_to_name_policy>
780  (xp._index_to_name_map, false);
781 
782  // Postconditions:
783 
784  ensure(result >= 0);
785 
786  // Exit
787 
788  return result;
789 }
790 
791 
bool contains_entry(const entry_type &xentry) const
True if this already contains an entry equal to xentry.
size_type name_ct(const index_type &xindex) const
The number of names associated with key xindex.
name_list_type::iterator name_iterator
The iterator type for names.
Definition: name_multimap.h:92
size_type ct() const
The number of items currently in use.
const_iterator begin() const
The initial value for iterators over this map.
pod_index_type index_type
The type of the index in the map.
Definition: name_multimap.h:77
index_type index(const std::string &xname) const
The index associated with name xname.
void delete_name(const std::string &xname)
Removes the entry for name xname.
name_list_type::const_iterator const_name_iterator
The const iterator type for names.
Definition: name_multimap.h:97
const name_list_type & all_names(index_type xindex) const
All names associated with index xindex.
void clear()
Removes all entries.
std::list< std::string > name_list_type
The type of name list for this map.
Definition: name_multimap.h:87
std::map< index_type, name_list_type >::iterator iterator
The iterator type for this map.
A partial multi-valued relation with total injective inverse between names and indices of type index_...
Definition: name_multimap.h:63
STL namespace.
void reserve(index_type xub)
Makes ub() at least xub; if new storage is allocated, it is uninitialized.
Call deep_size on the key.
Definition: deep_size.h:82
const_iterator end() const
The final value for iterators over this map.
Abstract base class with useful features for all objects.
Definition: any.h:39
void push_back(const_reference_type item)
Insert item at the end of the items in the auto_block.
std::pair< index_type, std::string > entry_type
The type of an entry in the map.
Definition: name_multimap.h:82
virtual name_multimap * clone() const
Virtual constructor; makes a new instance of the same type as this.
int ct() const
The number of index values in the map.
void set_ct(size_type xct)
Sets ct() == xct.
SHEAF_DLL_SPEC size_t deep_size(const dof_descriptor_array &xp, bool xinclude_shallow=true)
The deep size of the referenced object of type dof_descriptor_array.
unsigned long size_type
An unsigned integral type used to represent sizes and capacities.
Definition: sheaf.h:52
virtual ~name_multimap()
Destructor.
bool contains_name(const std::string &xname) const
True if this already contains an entry with name xname.
bool operator==(const name_multimap &xother)
Equality test; true if other has the same contents as this.
Call deep_size on the value.
Definition: deep_size.h:96
bool contains_index(index_type xindex) const
True if this already contains an entry with index xindex.
name_multimap()
Default constructor.
bool empty() const
True if and only if the map contains no entries.
virtual bool invariant() const
Class invariant.
virtual bool is_ancestor_of(const any *other) const
Conformance test; true if other conforms to this.
SHEAF_DLL_SPEC std::ostream & operator<<(std::ostream &os, const dof_descriptor_array &p)
Insert dof_descriptor_array& p into ostream& os.
void put_entry(const entry_type &xentry, bool xunique)
Sets (xindex, xname) as an entry in the map. If xunique, deletes all other entries for xindex...
void print() const
Prints the data members of this on cout. Intended for use debugging.
std::string name(index_type xindex) const
The primary (0-th) name associated with index xindex.
SHEAF_DLL_SPEC bool is_valid(pod_index_type xpod_index)
True if an only if xpod_index is valid.
Definition: pod_types.cc:37
std::map< index_type, name_list_type >::const_iterator const_iterator
The const iterator type for this map.
SHEAF_DLL_SPEC pod_index_type invalid_pod_index()
The invalid pod index value.
Definition: pod_types.cc:31
void delete_index(index_type xindex)
Removes all entires for index xindex.
name_multimap & operator=(const name_multimap &xother)
Assignment operator; make this a copy of xother.