AAO DRAMA/DRAMA2 C++ Interface
DRAMA C++11 and later interface
sds.hh
Go to the documentation of this file.
1#ifndef _DRAMA2_SDS_INC
2#define _DRAMA2_SDS_INC
3
15/*
16 * History:
17 07-Jan-2014 - TJF - Original version
18 14-Sep-2016 - TJF - Start of history after development.
19 14-Sep-2016 - TJF - Add Exists() by index.
20 09-Jan-2023 - TJF - std::iterator is depreciated from C++17.
21
22 * The above ID is for Doxygen, this one has the format ACMM is looking for.
23 * "@(#) $Id$"
24 */
25#include "sds.h"
26#include "arg.h"
27#include <string>
28#include <stdio.h>
29#include <vector>
30#include <memory>
31#include <assert.h>
32
33/*
34 * A bit of a flaw in our include file layout means we need to declare this
35 * here. Its real location is drama.hh, but we don't want to include that
36 * in this file.
37 */
38namespace drama {
39 extern void CheckLockTaken(const std::string func,
40 const std::string &file,
41 const int lineNum) ;
42} // namespace drama.
43
44
45#include "drama/exception.hh"
46#include "drama/sdsarray.hh"
47
48#include <tuple>
49
50namespace drama {
54 namespace sds {
55 using std::begin;
56 using std::end;
57
58 /*
59 * The SdsArgPut() template function is used by the Put() method
60 * of sds::Id and is implementing traditional Arg style Put.
61 *
62 * The idea is that we must instantiate a specific version of this
63 * for each primitive SDS type and for strings.
64 *
65 * The Put() method won't link unless there is a specific version for
66 * the type in question. There are all implemented in parsys.cpp.
67 */
68 template <typename T> void SdsArgPut(
69 SdsIdType id, const std::string &name,
71
72 template <> void SdsArgPut<bool>(
73 SdsIdType id, const std::string &name,
74 bool value, StatusType *status);
75 template <> void SdsArgPut<char>(
76 SdsIdType id, const std::string &name,
77 char value, StatusType *status);
78 template <> void SdsArgPut<short>(
79 SdsIdType id, const std::string &name,
80 short value, StatusType *status);
81 template <> void SdsArgPut<unsigned short>(
82 SdsIdType id, const std::string &name,
83 unsigned short value, StatusType *status);
84 template <> void SdsArgPut<INT32>(
85 SdsIdType id, const std::string &name,
87 template <> void SdsArgPut<UINT32>(
88 SdsIdType id, const std::string &name,
90 template <> void SdsArgPut<INT64>(
91 SdsIdType id, const std::string &name,
93 template <> void SdsArgPut<UINT64>(
94 SdsIdType id, const std::string &name,
96 template <> void SdsArgPut<float>(
97 SdsIdType id, const std::string &name,
98 float value, StatusType *status);
99 template <> void SdsArgPut<double>(
100 SdsIdType id, const std::string &name,
101 double value, StatusType *status);
102
103 template <> void SdsArgPut<const char *>(
104 SdsIdType id, const std::string &name,
105 const char *value, StatusType *status);
106
107 /*
108 * The SdsArgGet() template function is used by the Get() method
109 * of sds::Id and is implementing traditional Arg style Get.
110 *
111 * The idea is that we must instantiate a specific version of this
112 * for each primitive SDS type.
113 *
114 * The Get() method won't link unless there is a specific version for
115 * the type in question.
116 */
117 template <typename T> void SdsArgGet(
118 SdsIdType id, const std::string &name,
119 T *value, StatusType *status);
120
121 template <> void SdsArgGet<bool>(
122 SdsIdType id, const std::string &name,
123 bool *value, StatusType *status);
124 template <> void SdsArgGet<char>(
125 SdsIdType id, const std::string &name,
126 char *value, StatusType *status);
127 template <> void SdsArgGet<short>(
128 SdsIdType id, const std::string &name,
129 short *value, StatusType *status);
130 template <> void SdsArgGet<unsigned short>(
131 SdsIdType id, const std::string &name,
132 unsigned short *value, StatusType *status);
133 template <> void SdsArgGet<INT32>(
134 SdsIdType id, const std::string &name,
136 template <> void SdsArgGet<UINT32>(
137 SdsIdType id, const std::string &name,
139 template <> void SdsArgGet<INT64>(
140 SdsIdType id, const std::string &name,
142 template <> void SdsArgGet<UINT64>(
143 SdsIdType id, const std::string &name,
145 template <> void SdsArgGet<float>(
146 SdsIdType id, const std::string &name,
147 float *value, StatusType *status);
148 template <> void SdsArgGet<double>(
149 SdsIdType id, const std::string &name,
150 double *value, StatusType *status);
151 template <> void SdsArgGet<std::string>(
152 SdsIdType id, const std::string &name,
153 std::string *value, StatusType *status);
154
155
156
157
158
159
160 /*
161 * The PutScalar() template function is used by the Put() method
162 * of sds::Id (no name version) and is implementing something like
163 * the traditional Arg style Put, but directly into the current item.
164 *
165 * The idea is that we must instantiate a specific version of this
166 * for each primitive SDS type and for strings.
167 *
168 * The Put() method won't link unless there is a specific version for
169 * the type in question. There are all implemented in parsys.cpp.
170 */
171 template <typename T> void PutScalar(
172 SdsIdType id,
173 T value, StatusType *status);
174
175 template <> void PutScalar<bool>(
176 SdsIdType id,
177 bool value, StatusType *status);
178 template <> void PutScalar<char>(
179 SdsIdType id,
180 char value, StatusType *status);
181 template <> void PutScalar<short>(
182 SdsIdType id,
183 short value, StatusType *status);
184 template <> void PutScalar<unsigned short>(
185 SdsIdType id,
186 unsigned short value, StatusType *status);
187 template <> void PutScalar<INT32>(
188 SdsIdType id,
190 template <> void PutScalar<UINT32>(
191 SdsIdType id,
193 template <> void PutScalar<INT64>(
194 SdsIdType id,
196 template <> void PutScalar<UINT64>(
197 SdsIdType id,
199 template <> void PutScalar<float>(
200 SdsIdType id,
201 float value, StatusType *status);
202 template <> void PutScalar<double>(
203 SdsIdType id,
204 double value, StatusType *status);
205
206 template <> void PutScalar<const char *>(
207 SdsIdType id,
208 const char *value, StatusType *status);
209
210 template <> void PutScalar<const std::string &>(
211 SdsIdType id,
212 const std::string &value, StatusType *status);
213
214 /*
215 * The GetScalar() template function is used by the Get() method
216 * (no name versions) of sds::Id and is implementing something like
217 * the traditional Arg style Get, but from the current item directly,
218 * hence why no name is supplied.
219 *
220 * The idea is that we must instantiate a specific version of this
221 * for each primitive SDS type.
222 *
223 * The Get() method won't link unless there is a specific version for
224 * the type in question.
225 */
226 template <typename T> void GetScalar(
227 SdsIdType id,
228 T *value, StatusType *status);
229
230 template <> void GetScalar<bool>(
231 SdsIdType id,
232 bool *value, StatusType *status);
233 template <> void GetScalar<char>(
234 SdsIdType id,
235 char *value, StatusType *status);
236 template <> void GetScalar<short>(
237 SdsIdType id,
238 short *value, StatusType *status);
239 template <> void GetScalar<unsigned short>(
240 SdsIdType id,
241 unsigned short *value, StatusType *status);
242 template <> void GetScalar<INT32>(
243 SdsIdType id,
245 template <> void GetScalar<UINT32>(
246 SdsIdType id,
248 template <> void GetScalar<INT64>(
249 SdsIdType id,
251 template <> void GetScalar<UINT64>(
252 SdsIdType id,
254 template <> void GetScalar<float>(
255 SdsIdType id,
256 float *value, StatusType *status);
257 template <> void GetScalar<double>(
258 SdsIdType id,
259 double *value, StatusType *status);
260 template <> void GetScalar<std::string>(
261 SdsIdType id,
262 std::string *value, StatusType *status);
263
264
268 class PrintObjectPnt {
269 public:
278 virtual void Print(const std::string &line) = 0;
279 };
283 class PrintObjectCR {
284 public:
293 virtual void Print(const std::string &line) const = 0;
294 };
401 class Id {
402 private:
403 SdsIdType _id; /* Actual Sds id. 0 (zero) is the null ID */
404 struct {
405 bool free : 1;/* Set true to cause destructor to free the OD*/
406 bool del : 1;/* If free is true, destructor will do SdsDelete*/
407 bool readfree : 1;/* if free , destructor will do SdsReadFree */
408 } _flags;
409
410 /*
411 * Private routine to clean up, will be called by destructor and
412 * Shallow copy operations.
413 *
414 * We defer the work to CleanUpWorker(), but need to indicate to
415 * it if SdsFreeIdAndCheck() should be invoked instead of
416 * just SdsFreeId().
417 *
418 * @param from_where Where have we been invoked form, for message
419 * about SDS ID free failures.
420 */
421 /* no exceptions allowed as may be called from move or destructor */
422 void CleanUp(const std::string &from_where) noexcept {
423#if defined(SDS_CHECK_FREE)||defined(SDS_CHECK_FREE_W)
424 bool check_free = true;
425#else
426 bool check_free = false;
427#endif
428 CleanUpWorker(check_free, from_where);
429 }
430
431 /*
432 * Do the actual clean up.
433 */
434 void CleanUpWorker(bool check, const std::string &from_where) noexcept;
435
436
437
438 /* This method is used by the ArrayAccess methods to check the item
439 is appropiate for the SdsArrayAccessHelper being used
440 */
441 template <class ContainerType>
442 void CheckArrayType(
443 const SdsCodeType code, /* Expected code */
444 const long ndims, /* Expected number of dims */
445 ContainerType * const dims) const { /* Actual dims written here */
446
448 /*
449 * Get details on the object.
450 */
451 GetDims(dims);
452 /*
453 * Check the code and number of dimensions are correct.
454 */
455 if (tcode != code)
456 {
458 "SDS type does not match expected array type");
459 }
460 if (dims->size() == 0)
461 {
463 "Attempt to access an array in an SDS structure which is not an array");
464 }
465 if (dims->size() != static_cast<unsigned>(ndims))
466 {
468 "SDS Array structure has % dimensions instead of the expected %",
469 dims->size(), ndims);
470 }
471
472 }
473 /*
474 * A simplified access to CheckArrayType, for a single
475 * dimensional array.
476 */
477 void CheckArrayTypeSingleDim(
478 const SdsCodeType code,
479 unsigned long * const nitems) const { /* Actual number of items written here*/
480
481 std::vector<unsigned long> dims;
482 CheckArrayType(code, 1, &dims);
483 *nitems = dims[0];
484
485 }
486
487 /*
488 * This is used to set an ArrayAccessHelper item's data
489 * pointer to be the result of SdsPointer() on this item.
490 *
491 */
492 template <class T> void SetArrayHelperDataAddr(
493 T * const data) const {
494
495 unsigned char *dataAddr = 0;
497 data->SetDataToAddr(dataAddr);
498 }
499
500
501 public:
513 /* Whilst we have SdsCloneId() we can't really use it at this
514 * point since we don't know what to do with the flags.
515 */
516 Id& operator=(const Id &rhs) = delete;
528 /* Whilst we have SdsCloneId() we can't really use it at this
529 * point since we don't know what to do with the flags (who
530 * gets to control deletion?)
531 */
532 Id(const Id &source) = delete;
533
534 /*
535 * Note, the "copy elision" rule is an allowed optimization
536 * in C++, implemented in gcc. It means that the following
537 * two methods will not actually be invoked, through they
538 * must exist for the moves to be allowed. In effect, in cases
539 * where a temp would be constructed and its value moved,
540 * the optimization allows the target variable to be constructed
541 * instead of the temp. See
542 *
543 * http://en.cppreference.com/w/cpp/language/copy_elision
544 *
545 */
546
547
555 Id& operator=(Id &&rhs) noexcept {
556 //fprintf(stderr,"drama::sds::Id move assignment triggered\n");
557
558 CleanUp("sds::Id move assignment");
560 _id = rhs._id;
561 _flags = std::move(rhs._flags);
562
563 rhs._id = 0;
564 return *this;
565 }
573 Id(Id &&source) noexcept :
574 _id(source._id), _flags(std::move(source._flags)) {
575 //fprintf(stderr,"drama::sds::Id move constructor triggered\n");
576 source._id = 0;
577 }
578
584 Id() {
585 _id = 0;
586 _flags.free = false;
587 _flags.del = false;
588 _flags.readfree = false;
589 }
590
591 private:
592 /* Construct an sds::Id item from an existing C language SDS id.
593 *
594 * This sds::Id constructor that takes an existing SDS id
595 * (C style) and creates an sds::Id class object which refers
596 * to that SDS id. You must explicitly specify if the item is to be
597 * free-ed and/or deleted when the object's destructor is invoked,
598 * and what you do depends on when what other code may do with
599 * item. The del and readfree are mutually exclusive, through
600 * this is currently not checked in this implementation.
601 *
602 * @param item The SdsIdType of the item. If 0 (the default), the
603 * sds::Id object constructed does not refer to any SDS
604 * item. This is normally only used when we want an
605 * argument to pass (by pointer) to a function which
606 * will use move assignment or sds::Id::ShallowCopy()
607 * to set the ID.
608 *
609 * @param free Set true to invoke DCF(SdsFreeId) on the ID when the
610 * object is destroyed. The default is false.
612 * @param del Set true to invoke DCF(SdsDelete) on the ID when
613 * the object is destroyed. The default is false.
614 *
615 * @param readfree Set true to invoke DCF(SdsReadFree) on the ID
616 * when the object is destroyed. The default is false.
617 *
618 */
619 explicit Id(const SdsIdType item, const bool free=false,
620 const bool del = false, const bool readfree = false) :
621 _id(item) {
622 _flags.free = free;
623 _flags.del = del;
624 _flags.readfree = readfree;
625 }
626 public:
642 static Id CreateNullItem();
643
670 const SdsIdType item, const bool free=false,
671 const bool del = false, const bool readfree = false);
672
684 const SdsIdType item);
685
686
703 static Id CreateFromSdsId(const SdsId &item);
704
722 static Id CreateFromSdsId(SdsId *item);
723
724
752 template <class ContainerType>
754
755 /*
756 * Confirm the container is a container of POD types.
757 * From C++20, std::is_pod<>() is depreciated, we can replace
758 * by std::is_standard_layout<>::value && std::is_trivial<>::value
759 *
760 */
761 static_assert(
762 (std::is_standard_layout<typename ContainerType::value_type>::value &&
763 std::is_trivial<typename ContainerType::value_type>::value) ,
764 "The value type in the container must be a standard layout and trivial (POD) type");
765
766 if (container->empty())
767 {
769 "Attempt to access data in empty container");
770 }
771 Id item(0, true, false, false); /* Must free-ed when done */
773 SdsAccess(&(*container)[0],&item._id,&status);
774 if (status != STATUS__OK)
775 DramaTHROW(status, "Failed to access SDS Item");
776
777 return item;
778 }
802 template <class ContainerType>
804 /*
805 * Confirm the container is a container of POD types.
806 * From C++20, std::is_pod<>() is depreciated, we can replace
807 * by std::is_standard_layout<>::value && std::is_trivial<>::value
808 */
809 static_assert(
810 (std::is_standard_layout<typename ContainerType::value_type>::value &&
811 std::is_trivial<typename ContainerType::value_type>::value ) ,
812 "The value type in the container must be a standard layout and trivial (POD) type");
813
814
815 if (container.empty())
816 {
818 "Attempt to access data in empty container");
819 }
820
821
822 Id item(0, true, true, false); /* Must deleted and free-ed when done */
824 SdsImport(&container[0],&item._id,&status);
825 if (status != STATUS__OK)
826 DramaTHROW(status, "Failed to import SDS Item");
827
828 return item;
829 }
846 static Id FromFile(const std::string &filename);
865 virtual Id CreateChildItem(
866 const std::string &name,
867 const SdsCodeType code,
868 const std::string &extra = "") const;
869
883 static Id CreateTopLevel(
884 const std::string &name,
885 const SdsCodeType code,
886 const std::string &extra = "");
887
912 template <class ContainerType>
914 const std::string &name,
915 const SdsCodeType code,
916 const ContainerType& dims,
917 const std::string &extra = "") const {
918
919 Id item(0,true, false, false);
921
922 /*
923 * "dims" can be any container that
924 * 1. Has a size method.
925 * 2. Can be used to initialize a std::vector of unsigned long.
926 * 3. And it is validated for a 0 < size <= 7.
927 */
928 if ((dims.size() < 1)||(dims.size() > SDS__MAXDIMS))
929 {
931 "Failed to create new SDS array - % dimensions, minimum supported 1, maximum supported is %",
932 dims.size(),
934 }
935 /*
936 * We need to pass an array of unsigned long to SdsNew for
937 * the dimensions. The best approach is to create a vector
938 * of unsigned long and initialize it with the contents of
939 * our passed in container.
940 */
941 std::vector<unsigned long> myDims(dims);
942
943 SdsNew(_id,name.c_str(),extra.size(),extra.data(),code,
944 myDims.size(), myDims.data(),&item._id,&status);
945 if (status != STATUS__OK)
946 DramaTHROW_S(status, "Failed to create new SDS array top-level item %",name);
947 return item;
948 }
949
973 const std::string &name,
974 const SdsCodeType code,
975 const unsigned nElem,
976 const std::string &extra = "") const {
977
978 Id item(0,true, false, false);
980
981 /*
982 * This is a simplification of the above multi-dimensional
983 * version.
984 */
985 unsigned long dims[1];
986 dims[0] = nElem;
987 SdsNew(_id,name.c_str(),extra.size(),extra.data(),code,
988 1, dims, &item._id,&status);
989 if (status != STATUS__OK)
990 DramaTHROW_S(status, "Failed to create new SDS array top-level item %",name);
991 return item;
992 }
993
994
995
1015 template <class ContainerType>
1016 static Id CreateTopLevelArray(
1017 const std::string & name,
1018 const SdsCodeType code,
1019 const ContainerType& dims,
1020 const std::string &extra = ""){
1021
1022 Id item(0,true, true, false);
1024
1025 /*
1026 * "dims" can be any container that
1027 * 1. Has a size method.
1028 * 2. Can be used to initialize a std::vector of unsigned long.
1029 * 3. And it is validated for a 0 < size <= 7.
1030 */
1031 if ((dims.size() < 1)||(dims.size() > SDS__MAXDIMS))
1032 {
1034 "Failed to create new SDS array - % dimensions, minimum supported 1, maximum supported is %",
1035 dims.size(),
1037 }
1038 /*
1039 * We need to pass an array of unsigned long to SdsNew for
1040 * the dimensions. The best approach is to create a vector
1041 * of unsigned long and initialize it with the contents of
1042 * our passed in container.
1044 std::vector<unsigned long> myDims(dims);
1045
1046
1047 SdsNew(0,name.c_str(),extra.size(),extra.data(),code,
1048 myDims.size(), myDims.data(),&item._id,&status);
1049 if (status != STATUS__OK)
1050 DramaTHROW_S(status, "Failed to create new SDS array top-level item %",name);
1051
1052 return item;
1053 }
1054
1074 static Id CreateTopLevelArray(
1075 const std::string & name,
1076 const SdsCodeType code,
1077 const unsigned nElem,
1078 const std::string &extra = ""){
1079
1080 Id item(0,true, true, false);
1082
1083 /*
1084 * This is a simplification of the above multi-dimensional
1085 * version.
1086 */
1087 unsigned long dims[1];
1088 dims[0] = nElem;
1089
1090
1091 SdsNew(0,name.c_str(),extra.size(),extra.data(),code,
1092 1, dims,&item._id,&status);
1093 if (status != STATUS__OK)
1094 DramaTHROW_S(status, "Failed to create new SDS array top-level item %",name);
1095
1096 return item;
1097 }
1098
1099
1100
1134 template <class ContainerType>
1136 bool throwOnNotFound=true) const {
1137 Id item(0, true, false, false);
1138
1139 /*
1140 * "dims" can be any container that
1141 * 1. Has a size method.
1142 * 2. Can be used to initialize a std::vector of unsigned long.
1143 * 3. And it is validated for a 0 < size <= 7.
1144 */
1145 if ((indicies.size() < 1)||(indicies.size() > SDS__MAXDIMS))
1146 {
1148 "Failed to access SDS array cell - % dimensions, minimum supported 1, maximum supported is %",
1149 indicies.size(),
1151 }
1152 /*
1153 * We need to pass an array of unsigned long to SdsCell for
1154 * the dimensions. The best approach is to create a vector
1155 * of unsigned long and initialize it with the contents of
1156 * our passed in container.
1157 */
1158 std::vector<unsigned long> myDims(indicies);
1159
1160
1162 SdsCell(_id, myDims.size(), myDims.data(), &item._id, &status);
1163
1164 /* Special case of item not found and don't want to throw, return null id */
1166 {
1167 item._flags.del = false;
1168 return item;
1169 }
1170
1171 if (status != STATUS__OK)
1173 "Failed to access cell of existing SDS array id");
1174 return item;
1175 }
1191 virtual Id Copy() const;
1192
1214 virtual Id Find(const std::string &name,
1215 bool throwOnNotFound=true) const;
1216
1244 virtual Id Index(const long index, bool throwOnNotFound=true) const;
1245
1262 virtual ~Id() {
1263 /*Just invoke the private cleanup routine */
1264 CleanUp("sds::Id destructor");
1265 }
1266 /* Modify flags */
1267
1273 virtual void SetFree() { _flags.free = true; }
1279 virtual void SetDelete() { _flags.del = true; }
1280
1289 virtual void ClearDelete() { _flags.del = false; }
1290
1300 virtual void Outlive() {
1301 _flags.free = false;
1302 _flags.del = false;
1303 _flags.readfree = false;
1304 }
1305
1307 * General operations, as per similar SDS operations.
1308 * Currently only Delete, Get and Put are virtual.
1309 */
1310
1328 virtual void Delete() {
1330 SdsDelete(_id,&status);
1331 if (status == STATUS__OK)
1332 {
1333 _flags.del = false;
1334 if (_flags.free)
1335 {
1336 SdsFreeId(_id, &status);
1337 if (status == STATUS__OK)
1338 {
1339 _id = 0;
1340 _flags.free = false;
1341 }
1342 }
1343 }
1344 else
1345 DramaTHROW(status, "Failed to delete SDS item");
1346 }
1374 template <class ContainerType>
1375 void Export(ContainerType *container) const {
1377
1378 /*
1379 * Confirm the container is a container of POD types.
1380 * From C++20, std::is_pod<>() is depreciated, we can replace
1381 * by std::is_standard_layout<>::value && std::is_trivial<>::value
1382 */
1383 static_assert(
1384 (std::is_standard_layout<typename ContainerType::value_type>::value &&
1385 std::is_trivial<typename ContainerType::value_type>::value) ,
1386 "The value type in the container must be a standard layout and trivial (POD) type");
1387
1388
1389 // Must multiple container size() in units by size of each unit.
1390 SdsExport(_id,
1391 (container->size()*sizeof((*container)[0])),
1392 &(*container)[0],&status);
1393 if (status != STATUS__OK)
1394 DramaTHROW(status, "Failed to export SDS item");
1395
1396 }
1421 template <class ContainerType>
1423 /*
1424 * Confirm the container is a container of POD types.
1425 * From C++20, std::is_pod<>() is depreciated, we can replace
1426 * by std::is_standard_layout<>::value && std::is_trivial<>::value
1427 */
1428 static_assert(
1429 (std::is_standard_layout<typename ContainerType::value_type>::value &&
1430 std::is_trivial<typename ContainerType::value_type>::value) ,
1431 "The value type in the container must be a standard layout and trivial (POD) type");
1432
1434 SdsExportDefined(_id,container->size(),&(*container)[0],&status);
1435 if (status != STATUS__OK)
1436 DramaTHROW(status, "Failed to export defined SDS item");
1437 }
1456 virtual void Extract() {
1458 SdsExtract(_id,&status);
1459 if (status != STATUS__OK)
1460 DramaTHROW(status, "Failed to extract SDS item");
1461
1462 /*
1463 * We need to modify the flags to those appropriate for
1464 * and indepent toplevel item
1465 */
1466 _flags.free = true;
1467 _flags.del = true;
1468 _flags.readfree = false;
1469 }
1482 virtual void Flush() {
1484
1485 //fprintf(stderr,"FLUSH:ID=%d\n", (int)(_id));
1486
1487
1488 SdsFlush(_id,&status);
1489 if (status != STATUS__OK)
1490 DramaTHROW(status, "Failed to flush SDS item");
1491 }
1519 template <typename T>
1520 void Get(const unsigned long length,
1521 T * const data,
1522 unsigned long *actlen = nullptr,
1523 const unsigned long offset=0) const {
1524
1525 /*
1526 * Confirm the data type is a POD type.
1527 * From C++20, std::is_pod<>() is depreciated, we can replace
1528 * by std::is_standard_layout<>::value && std::is_trivial<>::value
1529 */
1530 static_assert(
1531 (std::is_standard_layout<T>::value && std::is_trivial<T>::value) ,
1532 "The type T must be a standard layout and trivial (POD) type");
1533
1534
1535 unsigned long myactlen;
1536 if (!actlen) actlen = &myactlen;
1538 SdsGet(_id,length,offset,(void *)data,actlen,&status);
1539
1540 if (status != STATUS__OK)
1541 DramaTHROW(status, "Failed to Get data from SDS item");
1542 }
1555 virtual std::string GetExtra() const {
1556
1557 unsigned long length = 0;
1559 SdsGetExtraLen(_id, &length, &status);
1560 if ((status == STATUS__OK)&&(length == 0))
1561 return "";
1562 /*
1563 * Allocate some space to store the extra data in.
1564 */
1565 std::unique_ptr<char[]> extraData(new char[length+1]);
1566
1567 unsigned long actlen;
1568 /*
1569 * Get the data.
1570 */
1572 if (status != STATUS__OK)
1574 "Failed to Get extra data from SDS item");
1575 extraData[length] = 0; // Ensure null termination.
1576 return &extraData[0];
1577 }
1587 virtual std::string GetName() const {
1588
1589 char tName[SDS_C_NAMELEN];
1591 SdsGetName(_id,tName,&status);
1592
1593 if (status != STATUS__OK)
1595 "Failed to Get Name of SDS item");
1596 return tName;
1597
1598
1599 }
1614 virtual SdsCodeType GetCode() const {
1615 SdsCodeType code;
1617 SdsGetCode(_id,&code,&status);
1618 if (status != STATUS__OK)
1619 DramaTHROW(status, "Failed to Get code of SDS item");
1620
1621 return code;
1622
1623 }
1636 virtual void ValidateCode(SdsCodeType requiredCode) const {
1640 if (status != STATUS__OK)
1642 DramaTHROW(status, "Failed to Get code of SDS item");
1643 }
1644
1645 if (actualCode != requiredCode)
1646 {
1648 "SDS Item % has code %, was expected to have code %",
1649 GetName(),
1652 }
1653
1654 }
1655
1677 template <class ContainerType>
1678 void GetDims(ContainerType *dims) const {
1679
1680 unsigned long tdims[SDS_C_MAXARRAYDIMS];
1681 long ndims;
1684 if (status != STATUS__OK)
1686 "Failed to Get dimensions of SDS item");
1687
1688 /*
1689 * Copy dims to output location.
1690 */
1691 dims->clear();
1692 for (int i = 0; i < (int)(ndims) ; ++i)
1693 {
1694 dims->push_back(tdims[i]);
1695 }
1696
1697 }
1707 unsigned GetNumItems() const {
1708
1709 long numItems = 0;
1711 SdsNumItems(_id, &numItems, &status);
1712 if (status != STATUS__OK)
1714 "Failed to Get number of SDS items");
1715
1716 return numItems;
1717 }
1718
1719
1729 virtual void Insert(Id & to_insert) {
1731 SdsInsert(_id,to_insert._id,&status);
1732 if (status != STATUS__OK)
1733 DramaTHROW(status, "Failed to insert SDS item.");
1735
1736
1737 /*
1738 * If we succeed, the new child should not be deleted when
1739 * it's id is destroyed, so clear the flag. (This is why
1740 * we break Tony's normal rule of not using non-const
1741 * references.
1742 */
1743 to_insert._flags.del = false;
1744 }
1764 template <class ContainerType>
1765 void Insert(Id & to_insert,
1766 const ContainerType& dims) {
1767
1769 /*
1770 * "dims" can be any container that
1771 * 1. Has a size method.
1772 * 2. Can be used to initialize a std::vector of unsigned long.
1773 * 3. And it is validated for a 0 < size <= 7.
1774 */
1775 if ((dims.size() < 1)||(dims.size() > SDS__MAXDIMS))
1776 {
1778 "Failed to create new SDS array - % dimensions, minimum supported 1, maximum supported is %",
1779 dims.size(),
1781 }
1782
1783 /*
1784 * We need to pass an array of unsigned long to SdsNew for
1785 * the dimensions. The best approach is to create a vector
1786 * of unsigned long and initialize it with the contents of
1787 * our passed in container.
1788 */
1789 std::vector<unsigned long> myDims(dims);
1790
1791
1792 SdsInsertCell(_id,myDims.size(),myDims.data(),to_insert._id,&status);
1793
1794 if (status != STATUS__OK)
1795 DramaTHROW(status, "Failed to insert item into array cell");
1796 /*
1797 * If we succeed, the new child should not be deleted when
1798 * it's id is destroyed, so clear the flag
1799 */
1800 to_insert._flags.del = false;
1801 }
1802
1813 virtual void FillArray(const Id &elem) {
1815 SdsFillArray(_id,elem._id,&status);
1816 if (status != STATUS__OK)
1817 DramaTHROW(status, "Failed to fill structure");
1818 }
1819
1858 template <typename T>
1859 void Pointer(T **data, unsigned long * length=0) const {
1860
1861
1862 /*
1863 * Confirm the data type is a POD type.
1864 * From C++20, std::is_pod<>() is depreciated, we can replace
1865 * by std::is_standard_layout<>::value && std::is_trivial<>::value
1866 */
1867 static_assert(
1868 (std::is_standard_layout<T>::value && std::is_trivial<T>::value) ,
1869 "The type T must be a standard layout and trivial (POD) type");
1870
1871
1872 unsigned long mylength;
1874
1875 if (!length) length = &mylength;
1876
1877 void *tdata;
1878
1880 if (status != STATUS__OK)
1881 DramaTHROW(status, "Failed to get pointer to data.");
1882
1883 *data = static_cast<T *>(tdata);
1884
1885 /* fprintf(stderr,"Pointer:ID=%d, pointer=%p\n",
1886 (int)(_id), (void *)(tdata));
1887 */
1888 }
1889
1914 template <typename T>
1915 void Put(const unsigned long length,
1916 const T * const data,
1917 const unsigned long offset=0) {
1919 /*
1920 * Confirm the data type is a POD type.
1921 * From C++20, std::is_pod<>() is depreciated, we can replace
1922 * by std::is_standard_layout<>::value && std::is_trivial<>::value
1923 */
1924 static_assert(
1925 (std::is_standard_layout<T>::value && std::is_trivial<T>::value) ,
1926 "The type T must be a standard layout and trivial (POD) type");
1927
1928 const void *tdata = static_cast<const void *>(data);
1929
1931 if (status != STATUS__OK)
1932 DramaTHROW(status, "Failed to put data into SDS.");
1933
1934
1935 }
1936
1948 virtual void PutExtra(const std::string &extra) {
1949
1951 SdsPutExtra(_id,extra.size(),extra.data(),&status);
1952 if (status != STATUS__OK)
1953 DramaTHROW(status, "Failed to put extra data into SDS.");
1954 }
1963 virtual void Rename(const std::string &name) {
1965 SdsRename(_id,name.c_str(),&status);
1966 if (status != STATUS__OK)
1967 DramaTHROW(status, "Failed to rename SDS item..");
1968
1969 }
1996 template <class ContainerType>
1997 void Resize(const ContainerType& dims) {
1998
1999
2001 /*
2002 * "dims" can be any container that
2003 * 1. Has a size method.
2004 * 2. Can be used to initialize a std::vector of unsigned long.
2005 * 3. And it is validated for a 0 < size <= 7.
2006 */
2007 if ((dims.size() < 1)||(dims.size() > SDS__MAXDIMS))
2008 {
2010 "Failed to create new SDS array - % dimensions, minimum supported 1, maximum supported is %",
2011 dims.size(),
2013 }
2014
2015 /*
2016 * We need to pass an array of unsigned long to SdsResize for
2017 * the dimensions. The best approach is to create a vector
2018 * of unsigned long and initialize it with the contents of
2019 * our passed in container.
2020 */
2021 std::vector<unsigned long> myDims(dims);
2022
2023 SdsResize(_id,myDims.size(),myDims.data(),&status);
2025 if (status != STATUS__OK)
2026 DramaTHROW(status, "Failed to resize SDS array");
2027
2028 }
2036 virtual unsigned long Size() const {
2037 unsigned long bytes;
2039 SdsSize(_id,&bytes,&status);
2040 if (status != STATUS__OK)
2041 DramaTHROW(status, "Failed to return size of SDS structure");
2042 return bytes;
2043
2044 }
2058 virtual unsigned long SizeDefined() const {
2059 unsigned long bytes;
2062 if (status != STATUS__OK)
2063 DramaTHROW(status, "Failed to return size of SDS structure");
2064 return bytes;
2065
2066 }
2067
2072 virtual void List() const {
2074 SdsList(_id,&status);
2075
2076 if (status != STATUS__OK)
2077 DramaTHROW(status, "Failed to list SDS structure");
2078 }
2084 virtual void List(FILE *to) const {
2086 SdsListTo(to, _id,&status);
2087
2088 if (status != STATUS__OK)
2089 DramaTHROW(status,"Failed to list SDS structure");
2090 }
2102 virtual void List(std::ostream &strm,
2103 int lineMaxLen=100) const;
2104
2127 virtual void List(PrintObjectPnt *printer, int lineMaxLen=100) const;
2128
2151 virtual void List(const PrintObjectCR
2152 &printer, int lineMaxLen=100) const;
2153
2164 virtual void Write(const std::string &filename) const {
2166 SdsWrite(_id,filename.c_str(),&status);
2167 if (status != STATUS__OK)
2169 "Failed to write SDS structure to file \"%\"",
2170 filename);
2171
2172 }
2173
2184 virtual bool IsExternal() const {
2186 int external = 0;
2187 SdsIsExternal(_id, &external, &status);
2188 if (status != STATUS__OK)
2189 DramaTHROW(status, "Failed to determine if SDS is external");
2190
2191 return external;
2192 }
2193 /* Return the address of an external item.
2194 *
2195 * This method is used to determine the address of the buffer
2196 * containing an external item, if this item refers to an external
2197 * item. This is the value given the contructor which accessed this
2198 * item.
2199 *
2200 * @returns The address of the external item data buffer.
2201 */
2202#if 0 // SdsGetExternInfo() does not actually exist - not sure what happened
2203 virtual void *GetExternInfo() const {
2204 void *data;
2206 SdsGetExternInfo(_id, &data, &status);
2207 if (status != STATUS__OK)
2209 "Failed to get SDS external structure address");
2210
2212 return data;
2213 }
2214#endif
2215
2216
2230 virtual bool Exists(const std::string &name) const;
2244 virtual bool Exists(unsigned index) const;
2245
2246
2258 explicit operator SdsIdType() const { return _id; }
2259
2265 explicit operator bool() const {
2266 return (_id != 0);
2267 }
2268
2296 virtual SdsIdType COut(const bool outlives, bool * const free = 0,
2297 bool * const del= 0, bool * const readfree = 0) {
2298 if (free)
2299 *free = _flags.free;
2300 if (del)
2301 *del = _flags.del;
2302 if (readfree)
2303 *readfree = _flags.readfree;
2304 if (outlives)
2305 _flags.free = _flags.del = _flags.readfree = false;
2306 return (_id);
2307 }
2327 virtual void ShallowCopy (const Id & source) {
2328 if (this != &source)
2329 {
2330 CleanUp("sds::Id::ShallowCopy 1"); /* Run destructor on old id */
2331 _id = source._id;
2332 _flags.free = _flags.del = _flags.readfree = false;
2333 }
2334 }
2335
2336
2356 virtual void ShallowCopy (Id * source, const bool outlives) {
2357 if (this != source)
2358 {
2359 CleanUp("sds::Id::ShallowCopy 2"); /* Run destructor on old id */
2360 _id = source->_id;
2361 if (outlives)
2362 {
2363 /* If we will outlive the source, then we copy the source's
2364 * flags and set the sources flags to false.
2365 */
2366
2367 _flags.free = source->_flags.free;
2368 _flags.del = source->_flags.del;
2369 _flags.readfree = source->_flags.readfree;
2370
2371 source->_flags.free = source->_flags.del =
2372 source->_flags.readfree = false;
2373 }
2374 else
2375 {
2376 _flags.free = _flags.del = _flags.readfree = false;
2377 }
2378 }
2379 }
2380
2381
2401 virtual void ShallowCopy (const SdsIdType source, const bool free=false,
2402 const bool del = false, const bool readfree = false) {
2403 CleanUp("sds::Id::ShallowCopy 3"); /* Run destructor on old id */
2404 _flags.free = free;
2405 _flags.del = del;
2406 _flags.readfree = readfree;
2407 _id = source;
2408 }
2409
2421 virtual void ToSdsId(::SdsId *target, const bool outlives= false) {
2422 if (outlives)
2423 {
2424 /*
2425 * If the target outlives the source, then copy the
2426 * flags and then clear the close versions.
2427 */
2428 target->ShallowCopy(_id, _flags.free,
2429 _flags.del, _flags.readfree);
2430 _flags.free = false;
2431 _flags.del = false;
2432 _flags.readfree = false;
2433 }
2434 else
2435 {
2436 /*
2437 * Otherwise the defaults will do.
2438 */
2439 target->ShallowCopy(_id);
2440 }
2441 }
2442
2479 template <typename T> void ArrayAccess(
2480 ArrayAccessHelper<T> * const data) const {
2481
2482 unsigned long dims[SDS_C_MAXARRAYDIMS];
2483 CheckArrayTypeSingleDim(data->Code(), dims);
2484 data->SetNumElements(dims[0]);
2485 SetArrayHelperDataAddr(data);
2486 }
2523 template <typename T> void ArrayAccess(
2524 const unsigned long nitems, /* Expected number of elements in array*/
2525 sds::ArrayAccessHelper<T> * const data) const {
2526
2527 unsigned long dims[SDS_C_MAXARRAYDIMS];
2528 CheckArrayTypeSingleDim(data->Code(), dims);
2529 if (dims[0] != nitems)
2530 {
2532 "ArrayAccess expected % items, found %",
2533 nitems, dims[0]);
2534 }
2535 data->SetNumElements(dims[0]);
2536 SetArrayHelperDataAddr(data);
2537 }
2582 template <typename T, class ContainerType> void ArrayAccess(
2583 ArrayAccessHelper<T> * const data,
2584 long ndims,
2585 ContainerType *dims) const {
2586
2587
2588
2589 if ((ndims < 1)||(ndims > SDS_C_MAXARRAYDIMS))
2590 {
2592 "Failed to access SDS array. Numbers of dimensions % invalid, must be in range 1 to %",
2594
2595 }
2596 CheckArrayType(data->Code(), ndims, dims);
2597
2598 /*
2599 * work out the number of elements
2600 */
2601 unsigned long elements = (*dims)[0];
2602 for (unsigned long i = 1; i < dims->size() ; ++i)
2603 {
2604 elements *= (long)((*dims)[i]);
2605 }
2606 data->SetNumElements(elements);
2607 /*
2608 * Access the data.
2610 SetArrayHelperDataAddr(data);
2611 }
2612
2613
2660 template <typename T, class ContainerType> void ArrayAccess(
2661 ArrayAccessHelper<T> * const data,
2662 ContainerType *dims ) const {
2663
2664 /*
2665 * A bit of a pain, we need to call Dims to get the number
2666 * of dimensions.
2667 */
2668 GetDims(dims);
2669 /*
2670 * The use the above version where we know the number of dimensions
2671 */
2672 ArrayAccess(data, dims->size(), dims);
2673 }
2674
2675
2676 /*** ARG style methods ***/
2677
2692 static Id CreateArgStruct(const std::string &name = "ArgStructure");
2693
2726 template <typename ContainerType>
2727 static Id CreateArgCmdStruct(
2728 const ContainerType &values,
2729 const std::string &name="ArgStructure") {
2730
2731
2732 Id item(CreateArgStruct(name));
2733
2734 std::string itemName = "Argument";
2735
2736 unsigned argNum = 1;
2737 for (auto s: values) {
2738
2739 std::string thisName = itemName + std::to_string(argNum);
2740
2741 item.Put(thisName,s);
2742
2743 ++argNum;
2744
2745 }
2746
2747 return item;
2748
2749 }
2782 template <typename T>
2783 static Id CreateArgCmdStruct(
2784 const std::initializer_list<T> &values,
2785 const std::string &name="ArgStructure") {
2786
2787 return CreateArgCmdStruct(std::vector<T>(values), name);
2788 }
2818 template <typename T>
2820 const T value,
2821 const std::string &name="ArgStructure") {
2822
2823
2824 Id item(CreateArgStruct(name));
2825 item.Put("Argument1",value);
2826 return item;
2827 }
2828
2829
2858 template <typename ContainerType>
2859 void AddToArgCmdStruct(
2860 const ContainerType &values,
2861 const unsigned firstArg = 1) {
2862
2863 std::string itemName = "Argument";
2864
2865 unsigned argNum = firstArg;
2866 if (argNum == 0) argNum = 1;
2867 for (auto s: values) {
2868
2869 std::string thisName = itemName + std::to_string(argNum);
2870
2871 Put(thisName,s);
2872
2873 ++argNum;
2874
2875 }
2876 }
2877
2878
2879
2891 virtual std::string toString(int maxlen = 200) {
2892
2893 /*
2894 * Allocate some space to store the string in.
2895 */
2896 //std::unique_ptr<char[]> string(new char[maxlen]);
2897 char *string = new char[maxlen];
2898 int length=0;
2900 /*
2901 * ArgToString() does the job for us.
2902 */
2903 ArgToString((SdsIdType)(*this),maxlen,&length,&string[0],&status);
2904 if (status != STATUS__OK)
2905 {
2906 delete[] string;
2907 DramaTHROW(status, "Failed to convert SDS to string");
2908 }
2909
2910 std::string result=&string[0];
2911
2912 return result;
2913 }
2941 template <typename T>
2942 void Put (const std::string &name, T value, const std::string &extraData="") {
2943
2944
2946 /* There must be a specialization of SdsArgPut() which
2947 supports type T. Note that conversion of DRAMA status
2948 to DRAMA 2 exceptions is done here so it need only be
2949 done once.
2950 */
2951 SdsArgPut(_id, name, value, &status);
2952 if (status != STATUS__OK)
2954 "ArgPut failed of item \"%\" failed",
2955 name);
2956 if (extraData != "")
2957 {
2958 auto itemId = Find(name);
2959 itemId.PutExtra(extraData);
2960 }
2961
2962 }
2963
2975 void Put (const std::string &name, const std::string &value,
2976 const std::string &extraData="") {
2977
2978
2980 ArgPutString(_id, name.c_str(), value.c_str(), &status);
2981 if (status != STATUS__OK)
2983 "ArgPut failed of item \"%\" failed",
2984 name);
2985 if (extraData != "")
2986 {
2987 auto itemId = Find(name);
2988 itemId.PutExtra(extraData);
2989 }
2990
2991 }
3011 template <typename T>
3012 void Get (const std::string &name, T *value) const {
3013
3014
3016 /* There must be a specialization of SdsArgGet() which
3017 supports type T. Note that conversion of DRAMA status
3018 to DRAMA 2 exceptions is done here so it need only be
3019 done once.
3020 */
3021 SdsArgGet(_id, name, value, &status);
3022 if (status != STATUS__OK)
3024 "ArgGet failed of item \"%\" failed",
3025 name);
3026
3027 }
3028
3029
3047 template <typename T>
3048 void Put (T value) {
3049
3050
3052 /* There must be a specialization of PutScalar() which
3053 supports type T. Note that conversion of DRAMA status
3054 to DRAMA 2 exceptions is done here so it need only be
3055 done once.
3056 */
3057 PutScalar(_id, value, &status);
3058 if (status != STATUS__OK)
3059 DramaTHROW(status, "PutScalar failed of item failed");
3060
3061 }
3062
3070 void Put (const std::string &value) {
3071
3072
3074 ArgCvt(value.c_str(),ARG_STRING,ARG_SDS,&_id,0,&status);
3076 if (status != STATUS__OK)
3077 DramaTHROW(status, "ArgCvt failed of item failed");
3078
3079 }
3091 template <typename T>
3092 void Get (T *value) const {
3093
3094
3096 /* There must be a specialization of GetScalar() which
3097 supports type T. Note that conversion of DRAMA status
3098 to DRAMA 2 exceptions is done here so it need only be
3099 done once.
3100 */
3101 GetScalar(_id, value, &status);
3102 if (status != STATUS__OK)
3103 DramaTHROW(status, "GetScalar failed of item failed");
3104
3105 }
3106
3107
3129 template <class ContainerType>
3130 void CheckItem(SdsCodeType code,
3131 const ContainerType& dims) const {
3132
3133
3135 /*
3136 * "dims" can be any container that
3137 * 1. Has a size method.
3138 * 2. Can be used to initialize a std::vector of unsigned long.
3139 * 3. And it is validated for a 0 <= size <= 7.
3140 * (Note - dims.size() is unsigned)
3141 */
3142 if (dims.size() > SDS__MAXDIMS)
3143 {
3145 "Failed to check SDS array - % dimensions, minimum supported 0, maximum supported is %",
3146 dims.size(),
3148 }
3149
3150 /*
3151 * We need to pass an array of unsigned long to ArgCheckItem for
3152 * the dimensions. The best approach is to create a vector
3153 * of unsigned long and initialize it with the contents of
3154 * our passed in container.
3155 */
3156 std::vector<long> myDims(dims);
3158 ArgCheckItem(_id,code, myDims.size(),myDims.data(),&status);
3159
3160 if (status != STATUS__OK)
3161 DramaTHROW(status, "Check of SDS item failed");
3162
3163 }
3169 virtual int GetInt() const;
3175 virtual unsigned int GetUInt() const;
3181 virtual long GetLong() const;
3182
3188 virtual unsigned long GetULong() const;
3194 virtual double GetDouble() const;
3195
3201 std::string GetString() const;
3203
3204
3205 /* Enable watching of this SDS id.
3206 *
3207 * Output will go to stderr and any older watch details
3208 * are lost
3209 */
3210 void SetWatch() {
3212 SdsSetWatch(_id, nullptr, nullptr,
3213 nullptr, nullptr, nullptr, &status);
3214 if (status != STATUS__OK)
3215 DramaTHROW(status, "SdsSetWatch failed");
3216 }
3217
3218 }; /* class Id */
3219
3229 private:
3230 SdsCheckType _chkData;
3231 int _line;
3232 std::string _file;
3233 std::string _function;
3234 public:
3255 IdChecker(int line, const char *file, const char *function)
3256 : _line(line), _file(file), _function(function) {
3258 SdsCheckInit(&_chkData, &ignore);
3259 }
3266 virtual ~IdChecker() {
3268 SdsCheck(0, &_chkData, &status);
3269 if (status == SDS__CHK_LEAK)
3270 fprintf(stderr,"Warning:sds::IdChecker:Function leaked SDS id's - function %s, file %s, check object at line %d\n", _function.c_str(), _file.c_str(), _line);
3271 else if (status == SDS__CHK_RELEASED)
3272 fprintf(stderr,"Warning:sds::IdChecker:Function released SDS id's - function %s, file %s, check object at line %d\n", _function.c_str(), _file.c_str(), _line);
3273 }
3274 };
3286#define SDS_CHECK_IDS2(function_) drama::sds:IdChecker _sds_id_checker(__LINE__, __FILE__, (function_))
3287
3288
3291 typedef std::shared_ptr<Id> IdPtr;
3292
3294
3295 /*
3296 * This structure is used to specify a deleter to unique_ptr in
3297 * the DataPointer class. It provides a null deleter operation as
3298 * SDS will handle tidying this up.
3299 */
3300 struct _nodel
3301 {
3302 void operator()(void *) const { }
3303 };
3304
3323 template <typename T>
3324 class DataPointer : public std::unique_ptr<T,_nodel> {
3325
3326 private:
3327 unsigned long _lengthBytes; // Length of item in bytes.
3328 drama::sds::Id _refId; // SDS Id.
3329 public:
3338
3339 /*
3340 * Confirm the data type is a POD type.
3341 * From C++20, std::is_pod<>() is depreciated, we can replace
3342 * by std::is_standard_layout<>::value && std::is_trivial<>::value
3343 */
3344 static_assert(
3345 (std::is_standard_layout<T>::value && std::is_trivial<T>::value) ,
3346 "The type T must be a standard layout and trivial (POD) type");
3347
3348 T *dataPnt = 0;
3349 theId.Pointer(&dataPnt, &_lengthBytes);
3350
3351 if (_lengthBytes != sizeof(T))
3352 {
3354 "SDS Pointer error - expected % bytes, got %",
3355 sizeof(T), _lengthBytes);
3356
3357 }
3358
3359
3360 std::unique_ptr<T, _nodel> p(dataPnt, _nodel());
3361
3362 *((std::unique_ptr<T,_nodel>*)(this)) = std::move(p);
3363
3365
3366 }
3376
3377
3378 /*
3379 * Confirm the data type is a POD type.
3380 * From C++20, std::is_pod<>() is depreciated, we can replace
3381 * by std::is_standard_layout<>::value && std::is_trivial<>::value
3382 */
3383 static_assert(
3384 (std::is_standard_layout<T>::value && std::is_trivial<T>::value) ,
3385 "The type T must be a standard layout and trivial (POD) type");
3386
3387 T *dataPnt = 0;
3388 theId->Pointer(&dataPnt, &_lengthBytes);
3389
3390 if (_lengthBytes != sizeof(T))
3391 {
3393 "SDS Pointer error - expected % bytes, got %",
3394 sizeof(T), _lengthBytes);
3395
3396 }
3397
3398
3399 std::unique_ptr<T, _nodel> p(dataPnt, _nodel());
3400
3401 *((std::unique_ptr<T,_nodel>*)(this)) = std::move(p);
3403 _refId.ShallowCopy(theId, outlives);
3404
3405 }
3406
3407
3412 ~DataPointer() {
3413 try
3414 {
3415 _refId.Flush();
3416 }
3417 catch (...)
3418 {
3419 }
3420 }
3425 unsigned long NumBytes() const {
3426 return _lengthBytes;
3427 }
3428 }; // class DataPointer
3429
3449 template <typename T>
3450 class DataPointer<T[]> : public std::unique_ptr<T[], _nodel> {
3451
3452 private:
3453
3454
3455
3456 unsigned long _numItems;
3457 unsigned long _lengthBytes;
3458 drama::sds::Id _refId;
3459 public:
3461 typedef T * iterator;
3463 typedef const T * const_iterator;
3465 typedef T value_type;
3466
3478
3479 /*
3480 * Confirm the data type is a POD type.
3481 * From C++20, std::is_pod<>() is depreciated, we can replace
3482 * by std::is_standard_layout<>::value && std::is_trivial<>::value
3483 */
3484 static_assert(
3485 (std::is_standard_layout<T>::value && std::is_trivial<T>::value) ,
3486 "The type T must be a standard layout and trivial (POD) type");
3487
3488 T *dataPnt = 0;
3489 theId.Pointer(&dataPnt, &_lengthBytes);
3491 if (_lengthBytes < sizeof(T))
3494 "SDS Array Pointer error - expected at least % bytes, got %",
3495 sizeof(T), _lengthBytes);
3496
3497 }
3498
3499
3500 _numItems = _lengthBytes/sizeof(dataPnt[0]);
3501
3502
3503 std::unique_ptr<T[], _nodel> p(dataPnt, _nodel());
3504
3505 *((std::unique_ptr<T[],_nodel>*)(this)) = std::move(p);
3506
3507 _refId.ShallowCopy(theId);
3508
3509 }
3520
3521
3522 /*
3523 * Confirm the data type is a POD type.
3524 * From C++20, std::is_pod<>() is depreciated, we can replace
3525 * by std::is_standard_layout<>::value && std::is_trivial<>::value
3526 */
3527 static_assert(
3528 (std::is_standard_layout<T>::value && std::is_trivial<T>::value) ,
3529 "The type T must be a standard layout and trivial (POD) type");
3530
3531 T *dataPnt = 0;
3532 theId->Pointer(&dataPnt, &_lengthBytes);
3533
3534 if (_lengthBytes < sizeof(T))
3535 {
3537 "SDS Array Pointer error - expected at least % bytes, got %",
3538 sizeof(T), _lengthBytes);
3539
3540 }
3541
3542
3543 _numItems = _lengthBytes/sizeof(dataPnt[0]);
3544
3545
3546 std::unique_ptr<T[], _nodel> p(dataPnt, _nodel());
3547
3548 *((std::unique_ptr<T[],_nodel>*)(this)) = std::move(p);
3549
3550 _refId.ShallowCopy(theId, outlives);
3551
3552 }
3553
3558 ~DataPointer() {
3559 try
3560 {
3561 _refId.Flush();
3562 }
3563 catch (...)
3564 {
3565 }
3566 }
3571 unsigned long size() const {
3572 return _numItems;
3573 }
3578 unsigned long NumBytes() const {
3579 return _lengthBytes;
3580 }
3585 iterator begin() {
3586 return & (*this)[0];
3587 }
3592 iterator end() {
3593 return (&(*this)[0])+_numItems;
3594 }
3599 const_iterator begin() const {
3600 return & (*this)[0];
3601 }
3606 const_iterator end() const {
3607 return (&(*this)[0])+_numItems;
3608 }
3616 const_iterator cbegin() const {
3617 return & (*this)[0];
3618 }
3626 const_iterator cend() const {
3627 return (&(*this)[0])+_numItems;
3628 }
3640 bool empty() const {
3641 return false;
3642 }
3644 }; // class DataPointer - Array Partial specialization
3645
3673 /*
3674 * We need to implement the std::iterator template to ensure we pick
3675 * up various iterator types etc.
3676 *
3677 * It is unclear if we need to define the third argument to this
3678 * template, if we do, I'm not sure what it should be.
3679 *
3680 * std::iterator was depreciated from C++17, we are supposed
3681 * to now provide each of the relevant types explicitly.
3682 * See https://www.fluentcpp.com/2018/05/08/std-iterator-deprecated/ and
3683 * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0174r2.html#2.1
3684 */
3685 class IdIterator /*: public std::iterator<std::forward_iterator_tag, Id> */ {
3686 public: /* std::iterator equivalents */
3687 using iterator_category = std::forward_iterator_tag;
3688 using value_type = Id;
3689 using difference_type =std::ptrdiff_t;
3690 using pointer = Id*;
3691 using reference = Id&;
3692
3693 private:
3694 /* The item we are iterating through */
3695 const Id &_top;
3696 /* Is the item an array of structures. If false, presumed to
3697 * be a structure (validated by constructor)
3698 */
3699 bool _isArray = false;
3700 /* Index to Current component */
3701 unsigned long _curCell = ULONG_MAX;
3702 /* Index to last component + 1 */
3703 unsigned long _endCell = ULONG_MAX;
3704 public:
3716 explicit IdIterator(const Id & id, const bool setEnd=false) :
3717 _top(id) {
3718 /*
3719 * id must be a structure.
3720 */
3721 if (_top.GetCode() != SDS_STRUCT)
3722 {
3724 "Attempt to construct IdIterator on non-structured SDS item (code %)", _top.GetCode());
3725
3726 }
3727 /*
3728 * Grab the dimensions - can only work with a value of 0 or 1.
3729 */
3730 std::vector<unsigned> dims;
3731 _top.GetDims(&dims);
3732 if (dims.size() > 0)
3733 {
3734 /*
3735 * Array item.
3736 */
3737 _isArray = true;
3738 /*
3739 * Code does not yet handle dimensions greater then 1, as
3740 * that requires determining the order we index the
3741 * array etc.
3742 */
3743 if (dims.size() > 1)
3744 {
3746 "Attempt to construct IdIterator on an array of structures with more then 1 dimension - can't yet do that. ");
3747 }
3748 /*
3749 * Index of arrays starts at 1. dims[0] is one
3750 * past the last element.
3751 */
3752 _endCell = dims[0]+1;
3753 _curCell = 1;
3754 }
3755 else
3756 {
3757 /*
3758 * Indexing of structures starts at 1. GetNumItems() is
3759 * the maximum value.
3760 */
3761 _endCell = id.GetNumItems()+1;
3762 _curCell = 1;
3763 }
3764 /*
3765 * IF we are constructing the end item, set _curCell to _endCell.
3766 */
3767 if (setEnd)
3768 _curCell = _endCell;
3769 }
3770
3778 bool operator!= (const IdIterator& other) const {
3779 /* First ensure we are referring to the same SDS structure */
3780 if (&_top != &other._top)
3781 return false;
3782 return _curCell != other._curCell;
3783 }
3784
3790 Id operator* () const {
3791 if (_curCell >= _endCell)
3792 {
3794 "Attempt to dereference IdIterator past end of structure");
3795
3796
3797 }
3798 if (_isArray) {
3799 std::vector<unsigned long> indicies(1);
3800 indicies[0] = _curCell;
3801 return _top.Cell(indicies);
3802 } else {
3803 return _top.Index(_curCell);
3804 }
3812 const IdIterator & operator++ () {
3813 /*
3814 * Only increment if less then _endCell. This should ensure
3815 * we never advance past _endCell, ensuring that the comparison
3816 * against end() works correctly
3818 if (_curCell < _endCell)
3819 ++_curCell;
3820
3821 // although not strictly necessary for a range-based for loop
3822 // following the normal convention of returning a value from
3823 // operator++ is a good idea.
3824 return *this;
3825 }
3826
3827
3828 private:
3829 }; // class IdIterator
3830
3831
3832
3847 template <typename T>
3848 class ArrayContainer {
3849 public:
3851 typedef T value_type;
3853 typedef value_type& reference;
3855 typedef std::size_t size_type;
3856 private:
3857 T *_address = nullptr;
3858 size_type _size = 0;
3859 public:
3866 ArrayContainer(T *address, size_type size) :
3867 _address(address), _size(size){
3868 static_assert(
3869 (std::is_standard_layout<T>::value && std::is_trivial<T>::value) ,
3870 "The type T must be a standard layout and trivial (POD) type");
3871 }
3876 bool empty() const {
3877 return (_size <= 0);
3883 size_type size() const {
3884 return _size;
3885 }
3892 return _address[n];
3896 ~ArrayContainer() {}
3897 }; // Class ArrayContainer
3898
3899
3900 inline drama::sds::IdIterator begin(const drama::sds::Id &id) {
3901 return drama::sds::IdIterator(id);
3902 }
3904 return drama::sds::IdIterator(id, true);
3905 }
3906
3907 } // namespace sds
3908
3909} // namespace drama
3911#endif
SdsCodeType Code() const
Return the SDS type code of the item being accessed.
Definition sdsarray.hh:262
Helper class for access to an SDS Scalar Arrays.
Definition sdsarray.hh:180
size_type size() const
Returns the size of the container in items.
Definition sds.hh:3910
reference operator[](size_type n)
Returns an item at a particular address.
Definition sds.hh:3918
bool empty() const
Returns true if the container is empty.
Definition sds.hh:3903
value_type & reference
The type for a reference to the value.
Definition sds.hh:3880
T value_type
The value type.
Definition sds.hh:3878
ArrayContainer(T *address, size_type size)
Create a container to access the array.
Definition sds.hh:3893
std::size_t size_type
The type used for sizes.
Definition sds.hh:3882
~ArrayContainer()
Destroy the container, not the underlying array item.
Definition sds.hh:3923
A container for simple arrays for use with SDS templates.
Definition sds.hh:3875
const_iterator cend() const
Returns a const iterator pointing to the past-the-end element in the array.
Definition sds.hh:3653
iterator begin()
Returns an iterator pointing to the first element in the array.
Definition sds.hh:3612
const_iterator cbegin() const
Returns a const iterator pointing to the first element in the array.
Definition sds.hh:3643
bool empty() const
Returns true if container is empty.
Definition sds.hh:3667
const T * const_iterator
const iterator for this item
Definition sds.hh:3490
iterator end()
Returns an iterator pointing to the past-the-end element in the array.
Definition sds.hh:3619
unsigned long size() const
Return the number of elements in the array.
Definition sds.hh:3598
DataPointer(const drama::sds::Id &theId)
DataPointer Constructor.
Definition sds.hh:3503
const_iterator begin() const
Returns a const iterator pointing to the first element in the array.
Definition sds.hh:3626
unsigned long NumBytes() const
Return the size of the item in bytes.
Definition sds.hh:3605
~DataPointer()
DataPointer destructor.
Definition sds.hh:3585
T * iterator
iterator for this item
Definition sds.hh:3488
T value_type
Returns the type of T
Definition sds.hh:3492
DataPointer(drama::sds::Id *theId, bool outlives=false)
DataPointer Constructor.
Definition sds.hh:3546
const_iterator end() const
Returns a const iterator pointing to the past-the-end element in the array.
Definition sds.hh:3633
unsigned long NumBytes() const
Return the size of the item in bytes.
Definition sds.hh:3452
DataPointer(drama::sds::Id *theId, bool outlives)
DataPointer Constructor.
Definition sds.hh:3402
~DataPointer()
DataPointer destructor.
Definition sds.hh:3439
DataPointer(const drama::sds::Id &theId)
DataPointer Constructor.
Definition sds.hh:3364
A class that provides direct access to the data of an SDS item, via a sub-class of std::unique_ptr<>.
Definition sds.hh:3351
IdChecker(int line, const char *file, const char *function)
Construct an SdsChecker object.
Definition sds.hh:3282
virtual ~IdChecker()
SdsCheck destructor.
Definition sds.hh:3293
A class to check for SDS leaks.
Definition sds.hh:3255
IdIterator(const Id &id, const bool setEnd=false)
Construct a forward iterator for working through an SDS structure or array of structures.
Definition sds.hh:3743
bool operator!=(const IdIterator &other) const
Inequality operator.
Definition sds.hh:3805
Id operator*() const
Dereference operator - return the sds::Id item the iterator is pointing to.
Definition sds.hh:3817
const IdIterator & operator++()
Increment operator (prefix version).
Definition sds.hh:3839
An iterator for working through SDS Structures and SDS arrays of structures.
Definition sds.hh:3712
virtual void SetFree()
Indicate the underlying SDS item should be free-ed when the sds::Id object is destroyed.
Definition sds.hh:1300
virtual unsigned long GetULong() const
If the SDS item refers to a scalar value, convert it to an unsigned long integer.
Id CreateChildArray(const std::string &name, const SdsCodeType code, const unsigned nElem, const std::string &extra="") const
Factory constructor method Constructor which creates a new child item which is a one-dimensional arra...
Definition sds.hh:999
Id & operator=(Id &&rhs) noexcept
Move assignment operator.
Definition sds.hh:582
virtual std::string GetName() const
Return the name of the SDS item.
Definition sds.hh:1614
virtual std::string GetExtra() const
Get extra data from an SDS item.
Definition sds.hh:1582
virtual Id CreateChildItem(const std::string &name, const SdsCodeType code, const std::string &extra="") const
Factory constructor method which creates a new (non-array) child item.
void Resize(const ContainerType &dims)
Change the dimensions of an SDS array.
Definition sds.hh:2024
static Id FromFile(const std::string &filename)
Factory constructor method that reads an SDS structure from a file.
void Get(const std::string &name, T *value) const
Fetch primitive value from a named component of the structure.
Definition sds.hh:3039
virtual void ClearDelete()
Indicate the underlying SDS structure should NOT be deleted when the sds::Id object is destroyed.
Definition sds.hh:1316
virtual bool Exists(unsigned index) const
Determine if a item of a given index exists in a structure.
void CheckItem(SdsCodeType code, const ContainerType &dims) const
Check an item has a required structure.
Definition sds.hh:3157
unsigned GetNumItems() const
Return the number of components in an SDS structure.
Definition sds.hh:1734
virtual long GetLong() const
If the SDS item refers to a scalar value, convert it to long integer.
virtual void Outlive()
Force the actual SDS ID to outlive the sds::Id variable.
Definition sds.hh:1327
void ArrayAccess(const unsigned long nitems, sds::ArrayAccessHelper< T > *const data) const
Access the data of a single dimensional SDS primitive item array of a specified number of elements.
Definition sds.hh:2550
void ArrayAccess(ArrayAccessHelper< T > *const data) const
Access the data of a single dimensional SDS primitive array item of a specified number of elements.
Definition sds.hh:2506
static Id CreateArgCmdStruct(const ContainerType &values, const std::string &name="ArgStructure")
Factory constructor which creates a new "Arg" style SDS structure in the DRAMA Command style.
Definition sds.hh:2754
virtual void List(const PrintObjectCR &printer, int lineMaxLen=100) const
List the contents of the structure via a PrintObjectCR.
virtual void SetDelete()
Indicate the underlying SDS structure should be deleted when the sds::Id object is destroyed.
Definition sds.hh:1306
virtual Id Find(const std::string &name, bool throwOnNotFound=true) const
Factory constructor method Constructor which returns a reference to a named item.
static Id CreateByAccess(ContainerType *container)
Factory constructor method that accesses an exported SDS structure found in a byte stream.
Definition sds.hh:780
virtual unsigned long SizeDefined() const
Return the size of an SDS structure, as required for exporting when fully defined.
Definition sds.hh:2085
virtual void Write(const std::string &filename) const
Write the contents of the structure to a file.
Definition sds.hh:2191
virtual void Rename(const std::string &name)
Rename the SDS item.
Definition sds.hh:1990
virtual void List() const
List the contents of the structure to standard output.
Definition sds.hh:2099
void Put(const std::string &name, const std::string &value, const std::string &extraData="")
Insert a string value into a named component of the structure.
Definition sds.hh:3002
static Id CreateFromSdsId(SdsId *item)
Factory constructor method that constructs an sds::Id item from an existing old C++ interface SdsId i...
virtual unsigned int GetUInt() const
If the SDS item refers to a scalar value, convert it to an unsigned integer.
void Put(T value)
Insert a primitive value into the item.
Definition sds.hh:3075
Id & operator=(const Id &rhs)=delete
Assignment operator - deleted.
virtual double GetDouble() const
If the SDS item refers to a scalar value, convert it to a double item.
void Insert(Id &to_insert, const ContainerType &dims)
Insert an SDS object into this object, which is a structured array.
Definition sds.hh:1792
Id Cell(const ContainerType &indicies, bool throwOnNotFound=true) const
Factory constructor method Constructor that returns a cell of an existing id which must refer to an S...
Definition sds.hh:1162
virtual void ToSdsId(::SdsId *target, const bool outlives=false)
Shallow copy to an SdsId type.
Definition sds.hh:2448
static Id CreateByImport(const ContainerType &container)
Factory constructor method that imports an exported SDS structure found in a byte stream.
Definition sds.hh:830
virtual void List(FILE *to) const
List the contents of the structure to a C file.
Definition sds.hh:2111
virtual void ValidateCode(SdsCodeType requiredCode) const
Validate the code of the SDS item.
Definition sds.hh:1663
void ExportDefined(ContainerType *container) const
Export the SDS structure into a buffer, defining any undefined data.
Definition sds.hh:1449
void Export(ContainerType *container) const
Export the SDS structure into a buffer.
Definition sds.hh:1402
void Pointer(T **data, unsigned long *length=0) const
Obtain a pointer to the data area of a primitive SDS item.
Definition sds.hh:1886
virtual SdsCodeType GetCode() const
Return the code of the SDS item.
Definition sds.hh:1641
void ArrayAccess(ArrayAccessHelper< T > *const data, ContainerType *dims) const
Access the data of an SDS primitive item array.
Definition sds.hh:2687
static Id CreateTopLevelArray(const std::string &name, const SdsCodeType code, const unsigned nElem, const std::string &extra="")
Factory constructor method Constructor which creates a new one-dimensional array top-level item.
Definition sds.hh:1101
virtual void List(std::ostream &strm, int lineMaxLen=100) const
List the contents of the structure to an output stream.
Id(const Id &source)=delete
Copy constructor - deleted.
virtual void ShallowCopy(const SdsIdType source, const bool free=false, const bool del=false, const bool readfree=false)
Shallow copy from SdsIdType.
Definition sds.hh:2428
virtual void Delete()
Delete the SDS item.
Definition sds.hh:1355
static Id CreateFromSdsId(const SdsId &item)
Factory constructor method that constructs an sds::Id item from an existing old C++ interface SdsId i...
void GetDims(ContainerType *dims) const
Return the dimensions of the SDS item.
Definition sds.hh:1705
virtual ~Id()
sds::Id Destructor.
Definition sds.hh:1289
virtual void FillArray(const Id &elem)
Fill out the contents of this object, which is a structured array.
Definition sds.hh:1840
virtual SdsIdType COut(const bool outlives, bool *const free=0, bool *const del=0, bool *const readfree=0)
Return this item as an SdsIdType for return to C code.
Definition sds.hh:2323
void ArrayAccess(ArrayAccessHelper< T > *const data, long ndims, ContainerType *dims) const
Access the data of an SDS primitive item array.
Definition sds.hh:2609
virtual void Insert(Id &to_insert)
Insert an SDS object into this object.
Definition sds.hh:1756
virtual Id Index(const long index, bool throwOnNotFound=true) const
Factory constructor method Constructor which returns an id to a structured item indexed by position...
virtual unsigned long Size() const
Return the size of an SDS structure, as required for exporting.
Definition sds.hh:2063
void Get(const unsigned long length, T *const data, unsigned long *actlen=nullptr, const unsigned long offset=0) const
Get data from an SDS item.
Definition sds.hh:1547
static Id CreateArgCmdStructSingle(const T value, const std::string &name="ArgStructure")
Factory constructor which creates a new "Arg" style SDS structure in the DRAMA Command style.
Definition sds.hh:2846
void Put(const std::string &value)
Insert a string value into the component.
Definition sds.hh:3097
virtual void Extract()
Extract the SDS structure from its parent.
Definition sds.hh:1483
virtual void PutExtra(const std::string &extra)
Put extra data into an SDS item.
Definition sds.hh:1975
virtual void List(PrintObjectPnt *printer, int lineMaxLen=100) const
List the contents of the structure via a PrintObjectPnt object.
static Id CreateTopLevel(const std::string &name, const SdsCodeType code, const std::string &extra="")
Constructor which creates a new (non-array) top-level item.
virtual Id Copy() const
Factory constructor method Id Copy constructor.
void AddToArgCmdStruct(const ContainerType &values, const unsigned firstArg=1)
Insert a set of values from a container into an SDS structure in in the DRAMA Command style.
Definition sds.hh:2886
static Id CreateFromSdsIdType(const SdsIdType item, const bool free=false, const bool del=false, const bool readfree=false)
Factory constructor method that constructs an sds::Id item from an existing C language SDS id.
virtual void ShallowCopy(Id *source, const bool outlives)
Shallow copy from sds::Id.
Definition sds.hh:2383
void Put(const unsigned long length, const T *const data, const unsigned long offset=0)
Put data into an SDS item.
Definition sds.hh:1942
virtual void Flush()
Flush data modified by pointer.
Definition sds.hh:1509
static Id CreateArgStruct(const std::string &name="ArgStructure")
Factory constructor which creates a new "Arg" style SDS structure.
void Get(T *value) const
Fetch primitive value from the component.
Definition sds.hh:3119
static Id CreateArgCmdStruct(const std::initializer_list< T > &values, const std::string &name="ArgStructure")
Factory constructor which creates a new "Arg" style SDS structure in the DRAMA Command style.
Definition sds.hh:2810
virtual int GetInt() const
If the SDS item refers to a scalar value, convert it to an integer.
Id()
Default constructor.
Definition sds.hh:611
Id(Id &&source) noexcept
Move copy constructor.
Definition sds.hh:600
Id CreateChildArray(const std::string &name, const SdsCodeType code, const ContainerType &dims, const std::string &extra="") const
Factory constructor method Constructor which creates a new child item which is an multi-dimensional a...
Definition sds.hh:940
std::string GetString() const
If the SDS item refers to a scalar value or a character string, convert it to a string item.
virtual void ShallowCopy(const Id &source)
Shallow copy from a const sds::Id which will outlive this object.
Definition sds.hh:2354
static Id CreateTopLevelArray(const std::string &name, const SdsCodeType code, const ContainerType &dims, const std::string &extra="")
Factory constructor method Constructor which creates a new array top-level item.
Definition sds.hh:1043
void Put(const std::string &name, T value, const std::string &extraData="")
Insert a primitive value into a named component of the structure.
Definition sds.hh:2969
static Id CreateFromSdsIdTypeCopy(const SdsIdType item)
Factory constructor method that constructs an sds::Id item by coping an existing C language SDS id.
static Id CreateNullItem()
Factory constructor method that constructs an null sds::Id item .
virtual bool IsExternal() const
Determine if the SDS structure is external.
Definition sds.hh:2211
virtual std::string toString(int maxlen=200)
Convert the structure to a string.
Definition sds.hh:2918
virtual bool Exists(const std::string &name) const
Determine if a named item exists in a structure.
A C++ Interface to the handling SDS structures.
Definition sds.hh:428
virtual void Print(const std::string &line) const =0
Method invoked to print one line of an SDS listing.
Abstract class which is sub-classed to print SDS item listings.
Definition sds.hh:310
virtual void Print(const std::string &line)=0
Method invoked to print one line of an SDS listing.
Abstract class which is sub-classed to print SDS item listings.
Definition sds.hh:295
#define DramaTHROW_S(status_, format_,...)
Throw a Drama exception with safe string formatting.
Definition exception.hh:110
#define DramaTHROW(status_, message_)
Throw a Drama exception.
Definition exception.hh:93
DRAMA 2 Exception classes.
std::shared_ptr< Id > IdPtr
A shared pointer for sds::Id items.
Definition sds.hh:3318
void CreateRunDramaTask()
Create and run a DRAMA task, with standard exception handling.
Definition task.hh:1322
void CheckLockTaken(const std::string func, const std::string &file, const int lineNum)
Ensure the current thread has taken the DRAMA task lock.
The drama namespace contains all the classes, types etc of the DRAMA 2 implementation.
Definition drama.hh:93
DRAMA 2 include file - drama::sds::ArrayAccessHelper Sds class definitions.