TBTK
IndexedDataTree.h
Go to the documentation of this file.
1 /* Copyright 2017 Kristofer Bj√∂rnson
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
23 #ifndef COM_DAFER45_TBTK_INDEXED_DATA_TREE
24 #define COM_DAFER45_TBTK_INDEXED_DATA_TREE
25 
26 #include "TBTK/Index.h"
27 #include "TBTK/Serializable.h"
28 #include "TBTK/TBTKMacros.h"
29 
30 #include <complex>
31 #include <sstream>
32 
33 #include "TBTK/json.hpp"
34 
35 namespace TBTK{
36 
37 template<typename Data, bool = std::is_base_of<Serializable, Data>::value>
39 public:
42 
45  IndexedDataTree(const std::string &serialization, Mode mode);
46 
48  virtual ~IndexedDataTree();
49 
51  void add(const Data &data, const Index &index);
52 
54  bool get(Data &data, const Index &index) const;
55 
57  void clear();
58 
60  unsigned int getSizeInBytes() const;
61 
63  virtual std::string serialize(Mode mode) const;
64 private:
66  std::vector<IndexedDataTree> children;
67 
70  bool indexIncluded;
71 
75  bool indexSeparator;
76 
78  Data data;
79 
82  void add(const Data &data, const Index& index, unsigned int subindex);
83 
86  bool get(Data &data, const Index& index, unsigned int subindex) const;
87 };
88 
89 template<typename Data>
90 class IndexedDataTree<Data, true> : public Serializable{
91 public:
94 
97  IndexedDataTree(const std::string &serialization, Mode mode);
98 
100  virtual ~IndexedDataTree();
101 
103  void add(const Data &data, const Index &index);
104 
106  bool get(Data &data, const Index &index) const;
107 
109  void clear();
110 
112  unsigned int getSizeInBytes() const;
113 
115  virtual std::string serialize(Mode mode) const;
116 private:
118  std::vector<IndexedDataTree> children;
119 
122  bool indexIncluded;
123 
127  bool indexSeparator;
128 
130  Data data;
131 
134  void add(const Data &data, const Index& index, unsigned int subindex);
135 
138  bool get(Data &data, const Index& index, unsigned int subindex) const;
139 };
140 
141 template<typename Data>
142 class IndexedDataTree<Data, false> : public Serializable{
143 public:
145  IndexedDataTree();
146 
149  IndexedDataTree(const std::string &serialization, Mode mode);
150 
152  virtual ~IndexedDataTree();
153 
155  void add(const Data &data, const Index &index);
156 
158  bool get(Data &data, const Index &index) const;
159 
161  void clear();
162 
164  unsigned int getSizeInBytes() const;
165 
167  virtual std::string serialize(Mode mode) const;
168 private:
170  std::vector<IndexedDataTree> children;
171 
174  bool indexIncluded;
175 
179  bool indexSeparator;
180 
182  Data data;
183 
186  void add(const Data &data, const Index& index, unsigned int subindex);
187 
190  bool get(Data &data, const Index& index, unsigned int subindex) const;
191 };
192 
193 template<typename Data, bool isSerializable>
195  indexIncluded = false;
196  indexSeparator = false;
197 }
198 
199 template<typename Data>
201  indexIncluded = false;
202  indexSeparator = false;
203 }
204 
205 template<typename Data>
207  indexIncluded = false;
208  indexSeparator = false;
209 }
210 
211 template<>
213  const std::string &serialization,
214  Mode mode
215 ){
216  TBTKAssert(
217  validate(serialization, "IndexedDataTree", mode),
218  "IndexedDataTree<bool>::IndexedDataTree()",
219  "Unable to parse string as IndexedDataTree<bool> '"
220  << serialization << "'.",
221  ""
222  );
223 
224  switch(mode){
225  case Mode::JSON:
226  {
227  try{
228  nlohmann::json j = nlohmann::json::parse(
229  serialization
230  );
231  indexIncluded = j.at("indexIncluded").get<bool>();
232  indexSeparator = j.at("indexSeparator").get<bool>();
233  data = j.at("data").get<bool>();
234  try{
235  nlohmann::json children = j.at("children");
236  for(
237  nlohmann::json::iterator it = children.begin();
238  it != children.end();
239  ++it
240  ){
241  this->children.push_back(
243  it->dump(),
244  mode
245  )
246  );
247  }
248  }
249  catch(nlohmann::json::exception e){
250  //It is valid to not have children.
251  }
252  }
253  catch(nlohmann::json::exception e){
254  TBTKExit(
255  "IndexedDataTree<bool>::IndexedDataTree()",
256  "Unable to parse string as"
257  << " IndexedDataTree<bool> '"
258  << serialization << "'.",
259  ""
260  );
261  }
262 
263  break;
264  }
265  default:
266  TBTKExit(
267  "IndexedDataTree<bool>::IndexedDataTree()",
268  "Only Serializable::Mode::JSON is supported yet.",
269  ""
270  );
271  }
272 }
273 
274 template<>
276  const std::string &serialization,
277  Mode mode
278 ){
279  TBTKAssert(
280  validate(serialization, "IndexedDataTree", mode),
281  "IndexedDataTree<char>::IndexedDataTree()",
282  "Unable to parse string as IndexedDataTree<char> '"
283  << serialization << "'.",
284  ""
285  );
286 
287  switch(mode){
288  case Mode::JSON:
289  {
290  try{
291  nlohmann::json j = nlohmann::json::parse(
292  serialization
293  );
294  indexIncluded = j.at("indexIncluded").get<bool>();
295  data = j.at("data").get<char>();
296  try{
297  nlohmann::json children = j.at("children");
298  for(
299  nlohmann::json::iterator it = children.begin();
300  it != children.end();
301  ++it
302  ){
303  this->children.push_back(
305  it->dump(),
306  mode
307  )
308  );
309  }
310  }
311  catch(nlohmann::json::exception e){
312  //It is valid to not have children.
313  }
314  }
315  catch(nlohmann::json::exception e){
316  TBTKExit(
317  "IndexedDataTree<char>::IndexedDataTree()",
318  "Unable to parse string as"
319  << " IndexedDataTree<char> '"
320  << serialization << "'.",
321  ""
322  );
323  }
324 
325  break;
326  }
327  default:
328  TBTKExit(
329  "IndexedDataTree<char>::IndexedDataTree()",
330  "Only Serializable::Mode::JSON is supported yet.",
331  ""
332  );
333  }
334 }
335 
336 template<>
338  const std::string &serialization,
339  Mode mode
340 ){
341  TBTKAssert(
342  validate(serialization, "IndexedDataTree", mode),
343  "IndexedDataTree<int>::IndexedDataTree()",
344  "Unable to parse string as IndexedDataTree<int> '"
345  << serialization << "'.",
346  ""
347  );
348 
349  switch(mode){
350  case Mode::JSON:
351  {
352  try{
353  nlohmann::json j = nlohmann::json::parse(
354  serialization
355  );
356  indexIncluded = j.at("indexIncluded").get<bool>();
357  data = j.at("data").get<int>();
358  try{
359  nlohmann::json children = j.at("children");
360  for(
361  nlohmann::json::iterator it = children.begin();
362  it != children.end();
363  ++it
364  ){
365  this->children.push_back(
367  it->dump(),
368  mode
369  )
370  );
371  }
372  }
373  catch(nlohmann::json::exception e){
374  //It is valid to not have children.
375  }
376  }
377  catch(nlohmann::json::exception e){
378  TBTKExit(
379  "IndexedDataTree<int>::IndexedDataTree()",
380  "Unable to parse string as"
381  << " IndexedDataTree<int> '"
382  << serialization << "'.",
383  ""
384  );
385  }
386 
387  break;
388  }
389  default:
390  TBTKExit(
391  "IndexedDataTree<int>::IndexedDataTree()",
392  "Only Serializable::Mode::JSON is supported yet.",
393  ""
394  );
395  }
396 }
397 
398 template<>
400  const std::string &serialization,
401  Mode mode
402 ){
403  TBTKAssert(
404  validate(serialization, "IndexedDataTree", mode),
405  "IndexedDataTree<float>::IndexedDataTree()",
406  "Unable to parse string as IndexedDataTree<float> '"
407  << serialization << "'.",
408  ""
409  );
410 
411  switch(mode){
412  case Mode::JSON:
413  {
414  try{
415  nlohmann::json j = nlohmann::json::parse(
416  serialization
417  );
418  indexIncluded = j.at("indexIncluded").get<bool>();
419  data = j.at("data").get<float>();
420  try{
421  nlohmann::json children = j.at("children");
422  for(
423  nlohmann::json::iterator it = children.begin();
424  it != children.end();
425  ++it
426  ){
427  this->children.push_back(
429  it->dump(),
430  mode
431  )
432  );
433  }
434  }
435  catch(nlohmann::json::exception e){
436  //It is valid to not have children.
437  }
438  }
439  catch(nlohmann::json::exception e){
440  TBTKExit(
441  "IndexedDataTree<float>::IndexedDataTree()",
442  "Unable to parse string as"
443  << " IndexedDataTree<float> '"
444  << serialization << "'.",
445  ""
446  );
447  }
448 
449  break;
450  }
451  default:
452  TBTKExit(
453  "IndexedDataTree<float>::IndexedDataTree()",
454  "Only Serializable::Mode::JSON is supported yet.",
455  ""
456  );
457  }
458 }
459 
460 template<>
462  const std::string &serialization,
463  Mode mode
464 ){
465  TBTKAssert(
466  validate(serialization, "IndexedDataTree", mode),
467  "IndexedDataTree<double>::IndexedDataTree()",
468  "Unable to parse string as IndexedDataTree<double> '"
469  << serialization << "'.",
470  ""
471  );
472 
473  switch(mode){
474  case Mode::JSON:
475  {
476  try{
477  nlohmann::json j = nlohmann::json::parse(
478  serialization
479  );
480  indexIncluded = j.at("indexIncluded").get<bool>();
481  data = j.at("data").get<double>();
482  try{
483  nlohmann::json children = j.at("children");
484  for(
485  nlohmann::json::iterator it = children.begin();
486  it != children.end();
487  ++it
488  ){
489  this->children.push_back(
491  it->dump(),
492  mode
493  )
494  );
495  }
496  }
497  catch(nlohmann::json::exception e){
498  //It is valid to not have children.
499  }
500  }
501  catch(nlohmann::json::exception e){
502  TBTKExit(
503  "IndexedDataTree<double>::IndexedDataTree()",
504  "Unable to parse string as"
505  << " IndexedDataTree<double> '"
506  << serialization << "'.",
507  ""
508  );
509  }
510 
511  break;
512  }
513  default:
514  TBTKExit(
515  "IndexedDataTree<double>::IndexedDataTree()",
516  "Only Serializable::Mode::JSON is supported yet.",
517  ""
518  );
519  }
520 }
521 
522 template<>
524  const std::string &serialization,
525  Mode mode
526 ){
527  TBTKAssert(
528  validate(serialization, "IndexedDataTree", mode),
529  "IndexedDataTree<std::complex<double>>::IndexedDataTree()",
530  "Unable to parse string as IndexedDataTree<std::complex<double>> '"
531  << serialization << "'.",
532  ""
533  );
534 
535  switch(mode){
536  case Mode::JSON:
537  {
538  try{
539  nlohmann::json j = nlohmann::json::parse(
540  serialization
541  );
542  indexIncluded = j.at("indexIncluded").get<bool>();
543  std::string dataString = j.at("data").get<std::string>();
544  std::stringstream ss(dataString);
545  ss >> data;
546 // data = j.at("data").get<std::complex<double>>();
547  try{
548  nlohmann::json children = j.at("children");
549  for(
550  nlohmann::json::iterator it = children.begin();
551  it != children.end();
552  ++it
553  ){
554  this->children.push_back(
555  IndexedDataTree<std::complex<double>>(
556  it->dump(),
557  mode
558  )
559  );
560  }
561  }
562  catch(nlohmann::json::exception e){
563  //It is valid to not have children.
564  }
565  }
566  catch(nlohmann::json::exception e){
567  TBTKExit(
568  "IndexedDataTree<std::complex<double>>::IndexedDataTree()",
569  "Unable to parse string as"
570  << " IndexedDataTree<std::complex<double>> '"
571  << serialization << "'.",
572  ""
573  );
574  }
575 
576  break;
577  }
578  default:
579  TBTKExit(
580  "IndexedDataTree<std::complex<double>>::IndexedDataTree()",
581  "Only Serializable::Mode::JSON is supported yet.",
582  ""
583  );
584  }
585 }
586 
587 template<typename Data>
589  const std::string &serialization,
590  Mode mode
591 ){
592  TBTKAssert(
593  validate(serialization, "IndexedDataTree", mode),
594  "IndexedDataTree<Data>::IndexedDataTree()",
595  "Unable to parse string as IndexedDataTree<Data> '"
596  << serialization << "'.",
597  ""
598  );
599 
600  switch(mode){
601  case Mode::JSON:
602  {
603  try{
604  nlohmann::json j = nlohmann::json::parse(
605  serialization
606  );
607  indexIncluded = j.at("indexIncluded").get<bool>();
608  std::string dataString = j.at("data").get<std::string>();
609  data = Data(dataString, mode);
610 // data = j.at("data").get<Data>();
611  try{
612  nlohmann::json children = j.at("children");
613  for(
614  nlohmann::json::iterator it = children.begin();
615  it != children.end();
616  ++it
617  ){
618  this->children.push_back(
620  it->dump(),
621  mode
622  )
623  );
624  }
625  }
626  catch(nlohmann::json::exception e){
627  //It is valid to not have children.
628  }
629  }
630  catch(nlohmann::json::exception e){
631  TBTKExit(
632  "IndexedDataTree<Data>::IndexedDataTree()",
633  "Unable to parse string as"
634  << " IndexedDataTree<Data> '"
635  << serialization << "'.",
636  ""
637  );
638  }
639 
640  break;
641  }
642  default:
643  TBTKExit(
644  "IndexedDataTree<Data>::IndexedDataTree()",
645  "Only Serializable::Mode::JSON is supported yet.",
646  ""
647  );
648  }
649 }
650 
651 template<typename Data>
653  const std::string &serialization,
654  Mode mode
655 ){
656  TBTKNotYetImplemented("IndexedDataTree<Data, false>");
657 /* TBTKAssert(
658  validate(serialization, "IndexedDataTree", mode),
659  "IndexedDataTree<Data>::IndexedDataTree()",
660  "Unable to parse string as IndexedDataTree<Data> '"
661  << serialization << "'.",
662  ""
663  );
664 
665  switch(mode){
666  case Mode::JSON:
667  {
668  try{
669  nlohmann::json j = nlohmann::json::parse(
670  serialization
671  );
672  indexIncluded = j.at("indexIncluded").get<bool>();
673  std::string dataString = j.at("data").get<std::string>();
674  data = Data(dataString, mode);
675 // data = j.at("data").get<Data>();
676  try{
677  nlohmann::json children = j.at("children");
678  for(
679  nlohmann::json::iterator it = children.begin();
680  it != children.end();
681  ++it
682  ){
683  this->children.push_back(
684  IndexedDataTree<Data>(
685  it->dump(),
686  mode
687  )
688  );
689  }
690  }
691  catch(nlohmann::json::exception e){
692  //It is valid to not have children.
693  }
694  }
695  catch(nlohmann::json::exception e){
696  TBTKExit(
697  "IndexedDataTree<Data>::IndexedDataTree()",
698  "Unable to parse string as"
699  << " IndexedDataTree<Data> '"
700  << serialization << "'.",
701  ""
702  );
703  }
704 
705  break;
706  }
707  default:
708  TBTKExit(
709  "IndexedDataTree<Data>::IndexedDataTree()",
710  "Only Serializable::Mode::JSON is supported yet.",
711  ""
712  );
713  }*/
714 }
715 
716 template<typename Data, bool isSerializable>
718 }
719 
720 template<typename Data>
722 }
723 
724 template<typename Data>
726 }
727 
728 template<typename Data, bool isSerializable>
730  const Data &data,
731  const Index &index
732 ){
733  add(data, index, 0);
734 }
735 
736 template<typename Data>
738  const Data &data,
739  const Index &index
740 ){
741  add(data, index, 0);
742 }
743 
744 template<typename Data>
746  const Data &data,
747  const Index &index
748 ){
749  add(data, index, 0);
750 }
751 
752 template<typename Data, bool isSerializable>
754  const Data &data,
755  const Index &index,
756  unsigned int subindex
757 ){
758  if(subindex < index.getSize()){
759  //If the current subindex is not the last, the Index is
760  //propagated to the next node level.
761 
762  //Get current subindex
763  int currentIndex = index.at(subindex);
764 
765  if(currentIndex == IDX_SEPARATOR){
766  if(children.size() == 0){
767  indexSeparator = true;
768  }
769  else{
770  TBTKAssert(
771  indexSeparator,
772  "IndexedDataTree:add()",
773  "Invalid index '" << index.toString()
774  << "'. Another Index has already been"
775  << " added to the tree that has a"
776  << " conflicting index at the index"
777  << " separator at subindex '"
778  << subindex << "'.",
779  "Note that a separation point between"
780  << " two indices counts as a subindex."
781  );
782  }
783 
784  indexSeparator = false;
785  add(data, index, subindex+1);
786  indexSeparator = true;
787  return;
788  }
789  else{
790  TBTKAssert(
791  !indexSeparator,
792  "IndexedDataTree:add()",
793  "Invalid index '" << index.toString() << "'."
794  << " Another Index has already been added to"
795  << " the tree that has a conflicting index"
796  << " separator at subindex '"
797  << subindex << "'.",
798  "Note that a separation point between two"
799  << " indices counts as a subindex."
800  );
801  }
802 
803  TBTKAssert(
804  currentIndex >= 0,
805  "IndexedDataTree::add()",
806  "Invalid Index. Negative indices not allowed, but the"
807  << "index " << index.toString() << " have a negative"
808  << " index" << " in position " << subindex << ".",
809  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
810  << " separated by IDX_SEPARATOR with the value '"
811  << IDX_SEPARATOR << "' and are" << " represented as {1"
812  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
813  << " the only allowed instance of negative numbers."
814  );
815 
816  //If the subindex is bigger than the current number of child
817  //nodes, create empty nodes.
818  if(currentIndex >= children.size())
819  for(int n = children.size(); n <= currentIndex; n++)
820  children.push_back(IndexedDataTree());
821  //Error detection:
822  //If the current node has the indexIncluded flag set, another
823  //Index with fewer subindices than the current Index have
824  //previously been added to this node. This is an error because
825  //different number of subindices is only allowed if the Indices
826  //differ in one of their common indices.
827  TBTKAssert(
828  !indexIncluded,
829  "IndexedDataTree::add()",
830  "Incompatible indices. The Index " << index.toString()
831  << " cannot be added because an Index of length "
832  << subindex + 1 << " which exactly agrees with the "
833  << subindex + 1 << " first indices of the current"
834  << " Index has already been added.",
835  ""
836  );
837 
838  children.at(currentIndex).add(data, index, subindex+1);
839  }
840  else{
841  //If the current subindex is the last, the index is marked as
842  //included.
843 
844  //Error detection:
845  //If children is non-zero, another Data with more subindices
846  //have already been added to this node. This is an error
847  //because different number of subindices is only allowed if the
848  // indices differ in one of their common indices.
849  TBTKAssert(
850  children.size() == 0,
851  "IndexedDataTree::add()",
852  "Incompatible indices. The Index " << index.toString()
853  << " cannot be added because a longer Index which"
854  << " exactly agrees with the current Index in the"
855  << " common indices has already been added.",
856  ""
857  );
858 
859  indexIncluded = true;
860  this->data = data;
861  }
862 }
863 
864 template<typename Data>
866  const Data &data,
867  const Index &index,
868  unsigned int subindex
869 ){
870  if(subindex < index.getSize()){
871  //If the current subindex is not the last, the Index is
872  //propagated to the next node level.
873 
874  //Get current subindex
875  int currentIndex = index.at(subindex);
876 
877  if(currentIndex == IDX_SEPARATOR){
878  if(children.size() == 0){
879  indexSeparator = true;
880  }
881  else{
882  TBTKAssert(
883  indexSeparator,
884  "IndexedDataTree:add()",
885  "Invalid index '" << index.toString()
886  << "'. Another Index has already been"
887  << " added to the tree that has a"
888  << " conflicting index at the index"
889  << " separator at subindex '"
890  << subindex << "'.",
891  "Note that a separation point between"
892  << " two indices counts as a subindex."
893  );
894  }
895 
896  indexSeparator = false;
897  add(data, index, subindex+1);
898  indexSeparator = true;
899  return;
900  }
901  else{
902  TBTKAssert(
903  !indexSeparator,
904  "IndexedDataTree:add()",
905  "Invalid index '" << index.toString() << "'."
906  << " Another Index has already been added to"
907  << " the tree that has a conflicting index"
908  << " separator at subindex '"
909  << subindex << "'.",
910  "Note that a separation point between two"
911  << " indices counts as a subindex."
912  );
913  }
914 
915  TBTKAssert(
916  currentIndex >= 0,
917  "IndexedDataTree::add()",
918  "Invalid Index. Negative indices not allowed, but the"
919  << "index " << index.toString() << " have a negative"
920  << " index" << " in position " << subindex << ".",
921  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
922  << " separated by IDX_SEPARATOR with the value '"
923  << IDX_SEPARATOR << "' and are" << " represented as {1"
924  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
925  << " the only allowed instance of negative numbers."
926  );
927 
928  //If the subindex is bigger than the current number of child
929  //nodes, create empty nodes.
930  if((unsigned int)currentIndex >= children.size())
931  for(int n = children.size(); n <= currentIndex; n++)
932  children.push_back(IndexedDataTree());
933  //Error detection:
934  //If the current node has the indexIncluded flag set, another
935  //Index with fewer subindices than the current Index have
936  //previously been added to this node. This is an error because
937  //different number of subindices is only allowed if the Indices
938  //differ in one of their common indices.
939  TBTKAssert(
940  !indexIncluded,
941  "IndexedDataTree::add()",
942  "Incompatible indices. The Index " << index.toString()
943  << " cannot be added because an Index of length "
944  << subindex + 1 << " which exactly agrees with the "
945  << subindex + 1 << " first indices of the current"
946  << " Index has already been added.",
947  ""
948  );
949 
950  children.at(currentIndex).add(data, index, subindex+1);
951  }
952  else{
953  //If the current subindex is the last, the index is marked as
954  //included.
955 
956  //Error detection:
957  //If children is non-zero, another Data with more subindices
958  //have already been added to this node. This is an error
959  //because different number of subindices is only allowed if the
960  // indices differ in one of their common indices.
961  TBTKAssert(
962  children.size() == 0,
963  "IndexedDataTree::add()",
964  "Incompatible indices. The Index " << index.toString()
965  << " cannot be added because a longer Index which"
966  << " exactly agrees with the current Index in the"
967  << " common indices has already been added.",
968  ""
969  );
970 
971  indexIncluded = true;
972  this->data = data;
973  }
974 }
975 
976 template<typename Data>
978  const Data &data,
979  const Index &index,
980  unsigned int subindex
981 ){
982  if(subindex < index.getSize()){
983  //If the current subindex is not the last, the Index is
984  //propagated to the next node level.
985 
986  //Get current subindex
987  int currentIndex = index.at(subindex);
988 
989  if(currentIndex == IDX_SEPARATOR){
990  if(children.size() == 0){
991  indexSeparator = true;
992  }
993  else{
994  TBTKAssert(
995  indexSeparator,
996  "IndexedDataTree:add()",
997  "Invalid index '" << index.toString()
998  << "'. Another Index has already been"
999  << " added to the tree that has a"
1000  << " conflicting index at the index"
1001  << " separator at subindex '"
1002  << subindex << "'.",
1003  "Note that a separation point between"
1004  << " two indices counts as a subindex."
1005  );
1006  }
1007 
1008  indexSeparator = false;
1009  add(data, index, subindex+1);
1010  indexSeparator = true;
1011  return;
1012  }
1013  else{
1014  TBTKAssert(
1015  !indexSeparator,
1016  "IndexedDataTree:add()",
1017  "Invalid index '" << index.toString() << "'."
1018  << " Another Index has already been added to"
1019  << " the tree that has a conflicting index"
1020  << " separator at subindex '"
1021  << subindex << "'.",
1022  "Note that a separation point between two"
1023  << " indices counts as a subindex."
1024  );
1025  }
1026 
1027  TBTKAssert(
1028  currentIndex >= 0,
1029  "IndexedDataTree::add()",
1030  "Invalid Index. Negative indices not allowed, but the"
1031  << "index " << index.toString() << " have a negative"
1032  << " index" << " in position " << subindex << ".",
1033  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
1034  << " separated by IDX_SEPARATOR with the value '"
1035  << IDX_SEPARATOR << "' and are" << " represented as {1"
1036  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
1037  << " the only allowed instance of negative numbers."
1038  );
1039 
1040  //If the subindex is bigger than the current number of child
1041  //nodes, create empty nodes.
1042  if(currentIndex >= children.size())
1043  for(int n = children.size(); n <= currentIndex; n++)
1044  children.push_back(IndexedDataTree());
1045  //Error detection:
1046  //If the current node has the indexIncluded flag set, another
1047  //Index with fewer subindices than the current Index have
1048  //previously been added to this node. This is an error because
1049  //different number of subindices is only allowed if the Indices
1050  //differ in one of their common indices.
1051  TBTKAssert(
1052  !indexIncluded,
1053  "IndexedDataTree::add()",
1054  "Incompatible indices. The Index " << index.toString()
1055  << " cannot be added because an Index of length "
1056  << subindex + 1 << " which exactly agrees with the "
1057  << subindex + 1 << " first indices of the current"
1058  << " Index has already been added.",
1059  ""
1060  );
1061 
1062  children.at(currentIndex).add(data, index, subindex+1);
1063  }
1064  else{
1065  //If the current subindex is the last, the index is marked as
1066  //included.
1067 
1068  //Error detection:
1069  //If children is non-zero, another Data with more subindices
1070  //have already been added to this node. This is an error
1071  //because different number of subindices is only allowed if the
1072  // indices differ in one of their common indices.
1073  TBTKAssert(
1074  children.size() == 0,
1075  "IndexedDataTree::add()",
1076  "Incompatible indices. The Index " << index.toString()
1077  << " cannot be added because a longer Index which"
1078  << " exactly agrees with the current Index in the"
1079  << " common indices has already been added.",
1080  ""
1081  );
1082 
1083  indexIncluded = true;
1084  this->data = data;
1085  }
1086 }
1087 
1088 template<typename Data, bool isSerializable>
1089 bool IndexedDataTree<Data, isSerializable>::get(Data &data, const Index &index) const{
1090  return get(data, index, 0);
1091 }
1092 
1093 template<typename Data>
1094 bool IndexedDataTree<Data, true>::get(Data &data, const Index &index) const{
1095  return get(data, index, 0);
1096 }
1097 
1098 template<typename Data>
1099 bool IndexedDataTree<Data, false>::get(Data &data, const Index &index) const{
1100  return get(data, index, 0);
1101 }
1102 
1103 template<typename Data, bool isSerializable>
1105  Data &data,
1106  const Index &index,
1107  unsigned int subindex
1108 ) const{
1109  if(subindex < index.getSize()){
1110  //If the current subindex is not the last, continue to the next
1111  //node level.
1112 
1113  //Get current subindex.
1114  int currentIndex = index.at(subindex);
1115 
1116  TBTKAssert(
1117  currentIndex >= 0,
1118  "IndexedDataTree::add()",
1119  "Invalid Index. Negative indices not allowed, but the"
1120  << " index " << index.toString() << " have a negative"
1121  << " index in position " << subindex << ".",
1122  ""
1123  );
1124 
1125  //Return false because the Index is not included.
1126  if(currentIndex >= children.size())
1127  return false;
1128 
1129  return children.at(currentIndex).get(data, index, subindex+1);
1130  }
1131  else{
1132  //If the current subindex is the last, try to extract the data.
1133  //Return true if successful but false if the data does not
1134  //exist.
1135  if(indexIncluded){
1136  data = this->data;
1137 
1138  return true;
1139  }
1140  else{
1141  return false;
1142  }
1143  }
1144 }
1145 
1146 template<typename Data>
1148  Data &data,
1149  const Index &index,
1150  unsigned int subindex
1151 ) const{
1152  if(subindex < index.getSize()){
1153  //If the current subindex is not the last, continue to the next
1154  //node level.
1155 
1156  //Get current subindex.
1157  int currentIndex = index.at(subindex);
1158 
1159  if(currentIndex == IDX_SEPARATOR){
1160  if(indexSeparator){
1161  return get(data, index, subindex+1);
1162  }
1163  else{
1164  TBTKExit(
1165  "IndexedDataTree::get()",
1166  "Invalid Index. Found IDX_SEPARATOR at"
1167  << " subindex '" << subindex << "',"
1168  << " but the node is not an index"
1169  << " separator.",
1170  ""
1171  );
1172  }
1173  }
1174 
1175  TBTKAssert(
1176  currentIndex >= 0,
1177  "IndexedDataTree::get()",
1178  "Invalid Index. Negative indices not allowed, but the"
1179  << "index " << index.toString() << " have a negative"
1180  << " index" << " in position " << subindex << ".",
1181  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
1182  << " separated by IDX_SEPARATOR with the value '"
1183  << IDX_SEPARATOR << "' and are" << " represented as {1"
1184  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
1185  << " the only allowed instance of negative numbers."
1186  );
1187 
1188  //Return false because the Index is not included.
1189  if((unsigned int)currentIndex >= children.size())
1190  return false;
1191 
1192  return children.at(currentIndex).get(data, index, subindex+1);
1193  }
1194  else{
1195  //If the current subindex is the last, try to extract the data.
1196  //Return true if successful but false if the data does not
1197  //exist.
1198  if(indexIncluded){
1199  data = this->data;
1200 
1201  return true;
1202  }
1203  else{
1204  return false;
1205  }
1206  }
1207 }
1208 
1209 template<typename Data>
1211  Data &data,
1212  const Index &index,
1213  unsigned int subindex
1214 ) const{
1215  if(subindex < index.getSize()){
1216  //If the current subindex is not the last, continue to the next
1217  //node level.
1218 
1219  //Get current subindex.
1220  int currentIndex = index.at(subindex);
1221 
1222  if(currentIndex == IDX_SEPARATOR){
1223  if(indexSeparator){
1224  return get(data, index, subindex+1);
1225  }
1226  else{
1227  TBTKExit(
1228  "IndexedDataTree::get()",
1229  "Invalid Index. Found IDX_SEPARATOR at"
1230  << " subindex '" << subindex << "',"
1231  << " but the node is not an index"
1232  << " separator.",
1233  ""
1234  );
1235  }
1236  }
1237 
1238  TBTKAssert(
1239  currentIndex >= 0,
1240  "IndexedDataTree::get()",
1241  "Invalid Index. Negative indices not allowed, but the"
1242  << "index " << index.toString() << " have a negative"
1243  << " index" << " in position " << subindex << ".",
1244  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
1245  << " separated by IDX_SEPARATOR with the value '"
1246  << IDX_SEPARATOR << "' and are" << " represented as {1"
1247  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
1248  << " the only allowed instance of negative numbers."
1249  );
1250 
1251  //Return false because the Index is not included.
1252  if(currentIndex >= children.size())
1253  return false;
1254 
1255  return children.at(currentIndex).get(data, index, subindex+1);
1256  }
1257  else{
1258  //If the current subindex is the last, try to extract the data.
1259  //Return true if successful but false if the data does not
1260  //exist.
1261  if(indexIncluded){
1262  data = this->data;
1263 
1264  return true;
1265  }
1266  else{
1267  return false;
1268  }
1269  }
1270 }
1271 
1272 template<typename Data, bool isSerializable>
1274  indexIncluded = false;
1275  children.clear();
1276 }
1277 
1278 template<typename Data>
1280  indexIncluded = false;
1281  children.clear();
1282 }
1283 
1284 template<typename Data>
1286  indexIncluded = false;
1287  children.clear();
1288 }
1289 
1290 template<typename Data, bool isSerializable>
1292  unsigned int size = sizeof(IndexedDataTree<Data>);
1293  for(unsigned int n = 0; n < children.size(); n++)
1294  size += children.at(n).getSizeInBytes();
1295 
1296  return size;
1297 }
1298 
1299 template<typename Data>
1301  unsigned int size = sizeof(IndexedDataTree<Data>);
1302  for(unsigned int n = 0; n < children.size(); n++)
1303  size += children.at(n).getSizeInBytes();
1304 
1305  return size;
1306 }
1307 
1308 template<typename Data>
1310  unsigned int size = sizeof(IndexedDataTree<Data>);
1311  for(unsigned int n = 0; n < children.size(); n++)
1312  size += children.at(n).getSizeInBytes();
1313 
1314  return size;
1315 }
1316 
1317 template<>
1318 inline std::string IndexedDataTree<bool, false>::serialize(Mode mode) const{
1319  switch(mode){
1320  case Mode::JSON:
1321  {
1322  nlohmann::json j;
1323  j["id"] = "IndexedDataTree";
1324  j["indexIncluded"] = indexIncluded;
1325  j["indexSeparator"] = indexSeparator;
1326  j["data"] = data;
1327  for(unsigned int n = 0; n < children.size(); n++){
1328  j["children"].push_back(
1329  nlohmann::json::parse(
1330  children.at(n).serialize(mode)
1331  )
1332  );
1333  }
1334 
1335  return j.dump();
1336  }
1337  default:
1338  TBTKExit(
1339  "IndexedDataTree<Data>::serialize()",
1340  "Only Serializable::Mode::JSON is supported yet.",
1341  ""
1342  );
1343  }
1344 }
1345 
1346 template<>
1347 inline std::string IndexedDataTree<char, false>::serialize(Mode mode) const{
1348  switch(mode){
1349  case Mode::JSON:
1350  {
1351  nlohmann::json j;
1352  j["id"] = "IndexedDataTree";
1353  j["indexIncluded"] = indexIncluded;
1354  j["indexSeparator"] = indexSeparator;
1355  j["data"] = data;
1356  for(unsigned int n = 0; n < children.size(); n++){
1357  j["children"].push_back(
1358  nlohmann::json::parse(
1359  children.at(n).serialize(mode)
1360  )
1361  );
1362  }
1363 
1364  return j.dump();
1365  }
1366  default:
1367  TBTKExit(
1368  "IndexedDataTree<Data>::serialize()",
1369  "Only Serializable::Mode::JSON is supported yet.",
1370  ""
1371  );
1372  }
1373 }
1374 
1375 template<>
1376 inline std::string IndexedDataTree<int, false>::serialize(Mode mode) const{
1377  switch(mode){
1378  case Mode::JSON:
1379  {
1380  nlohmann::json j;
1381  j["id"] = "IndexedDataTree";
1382  j["indexIncluded"] = indexIncluded;
1383  j["indexSeparator"] = indexSeparator;
1384  j["data"] = data;
1385  for(unsigned int n = 0; n < children.size(); n++){
1386  j["children"].push_back(
1387  nlohmann::json::parse(
1388  children.at(n).serialize(mode)
1389  )
1390  );
1391  }
1392 
1393  return j.dump();
1394  }
1395  default:
1396  TBTKExit(
1397  "IndexedDataTree<Data>::serialize()",
1398  "Only Serializable::Mode::JSON is supported yet.",
1399  ""
1400  );
1401  }
1402 }
1403 
1404 template<>
1405 inline std::string IndexedDataTree<float, false>::serialize(Mode mode) const{
1406  switch(mode){
1407  case Mode::JSON:
1408  {
1409  nlohmann::json j;
1410  j["id"] = "IndexedDataTree";
1411  j["indexIncluded"] = indexIncluded;
1412  j["indexSeparator"] = indexSeparator;
1413  j["data"] = data;
1414  for(unsigned int n = 0; n < children.size(); n++){
1415  j["children"].push_back(
1416  nlohmann::json::parse(
1417  children.at(n).serialize(mode)
1418  )
1419  );
1420  }
1421 
1422  return j.dump();
1423  }
1424  default:
1425  TBTKExit(
1426  "IndexedDataTree<Data>::serialize()",
1427  "Only Serializable::Mode::JSON is supported yet.",
1428  ""
1429  );
1430  }
1431 }
1432 
1433 template<>
1434 inline std::string IndexedDataTree<double, false>::serialize(Mode mode) const{
1435  switch(mode){
1436  case Mode::JSON:
1437  {
1438  nlohmann::json j;
1439  j["id"] = "IndexedDataTree";
1440  j["indexIncluded"] = indexIncluded;
1441  j["indexSeparator"] = indexSeparator;
1442  j["data"] = data;
1443  for(unsigned int n = 0; n < children.size(); n++){
1444  j["children"].push_back(
1445  nlohmann::json::parse(
1446  children.at(n).serialize(mode)
1447  )
1448  );
1449  }
1450 
1451  return j.dump();
1452  }
1453  default:
1454  TBTKExit(
1455  "IndexedDataTree<Data>::serialize()",
1456  "Only Serializable::Mode::JSON is supported yet.",
1457  ""
1458  );
1459  }
1460 }
1461 
1462 template<>
1463 inline std::string IndexedDataTree<std::complex<double>, false>::serialize(Mode mode) const{
1464  switch(mode){
1465  case Mode::JSON:
1466  {
1467  nlohmann::json j;
1468  j["id"] = "IndexedDataTree";
1469  j["indexIncluded"] = indexIncluded;
1470  j["indexSeparator"] = indexSeparator;
1471  std::stringstream ss;
1472  ss << "(" << real(data) << "," << imag(data) << ")";
1473  j["data"] = ss.str();
1474  for(unsigned int n = 0; n < children.size(); n++){
1475  j["children"].push_back(
1476  nlohmann::json::parse(
1477  children.at(n).serialize(mode)
1478  )
1479  );
1480  }
1481 
1482  return j.dump();
1483  }
1484  default:
1485  TBTKExit(
1486  "IndexedDataTree<Data>::serialize()",
1487  "Only Serializable::Mode::JSON is supported yet.",
1488  ""
1489  );
1490  }
1491 }
1492 
1493 template<typename Data>
1495  switch(mode){
1496  case Mode::JSON:
1497  {
1498  nlohmann::json j;
1499  j["id"] = "IndexedDataTree";
1500  j["indexIncluded"] = indexIncluded;
1501  j["indexSeparator"] = indexSeparator;
1502  j["data"] = data.serialize(mode);
1503  for(unsigned int n = 0; n < children.size(); n++){
1504  j["children"].push_back(
1505  nlohmann::json::parse(
1506  children.at(n).serialize(mode)
1507  )
1508  );
1509  }
1510 
1511  return j.dump();
1512  }
1513  default:
1514  TBTKExit(
1515  "IndexedDataTree<Data>::serialize()",
1516  "Only Serializable::Mode::JSON is supported yet.",
1517  ""
1518  );
1519  }
1520 }
1521 
1522 template<typename Data>
1524  TBTKNotYetImplemented("IndexedDataTree<Data, false>");
1525 /* switch(mode){
1526  case Mode::JSON:
1527  {
1528  nlohmann::json j;
1529  j["id"] = "IndexedDataTree";
1530  j["indexIncluded"] = indexIncluded;
1531  j["indexSeparator"] = indexSeparator;
1532  j["data"] = data.serialize(mode);
1533  for(unsigned int n = 0; n < children.size(); n++){
1534  j["children"].push_back(
1535  nlohmann::json::parse(
1536  children.at(n).serialize(mode)
1537  )
1538  );
1539  }
1540 
1541  return j.dump();
1542  }
1543  default:
1544  TBTKExit(
1545  "IndexedDataTree<Data>::serialize()",
1546  "Only Serializable::Mode::JSON is supported yet.",
1547  ""
1548  );
1549  }*/
1550 }
1551 
1552 }; //End of namesapce TBTK
1553 
1554 #endif
unsigned int getSizeInBytes() const
Definition: IndexedDataTree.h:1291
virtual ~IndexedDataTree()
Definition: IndexedDataTree.h:717
Flexible physical index.
Precompiler macros.
Definition: Serializable.h:40
Definition: IndexedDataTree.h:38
IndexedDataTree()
Definition: IndexedDataTree.h:194
Flexible physical index.
Definition: Index.h:70
Definition: ModelFactory.h:35
unsigned int getSize() const
Definition: Index.h:342
void add(const Data &data, const Index &index)
Definition: IndexedDataTree.h:729
Mode
Definition: Serializable.h:44
bool get(Data &data, const Index &index) const
Definition: IndexedDataTree.h:1089
static bool validate(const std::string &serialization, const std::string &id, Mode mode)
void clear()
Definition: IndexedDataTree.h:1273
Abstract base class for serializable objects.
int & at(unsigned int n)
Definition: Index.h:334
std::string toString() const
Definition: Index.h:265
virtual std::string serialize(Mode mode) const