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
759 */
760 static_assert(
761 std::is_standard_layout<typename ContainerType::value_type>::value,
762 "The value type in the container must be a standard layout type");
763
764 if (container->empty())
765 {
767 "Attempt to access data in empty container");
768 }
769 Id item(0, true, false, false); /* Must free-ed when done */
771 SdsAccess(&(*container)[0],&item._id,&status);
772 if (status != STATUS__OK)
773 DramaTHROW(status, "Failed to access SDS Item");
774
775 return item;
776 }
800 template <class ContainerType>
802 /*
803 * Confirm the container is a container of POD types.
804 * From C++20, std::is_pod<>() is depreciated, we can replace
805 * by std::is_standard_layout<>::value
806 */
807 static_assert(
808 std::is_standard_layout<typename ContainerType::value_type>::value,
809 "The value type in the container must be a standard layout type");
810
811
812 if (container.empty())
813 {
815 "Attempt to access data in empty container");
816 }
817
818
819 Id item(0, true, true, false); /* Must deleted and free-ed when done */
821 SdsImport(&container[0],&item._id,&status);
822 if (status != STATUS__OK)
823 DramaTHROW(status, "Failed to import SDS Item");
824
825 return item;
826 }
827
843 static Id FromFile(const std::string &filename);
862 virtual Id CreateChildItem(
863 const std::string &name,
864 const SdsCodeType code,
865 const std::string &extra = "") const;
866
880 static Id CreateTopLevel(
881 const std::string &name,
882 const SdsCodeType code,
883 const std::string &extra = "");
884
915 template <class ContainerType>
917 const std::string &name,
918 const SdsCodeType code,
919 const ContainerType& dims,
920 const std::string &extra = "") const {
921
922 Id item(0,true, false, false);
924
925 /*
926 * "dims" can be any container that
927 * 1. Has a size method.
928 * 2. Can be used to initialize a std::vector of unsigned long.
929 * 3. And it is validated for a 0 < size <= 7.
930 */
931 if ((dims.size() < 1)||(dims.size() > SDS__MAXDIMS))
932 {
934 "Failed to create new SDS array - % dimensions, minimum supported 1, maximum supported is %",
935 dims.size(),
937 }
938 /*
939 * We need to pass an array of unsigned long to SdsNew for
940 * the dimensions. The best approach is to create a vector
941 * of unsigned long and initialize it with the contents of
942 * our passed in container.
943 */
944 std::vector<unsigned long> myDims(dims);
945
946 SdsNew(_id,name.c_str(),extra.size(),extra.data(),code,
947 myDims.size(), myDims.data(),&item._id,&status);
948 if (status != STATUS__OK)
949 DramaTHROW_S(status, "Failed to create new SDS array top-level item %",name);
950 return item;
951 }
952
983 const std::string &name,
984 const SdsCodeType code,
985 const unsigned nElem,
986 const std::string &extra = "") const {
987
988 Id item(0,true, false, false);
990
991 /*
992 * This is a simplification of the above multi-dimensional
993 * version.
994 */
995 unsigned long dims[1];
996 dims[0] = nElem;
997 SdsNew(_id,name.c_str(),extra.size(),extra.data(),code,
998 1, dims, &item._id,&status);
999 if (status != STATUS__OK)
1000 DramaTHROW_S(status, "Failed to create new SDS array top-level item %",name);
1001 return item;
1002 }
1003
1004
1005
1032 template <class ContainerType>
1033 static Id CreateTopLevelArray(
1034 const std::string & name,
1035 const SdsCodeType code,
1036 const ContainerType& dims,
1037 const std::string &extra = ""){
1038
1039 Id item(0,true, true, false);
1041
1042 /*
1043 * "dims" can be any container that
1044 * 1. Has a size method.
1045 * 2. Can be used to initialize a std::vector of unsigned long.
1046 * 3. And it is validated for a 0 < size <= 7.
1047 */
1048 if ((dims.size() < 1)||(dims.size() > SDS__MAXDIMS))
1049 {
1051 "Failed to create new SDS array - % dimensions, minimum supported 1, maximum supported is %",
1052 dims.size(),
1054 }
1055 /*
1056 * We need to pass an array of unsigned long to SdsNew for
1057 * the dimensions. The best approach is to create a vector
1058 * of unsigned long and initialize it with the contents of
1059 * our passed in container.
1061 std::vector<unsigned long> myDims(dims);
1062
1063
1064 SdsNew(0,name.c_str(),extra.size(),extra.data(),code,
1065 myDims.size(), myDims.data(),&item._id,&status);
1066 if (status != STATUS__OK)
1067 DramaTHROW_S(status, "Failed to create new SDS array top-level item %",name);
1068
1069 return item;
1070 }
1071
1097 static Id CreateTopLevelArray(
1098 const std::string & name,
1099 const SdsCodeType code,
1100 const unsigned nElem,
1101 const std::string &extra = ""){
1102
1103 Id item(0,true, true, false);
1105
1106 /*
1107 * This is a simplification of the above multi-dimensional
1108 * version.
1109 */
1110 unsigned long dims[1];
1111 dims[0] = nElem;
1112
1113
1114 SdsNew(0,name.c_str(),extra.size(),extra.data(),code,
1115 1, dims,&item._id,&status);
1116 if (status != STATUS__OK)
1117 DramaTHROW_S(status, "Failed to create new SDS array top-level item %",name);
1118
1119 return item;
1120 }
1121
1122
1123
1157 template <class ContainerType>
1159 bool throwOnNotFound=true) const {
1160 Id item(0, true, false, false);
1161
1162 /*
1163 * "dims" can be any container that
1164 * 1. Has a size method.
1165 * 2. Can be used to initialize a std::vector of unsigned long.
1166 * 3. And it is validated for a 0 < size <= 7.
1167 */
1168 if ((indicies.size() < 1)||(indicies.size() > SDS__MAXDIMS))
1169 {
1171 "Failed to access SDS array cell - % dimensions, minimum supported 1, maximum supported is %",
1172 indicies.size(),
1174 }
1175 /*
1176 * We need to pass an array of unsigned long to SdsCell for
1177 * the dimensions. The best approach is to create a vector
1178 * of unsigned long and initialize it with the contents of
1179 * our passed in container.
1180 */
1181 std::vector<unsigned long> myDims(indicies);
1182
1183
1185 SdsCell(_id, myDims.size(), myDims.data(), &item._id, &status);
1186
1187 /* Special case of item not found and don't want to throw, return null id */
1189 {
1190 item._flags.del = false;
1191 return item;
1192 }
1193
1194 if (status != STATUS__OK)
1196 "Failed to access cell of existing SDS array id");
1197 return item;
1198 }
1214 virtual Id Copy() const;
1215
1237 virtual Id Find(const std::string &name,
1238 bool throwOnNotFound=true) const;
1239
1267 virtual Id Index(const long index, bool throwOnNotFound=true) const;
1268
1285 virtual ~Id() {
1286 /*Just invoke the private cleanup routine */
1287 CleanUp("sds::Id destructor");
1288 }
1289 /* Modify flags */
1290
1296 virtual void SetFree() { _flags.free = true; }
1302 virtual void SetDelete() { _flags.del = true; }
1303
1312 virtual void ClearDelete() { _flags.del = false; }
1313
1323 virtual void Outlive() {
1324 _flags.free = false;
1325 _flags.del = false;
1326 _flags.readfree = false;
1327 }
1328
1330 * General operations, as per similar SDS operations.
1331 * Currently only Delete, Get and Put are virtual.
1332 */
1333
1351 virtual void Delete() {
1353 SdsDelete(_id,&status);
1354 if (status == STATUS__OK)
1355 {
1356 _flags.del = false;
1357 if (_flags.free)
1358 {
1359 SdsFreeId(_id, &status);
1360 if (status == STATUS__OK)
1361 {
1362 _id = 0;
1363 _flags.free = false;
1364 }
1365 }
1366 }
1367 else
1368 DramaTHROW(status, "Failed to delete SDS item");
1369 }
1370
1371
1380 virtual void DeleteIfExists(const std::string &name) {
1381
1382 if (!Exists(name)) return;
1383
1384 auto itemId = Find(name);
1385 itemId.Delete();
1386 }
1387
1415 template <class ContainerType>
1416 void Export(ContainerType *container) const {
1418
1419 /*
1420 * Confirm the container is a container of POD types.
1421 * From C++20, std::is_pod<>() is depreciated, we can replace
1422 * by std::is_standard_layout<>::value
1423 */
1424 static_assert(
1425 std::is_standard_layout<typename ContainerType::value_type>::value,
1426 "The value type in the container must be a standard layout type");
1427
1428
1429 // Must multiple container size() in units by size of each unit.
1430 SdsExport(_id,
1431 (container->size()*sizeof((*container)[0])),
1432 &(*container)[0],&status);
1433 if (status != STATUS__OK)
1434 DramaTHROW(status, "Failed to export SDS item");
1435
1436 }
1461 template <class ContainerType>
1463 /*
1464 * Confirm the container is a container of POD types.
1465 * From C++20, std::is_pod<>() is depreciated, we can replace
1466 * by std::is_standard_layout<>::value
1467 */
1468 static_assert(
1469 std::is_standard_layout<typename ContainerType::value_type>::value ,
1470 "The value type in the container must be a standard layout type");
1471
1473 SdsExportDefined(_id,container->size(),&(*container)[0],&status);
1474 if (status != STATUS__OK)
1475 DramaTHROW(status, "Failed to export defined SDS item");
1476 }
1495 virtual void Extract() {
1497 SdsExtract(_id,&status);
1498 if (status != STATUS__OK)
1499 DramaTHROW(status, "Failed to extract SDS item");
1500
1501 /*
1502 * We need to modify the flags to those appropriate for
1503 * and indepent toplevel item
1504 */
1505 _flags.free = true;
1506 _flags.del = true;
1507 _flags.readfree = false;
1508 }
1521 virtual void Flush() {
1523
1524 //fprintf(stderr,"FLUSH:ID=%d\n", (int)(_id));
1525
1526
1527 SdsFlush(_id,&status);
1528 if (status != STATUS__OK)
1529 DramaTHROW(status, "Failed to flush SDS item");
1530 }
1558 template <typename T>
1559 void Get(const unsigned long length,
1560 T * const data,
1561 unsigned long *actlen = nullptr,
1562 const unsigned long offset=0) const {
1563
1564 /*
1565 * Confirm the data type is a POD type.
1566 * From C++20, std::is_pod<>() is depreciated, we can replace
1567 * by std::is_standard_layout<>::value.
1568 */
1569 static_assert(
1570 std::is_standard_layout<T>::value,
1571 "The type T must be a standard layout type");
1572
1573 unsigned long myactlen;
1574 if (!actlen) actlen = &myactlen;
1576 SdsGet(_id,length,offset,(void *)data,actlen,&status);
1577
1578 if (status != STATUS__OK)
1579 DramaTHROW(status, "Failed to Get data from SDS item");
1580 }
1593 virtual std::string GetExtra() const {
1594
1595 unsigned long length = 0;
1597 SdsGetExtraLen(_id, &length, &status);
1598 if ((status == STATUS__OK)&&(length == 0))
1599 return "";
1600 /*
1601 * Allocate some space to store the extra data in.
1602 */
1603 std::unique_ptr<char[]> extraData(new char[length+1]);
1604
1605 unsigned long actlen;
1606 /*
1607 * Get the data.
1608 */
1610 if (status != STATUS__OK)
1612 "Failed to Get extra data from SDS item");
1613 extraData[length] = 0; // Ensure null termination.
1614 return &extraData[0];
1615 }
1625 virtual std::string GetName() const {
1626
1627 char tName[SDS_C_NAMELEN];
1629 SdsGetName(_id,tName,&status);
1630
1631 if (status != STATUS__OK)
1633 "Failed to Get Name of SDS item");
1634 return tName;
1635
1636
1637 }
1652 virtual SdsCodeType GetCode() const {
1653 SdsCodeType code;
1655 SdsGetCode(_id,&code,&status);
1656 if (status != STATUS__OK)
1657 DramaTHROW(status, "Failed to Get code of SDS item");
1658
1659 return code;
1660
1661 }
1674 virtual void ValidateCode(SdsCodeType requiredCode) const {
1678 if (status != STATUS__OK)
1680 DramaTHROW(status, "Failed to Get code of SDS item");
1681 }
1682
1683 if (actualCode != requiredCode)
1684 {
1686 "SDS Item % has code %, was expected to have code %",
1687 GetName(),
1690 }
1691
1692 }
1693
1715 template <class ContainerType>
1716 void GetDims(ContainerType *dims) const {
1717
1718 unsigned long tdims[SDS_C_MAXARRAYDIMS];
1719 long ndims;
1722 if (status != STATUS__OK)
1724 "Failed to Get dimensions of SDS item");
1725
1726 /*
1727 * Copy dims to output location.
1728 */
1729 dims->clear();
1730 for (int i = 0; i < (int)(ndims) ; ++i)
1731 {
1732 dims->push_back(tdims[i]);
1733 }
1734
1735 }
1745 unsigned GetNumItems() const {
1746
1747 long numItems = 0;
1749 SdsNumItems(_id, &numItems, &status);
1750 if (status != STATUS__OK)
1752 "Failed to Get number of SDS items");
1753
1754 return numItems;
1755 }
1756
1757
1767 virtual void Insert(Id & to_insert) {
1769 SdsInsert(_id,to_insert._id,&status);
1770 if (status != STATUS__OK)
1771 DramaTHROW(status, "Failed to insert SDS item.");
1773
1774
1775 /*
1776 * If we succeed, the new child should not be deleted when
1777 * it's id is destroyed, so clear the flag. (This is why
1778 * we break Tony's normal rule of not using non-const
1779 * references.
1780 */
1781 to_insert._flags.del = false;
1782 }
1802 template <class ContainerType>
1803 void Insert(Id & to_insert,
1804 const ContainerType& dims) {
1805
1807 /*
1808 * "dims" can be any container that
1809 * 1. Has a size method.
1810 * 2. Can be used to initialize a std::vector of unsigned long.
1811 * 3. And it is validated for a 0 < size <= 7.
1812 */
1813 if ((dims.size() < 1)||(dims.size() > SDS__MAXDIMS))
1814 {
1816 "Failed to create new SDS array - % dimensions, minimum supported 1, maximum supported is %",
1817 dims.size(),
1819 }
1820
1821 /*
1822 * We need to pass an array of unsigned long to SdsNew for
1823 * the dimensions. The best approach is to create a vector
1824 * of unsigned long and initialize it with the contents of
1825 * our passed in container.
1826 */
1827 std::vector<unsigned long> myDims(dims);
1828
1829
1830 SdsInsertCell(_id,myDims.size(),myDims.data(),to_insert._id,&status);
1831
1832 if (status != STATUS__OK)
1833 DramaTHROW(status, "Failed to insert item into array cell");
1834 /*
1835 * If we succeed, the new child should not be deleted when
1836 * it's id is destroyed, so clear the flag
1837 */
1838 to_insert._flags.del = false;
1839 }
1840
1851 virtual void FillArray(const Id &elem) {
1853 SdsFillArray(_id,elem._id,&status);
1854 if (status != STATUS__OK)
1855 DramaTHROW(status, "Failed to fill structure");
1856 }
1857
1896 template <typename T>
1897 void Pointer(T **data, unsigned long * length=0) const {
1898
1899
1900 /*
1901 * Confirm the data type is a POD type.
1902 * From C++20, std::is_pod<>() is depreciated, we can replace
1903 * by std::is_standard_layout<>::value
1904 */
1905 static_assert(
1906 std::is_standard_layout<T>::value,
1907 "The type T must be a standard layout and type");
1908
1909
1910 unsigned long mylength;
1912
1913 if (!length) length = &mylength;
1914
1915 void *tdata;
1916
1918 if (status != STATUS__OK)
1919 DramaTHROW(status, "Failed to get pointer to data.");
1920
1921 *data = static_cast<T *>(tdata);
1922
1923 /* fprintf(stderr,"Pointer:ID=%d, pointer=%p\n",
1924 (int)(_id), (void *)(tdata));
1925 */
1926 }
1927
1952 template <typename T>
1953 void Put(const unsigned long length,
1954 const T * const data,
1955 const unsigned long offset=0) {
1957 /*
1958 * Confirm the data type is a POD type.
1959 * From C++20, std::is_pod<>() is depreciated, we can replace
1960 * by std::is_standard_layout<>::value
1961 */
1962 static_assert(
1963 std::is_standard_layout<T>::value,
1964 "The type T must be a standard layout type");
1965
1966 const void *tdata = static_cast<const void *>(data);
1967
1969 if (status != STATUS__OK)
1970 DramaTHROW(status, "Failed to put data into SDS.");
1971
1972
1973 }
1974
1986 virtual void PutExtra(const std::string &extra) {
1987
1989 SdsPutExtra(_id,extra.size(),extra.data(),&status);
1990 if (status != STATUS__OK)
1991 DramaTHROW(status, "Failed to put extra data into SDS.");
1992 }
2001 virtual void Rename(const std::string &name) {
2003 SdsRename(_id,name.c_str(),&status);
2004 if (status != STATUS__OK)
2005 DramaTHROW(status, "Failed to rename SDS item..");
2006
2007 }
2034 template <class ContainerType>
2035 void Resize(const ContainerType& dims) {
2036
2037
2039 /*
2040 * "dims" can be any container that
2041 * 1. Has a size method.
2042 * 2. Can be used to initialize a std::vector of unsigned long.
2043 * 3. And it is validated for a 0 < size <= 7.
2044 */
2045 if ((dims.size() < 1)||(dims.size() > SDS__MAXDIMS))
2046 {
2048 "Failed to create new SDS array - % dimensions, minimum supported 1, maximum supported is %",
2049 dims.size(),
2051 }
2052
2053 /*
2054 * We need to pass an array of unsigned long to SdsResize for
2055 * the dimensions. The best approach is to create a vector
2056 * of unsigned long and initialize it with the contents of
2057 * our passed in container.
2058 */
2059 std::vector<unsigned long> myDims(dims);
2060
2061 SdsResize(_id,myDims.size(),myDims.data(),&status);
2063 if (status != STATUS__OK)
2064 DramaTHROW(status, "Failed to resize SDS array");
2065
2066 }
2074 virtual unsigned long Size() const {
2075 unsigned long bytes;
2077 SdsSize(_id,&bytes,&status);
2078 if (status != STATUS__OK)
2079 DramaTHROW(status, "Failed to return size of SDS structure");
2080 return bytes;
2081
2082 }
2096 virtual unsigned long SizeDefined() const {
2097 unsigned long bytes;
2100 if (status != STATUS__OK)
2101 DramaTHROW(status, "Failed to return size of SDS structure");
2102 return bytes;
2103
2104 }
2105
2110 virtual void List() const {
2112 SdsList(_id,&status);
2113
2114 if (status != STATUS__OK)
2115 DramaTHROW(status, "Failed to list SDS structure");
2116 }
2122 virtual void List(FILE *to) const {
2124 SdsListTo(to, _id,&status);
2125
2126 if (status != STATUS__OK)
2127 DramaTHROW(status,"Failed to list SDS structure");
2128 }
2140 virtual void List(std::ostream &strm,
2141 int lineMaxLen=100) const;
2142
2165 virtual void List(PrintObjectPnt *printer, int lineMaxLen=100) const;
2166
2189 virtual void List(const PrintObjectCR
2190 &printer, int lineMaxLen=100) const;
2191
2202 virtual void Write(const std::string &filename) const {
2204 SdsWrite(_id,filename.c_str(),&status);
2205 if (status != STATUS__OK)
2207 "Failed to write SDS structure to file \"%\"",
2208 filename);
2209
2210 }
2211
2222 virtual bool IsExternal() const {
2224 int external = 0;
2225 SdsIsExternal(_id, &external, &status);
2226 if (status != STATUS__OK)
2227 DramaTHROW(status, "Failed to determine if SDS is external");
2228
2229 return external;
2230 }
2231 /* Return the address of an external item.
2232 *
2233 * This method is used to determine the address of the buffer
2234 * containing an external item, if this item refers to an external
2235 * item. This is the value given the contructor which accessed this
2236 * item.
2237 *
2238 * @returns The address of the external item data buffer.
2239 */
2240#if 0 // SdsGetExternInfo() does not actually exist - not sure what happened
2241 virtual void *GetExternInfo() const {
2242 void *data;
2244 SdsGetExternInfo(_id, &data, &status);
2245 if (status != STATUS__OK)
2247 "Failed to get SDS external structure address");
2248
2250 return data;
2251 }
2252#endif
2253
2254
2268 virtual bool Exists(const std::string &name) const;
2282 virtual bool Exists(unsigned index) const;
2283
2284
2296 explicit operator SdsIdType() const { return _id; }
2297
2303 explicit operator bool() const {
2304 return (_id != 0);
2305 }
2306
2334 virtual SdsIdType COut(const bool outlives, bool * const free = 0,
2335 bool * const del= 0, bool * const readfree = 0) {
2336 if (free)
2337 *free = _flags.free;
2338 if (del)
2339 *del = _flags.del;
2340 if (readfree)
2341 *readfree = _flags.readfree;
2342 if (outlives)
2343 _flags.free = _flags.del = _flags.readfree = false;
2344 return (_id);
2345 }
2365 virtual void ShallowCopy (const Id & source) {
2366 if (this != &source)
2367 {
2368 CleanUp("sds::Id::ShallowCopy 1"); /* Run destructor on old id */
2369 _id = source._id;
2370 _flags.free = _flags.del = _flags.readfree = false;
2371 }
2372 }
2373
2374
2394 virtual void ShallowCopy (Id * source, const bool outlives) {
2395 if (this != source)
2396 {
2397 CleanUp("sds::Id::ShallowCopy 2"); /* Run destructor on old id */
2398 _id = source->_id;
2399 if (outlives)
2400 {
2401 /* If we will outlive the source, then we copy the source's
2402 * flags and set the sources flags to false.
2403 */
2404
2405 _flags.free = source->_flags.free;
2406 _flags.del = source->_flags.del;
2407 _flags.readfree = source->_flags.readfree;
2408
2409 source->_flags.free = source->_flags.del =
2410 source->_flags.readfree = false;
2411 }
2412 else
2413 {
2414 _flags.free = _flags.del = _flags.readfree = false;
2415 }
2416 }
2417 }
2418
2419
2439 virtual void ShallowCopy (const SdsIdType source, const bool free=false,
2440 const bool del = false, const bool readfree = false) {
2441 CleanUp("sds::Id::ShallowCopy 3"); /* Run destructor on old id */
2442 _flags.free = free;
2443 _flags.del = del;
2444 _flags.readfree = readfree;
2445 _id = source;
2446 }
2447
2459 virtual void ToSdsId(::SdsId *target, const bool outlives= false) {
2460 if (outlives)
2461 {
2462 /*
2463 * If the target outlives the source, then copy the
2464 * flags and then clear the close versions.
2465 */
2466 target->ShallowCopy(_id, _flags.free,
2467 _flags.del, _flags.readfree);
2468 _flags.free = false;
2469 _flags.del = false;
2470 _flags.readfree = false;
2471 }
2472 else
2473 {
2474 /*
2475 * Otherwise the defaults will do.
2476 */
2477 target->ShallowCopy(_id);
2478 }
2479 }
2480
2517 template <typename T> void ArrayAccess(
2518 ArrayAccessHelper<T> * const data) const {
2519
2520 unsigned long dims[SDS_C_MAXARRAYDIMS];
2521 CheckArrayTypeSingleDim(data->Code(), dims);
2522 data->SetNumElements(dims[0]);
2523 SetArrayHelperDataAddr(data);
2524 }
2561 template <typename T> void ArrayAccess(
2562 const unsigned long nitems,
2563 sds::ArrayAccessHelper<T> * const data) const {
2564
2565 unsigned long dims[SDS_C_MAXARRAYDIMS];
2566 CheckArrayTypeSingleDim(data->Code(), dims);
2567 if (dims[0] != nitems)
2568 {
2570 "ArrayAccess expected % items, found %",
2571 nitems, dims[0]);
2572 }
2573 data->SetNumElements(dims[0]);
2574 SetArrayHelperDataAddr(data);
2575 }
2620 template <typename T, class ContainerType> void ArrayAccess(
2621 ArrayAccessHelper<T> * const data,
2622 long ndims,
2623 ContainerType *dims) const {
2624
2625
2626
2627 if ((ndims < 1)||(ndims > SDS_C_MAXARRAYDIMS))
2628 {
2630 "Failed to access SDS array. Numbers of dimensions % invalid, must be in range 1 to %",
2632
2633 }
2634 CheckArrayType(data->Code(), ndims, dims);
2635
2636 /*
2637 * work out the number of elements
2638 */
2639 unsigned long elements = (*dims)[0];
2640 for (unsigned long i = 1; i < dims->size() ; ++i)
2641 {
2642 elements *= (long)((*dims)[i]);
2643 }
2644 data->SetNumElements(elements);
2645 /*
2646 * Access the data.
2648 SetArrayHelperDataAddr(data);
2649 }
2650
2651
2697 template <typename T, class ContainerType> void ArrayAccess(
2698 ArrayAccessHelper<T> * const data,
2699 ContainerType *dims ) const {
2700
2701 /*
2702 * A bit of a pain, we need to call Dims to get the number
2703 * of dimensions.
2704 */
2705 GetDims(dims);
2706 /*
2707 * The use the above version where we know the number of dimensions
2708 */
2709 ArrayAccess(data, dims->size(), dims);
2710 }
2711 /*** Array creation and access in one operation */
2712
2755 template <typename T> Id ArrayCreateAndAccess(
2756 const std::string &name,
2757 const unsigned nitems,
2758 sds::ArrayWriteHelper<T> * const data,
2759 const std::string & extra = "") {
2760
2761 auto arrayId = CreateChildArray(name, data->Code(), nitems, extra);
2762
2763 data->SetNumElements(nitems);
2764 arrayId.SetArrayHelperDataAddr(data);
2765 return arrayId;
2766 }
2820 template <typename T, class ContainerType> Id ArrayCreateAndAccess(
2821 const std::string &name,
2822 const ContainerType &dims,
2823 sds::ArrayWriteHelper<T> * const data,
2824 const std::string & extra = "") {
2825
2826 auto arrayId = CreateChildArray(name, data->Code(), dims, extra);
2827
2828 /* We need the number of elements (items) in the SDS
2829 * array we have just created
2830 */
2831 unsigned long elements = dims[0];
2832 for (unsigned long i = 1; i < dims.size() ; ++i)
2833 {
2834 elements *= (long)(dims[i]);
2835 }
2836 /* now we can set things up */
2837 data->SetNumElements(elements);
2838 arrayId.SetArrayHelperDataAddr(data);
2839 return arrayId;
2840 }
2841
2842 /*** ARG style methods ***/
2843
2858 static Id CreateArgStruct(const std::string &name = "ArgStructure");
2859
2892 template <typename ContainerType>
2893 static Id CreateArgCmdStruct(
2894 const ContainerType &values,
2895 const std::string &name="ArgStructure") {
2896
2897
2898 Id item(CreateArgStruct(name));
2899
2900 std::string itemName = "Argument";
2901
2902 unsigned argNum = 1;
2903 for (auto s: values) {
2904
2905 std::string thisName = itemName + std::to_string(argNum);
2906
2907 item.Put(thisName,s);
2908
2909 ++argNum;
2910
2911 }
2912
2913 return item;
2914
2915 }
2948 template <typename T>
2949 static Id CreateArgCmdStruct(
2950 const std::initializer_list<T> &values,
2951 const std::string &name="ArgStructure") {
2952
2953 return CreateArgCmdStruct(std::vector<T>(values), name);
2954 }
2984 template <typename T>
2986 const T value,
2987 const std::string &name="ArgStructure") {
2988
2989
2990 Id item(CreateArgStruct(name));
2991 item.Put("Argument1",value);
2992 return item;
2993 }
2994
2995
3024 template <typename ContainerType>
3025 void AddToArgCmdStruct(
3026 const ContainerType &values,
3027 const unsigned firstArg = 1) {
3028
3029 std::string itemName = "Argument";
3030
3031 unsigned argNum = firstArg;
3032 if (argNum == 0) argNum = 1;
3033 for (auto s: values) {
3034
3035 std::string thisName = itemName + std::to_string(argNum);
3036
3037 Put(thisName,s);
3038
3039 ++argNum;
3040
3041 }
3042 }
3043
3044
3045
3057 virtual std::string toString(int maxlen = 200) {
3058
3059 /*
3060 * Allocate some space to store the string in.
3061 */
3062 //std::unique_ptr<char[]> string(new char[maxlen]);
3063 char *string = new char[maxlen];
3064 int length=0;
3066 /*
3067 * ArgToString() does the job for us.
3068 */
3069 ArgToString((SdsIdType)(*this),maxlen,&length,&string[0],&status);
3070 if (status != STATUS__OK)
3071 {
3072 delete[] string;
3073 DramaTHROW(status, "Failed to convert SDS to string");
3074 }
3075
3076 std::string result=&string[0];
3077
3078 return result;
3079 }
3107 template <typename T>
3108 void Put (const std::string &name, T value, const std::string &extraData="") {
3109
3110
3112 /* There must be a specialization of SdsArgPut() which
3113 supports type T. Note that conversion of DRAMA status
3114 to DRAMA 2 exceptions is done here so it need only be
3115 done once.
3116 */
3117 SdsArgPut(_id, name, value, &status);
3118 if (status != STATUS__OK)
3120 "ArgPut failed of item \"%\" failed",
3121 name);
3122 if (extraData != "")
3123 {
3124 auto itemId = Find(name);
3125 itemId.PutExtra(extraData);
3126 }
3127
3128 }
3129
3141 void Put (const std::string &name, const std::string &value,
3142 const std::string &extraData="") {
3143
3144
3146 ArgPutString(_id, name.c_str(), value.c_str(), &status);
3147 if (status != STATUS__OK)
3149 "ArgPut failed of item \"%\" failed",
3150 name);
3151 if (extraData != "")
3152 {
3153 auto itemId = Find(name);
3154 itemId.PutExtra(extraData);
3155 }
3156
3157 }
3177 template <typename T>
3178 void Get (const std::string &name, T *value) const {
3179
3180
3182 /* There must be a specialization of SdsArgGet() which
3183 supports type T. Note that conversion of DRAMA status
3184 to DRAMA 2 exceptions is done here so it need only be
3185 done once.
3186 */
3187 SdsArgGet(_id, name, value, &status);
3188 if (status != STATUS__OK)
3190 "ArgGet failed of item \"%\" failed",
3191 name);
3192
3193 }
3194
3195
3213 template <typename T>
3214 void Put (T value) {
3215
3216
3218 /* There must be a specialization of PutScalar() which
3219 supports type T. Note that conversion of DRAMA status
3220 to DRAMA 2 exceptions is done here so it need only be
3221 done once.
3222 */
3223 PutScalar(_id, value, &status);
3224 if (status != STATUS__OK)
3225 DramaTHROW(status, "PutScalar failed of item failed");
3226
3227 }
3228
3236 void Put (const std::string &value) {
3237
3238
3240 ArgCvt(value.c_str(),ARG_STRING,ARG_SDS,&_id,0,&status);
3242 if (status != STATUS__OK)
3243 DramaTHROW(status, "ArgCvt failed of item failed");
3244
3245 }
3257 template <typename T>
3258 void Get (T *value) const {
3259
3260
3262 /* There must be a specialization of GetScalar() which
3263 supports type T. Note that conversion of DRAMA status
3264 to DRAMA 2 exceptions is done here so it need only be
3265 done once.
3266 */
3267 GetScalar(_id, value, &status);
3268 if (status != STATUS__OK)
3269 DramaTHROW(status, "GetScalar failed of item failed");
3270
3271 }
3272
3273
3295 template <class ContainerType>
3296 void CheckItem(SdsCodeType code,
3297 const ContainerType& dims) const {
3298
3299
3301 /*
3302 * "dims" can be any container that
3303 * 1. Has a size method.
3304 * 2. Can be used to initialize a std::vector of unsigned long.
3305 * 3. And it is validated for a 0 <= size <= 7.
3306 * (Note - dims.size() is unsigned)
3307 */
3308 if (dims.size() > SDS__MAXDIMS)
3309 {
3311 "Failed to check SDS array - % dimensions, minimum supported 0, maximum supported is %",
3312 dims.size(),
3314 }
3315
3316 /*
3317 * We need to pass an array of unsigned long to ArgCheckItem for
3318 * the dimensions. The best approach is to create a vector
3319 * of unsigned long and initialize it with the contents of
3320 * our passed in container.
3321 */
3322 std::vector<long> myDims(dims);
3324 ArgCheckItem(_id,code, myDims.size(),myDims.data(),&status);
3325
3326 if (status != STATUS__OK)
3327 DramaTHROW(status, "Check of SDS item failed");
3328
3329 }
3335 virtual int GetInt() const;
3341 virtual unsigned int GetUInt() const;
3347 virtual long GetLong() const;
3348
3354 virtual unsigned long GetULong() const;
3360 virtual double GetDouble() const;
3361
3367 std::string GetString() const;
3369
3370
3371 /* Enable watching of this SDS id.
3372 *
3373 * Output will go to stderr and any older watch details
3374 * are lost
3375 */
3376 void SetWatch() {
3378 SdsSetWatch(_id, nullptr, nullptr,
3379 nullptr, nullptr, nullptr, &status);
3380 if (status != STATUS__OK)
3381 DramaTHROW(status, "SdsSetWatch failed");
3382 }
3383
3384 }; /* class Id */
3385
3395 private:
3396 SdsCheckType _chkData;
3397 int _line;
3398 std::string _file;
3399 std::string _function;
3400 public:
3421 IdChecker(int line, const char *file, const char *function)
3422 : _line(line), _file(file), _function(function) {
3424 SdsCheckInit(&_chkData, &ignore);
3425 }
3432 virtual ~IdChecker() {
3434 SdsCheck(0, &_chkData, &status);
3435 if (status == SDS__CHK_LEAK)
3436 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);
3437 else if (status == SDS__CHK_RELEASED)
3438 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);
3439 }
3440 };
3452#define SDS_CHECK_IDS2(function_) drama::sds:IdChecker _sds_id_checker(__LINE__, __FILE__, (function_))
3453
3454
3457 typedef std::shared_ptr<Id> IdPtr;
3458
3460
3461 /*
3462 * This structure is used to specify a deleter to unique_ptr in
3463 * the DataPointer class. It provides a null deleter operation as
3464 * SDS will handle tidying this up.
3465 */
3466 struct _nodel
3467 {
3468 void operator()(void *) const { }
3469 };
3470
3489 template <typename T>
3490 class DataPointer : public std::unique_ptr<T,_nodel> {
3491
3492 private:
3493 unsigned long _lengthBytes; // Length of item in bytes.
3494 drama::sds::Id _refId; // SDS Id.
3495 public:
3504
3505 /*
3506 * Confirm the data type is a POD type.
3507 * From C++20, std::is_pod<>() is depreciated, we can replace
3508 * by std::is_standard_layout<>::value
3509 */
3510 static_assert(
3511 std::is_standard_layout<T>::value,
3512 "The type T must be a standard layout and type");
3513
3514 T *dataPnt = 0;
3515 theId.Pointer(&dataPnt, &_lengthBytes);
3516
3517 if (_lengthBytes != sizeof(T))
3518 {
3520 "SDS Pointer error - expected % bytes, got %",
3521 sizeof(T), _lengthBytes);
3522
3523 }
3524
3525
3526 std::unique_ptr<T, _nodel> p(dataPnt, _nodel());
3527
3528 *((std::unique_ptr<T,_nodel>*)(this)) = std::move(p);
3529
3531
3532 }
3542
3543
3544 /*
3545 * Confirm the data type is a POD type.
3546 * From C++20, std::is_pod<>() is depreciated, we can replace
3547 * by std::is_standard_layout<>::value
3548 */
3549 static_assert(
3550 std::is_standard_layout<T>::value,
3551 "The type T must be a standard layout type");
3552
3553 T *dataPnt = 0;
3554 theId->Pointer(&dataPnt, &_lengthBytes);
3555
3556 if (_lengthBytes != sizeof(T))
3557 {
3559 "SDS Pointer error - expected % bytes, got %",
3560 sizeof(T), _lengthBytes);
3561
3562 }
3563
3564
3565 std::unique_ptr<T, _nodel> p(dataPnt, _nodel());
3566
3567 *((std::unique_ptr<T,_nodel>*)(this)) = std::move(p);
3569 _refId.ShallowCopy(theId, outlives);
3570
3571 }
3572
3573
3578 ~DataPointer() {
3579 try
3580 {
3581 _refId.Flush();
3582 }
3583 catch (...)
3584 {
3585 }
3586 }
3591 unsigned long NumBytes() const {
3592 return _lengthBytes;
3593 }
3594 }; // class DataPointer
3595
3615 template <typename T>
3616 class DataPointer<T[]> : public std::unique_ptr<T[], _nodel> {
3617
3618 private:
3619 unsigned long _numItems;
3620 unsigned long _lengthBytes;
3621 drama::sds::Id _refId;
3622 public:
3624 typedef T * iterator;
3626 typedef const T * const_iterator;
3628 typedef T value_type;
3629
3640
3641
3642 /*
3643 * Confirm the data type is a POD type.
3644 * From C++20, std::is_pod<>() is depreciated, we can replace
3645 * by std::is_standard_layout<>::value
3646 */
3647 static_assert(
3648 std::is_standard_layout<T>::value,
3649 "The type T must be a standard layout type");
3650
3651 T *dataPnt = 0;
3652 theId.Pointer(&dataPnt, &_lengthBytes);
3654 if (_lengthBytes < sizeof(T))
3657 "SDS Array Pointer error - expected at least % bytes, got %",
3658 sizeof(T), _lengthBytes);
3659
3660 }
3661
3662
3663 _numItems = _lengthBytes/sizeof(dataPnt[0]);
3664
3665
3666 std::unique_ptr<T[], _nodel> p(dataPnt, _nodel());
3667
3668 *((std::unique_ptr<T[],_nodel>*)(this)) = std::move(p);
3669
3670 _refId.ShallowCopy(theId);
3671
3672 }
3683
3684
3685 /*
3686 * Confirm the data type is a POD type.
3687 * From C++20, std::is_pod<>() is depreciated, we can replace
3688 * by std::is_standard_layout<>::value
3689 */
3690 static_assert(
3691 std::is_standard_layout<T>::value,
3692 "The type T must be a standard layout type");
3693
3694 T *dataPnt = 0;
3695 theId->Pointer(&dataPnt, &_lengthBytes);
3696
3697 if (_lengthBytes < sizeof(T))
3698 {
3700 "SDS Array Pointer error - expected at least % bytes, got %",
3701 sizeof(T), _lengthBytes);
3702
3703 }
3704
3705
3706 _numItems = _lengthBytes/sizeof(dataPnt[0]);
3707
3708
3709 std::unique_ptr<T[], _nodel> p(dataPnt, _nodel());
3710
3711 *((std::unique_ptr<T[],_nodel>*)(this)) = std::move(p);
3712
3713 _refId.ShallowCopy(theId, outlives);
3714
3715 }
3716
3721 ~DataPointer() {
3722 try
3723 {
3724 _refId.Flush();
3725 }
3726 catch (...)
3727 {
3728 }
3729 }
3734 unsigned long size() const {
3735 return _numItems;
3736 }
3741 unsigned long NumBytes() const {
3742 return _lengthBytes;
3743 }
3748 iterator begin() {
3749 return & (*this)[0];
3750 }
3755 iterator end() {
3756 return (&(*this)[0])+_numItems;
3757 }
3762 const_iterator begin() const {
3763 return & (*this)[0];
3764 }
3769 const_iterator end() const {
3770 return (&(*this)[0])+_numItems;
3771 }
3779 const_iterator cbegin() const {
3780 return & (*this)[0];
3781 }
3789 const_iterator cend() const {
3790 return (&(*this)[0])+_numItems;
3791 }
3803 bool empty() const {
3804 return false;
3805 }
3807 }; // class DataPointer - Array Partial specialization
3808
3836 /*
3837 * We need to implement the std::iterator template to ensure we pick
3838 * up various iterator types etc.
3839 *
3840 * It is unclear if we need to define the third argument to this
3841 * template, if we do, I'm not sure what it should be.
3842 *
3843 * std::iterator was depreciated from C++17, we are supposed
3844 * to now provide each of the relevant types explicitly.
3845 * See https://www.fluentcpp.com/2018/05/08/std-iterator-deprecated/ and
3846 * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0174r2.html#2.1
3847 */
3848 class IdIterator /*: public std::iterator<std::forward_iterator_tag, Id> */ {
3849 public: /* std::iterator equivalents */
3850 using iterator_category = std::forward_iterator_tag;
3851 using value_type = Id;
3852 using difference_type =std::ptrdiff_t;
3853 using pointer = Id*;
3854 using reference = Id&;
3855
3856 private:
3857 /* The item we are iterating through */
3858 const Id &_top;
3859 /* Is the item an array of structures. If false, presumed to
3860 * be a structure (validated by constructor)
3861 */
3862 bool _isArray = false;
3863 /* Index to Current component */
3864 unsigned long _curCell = ULONG_MAX;
3865 /* Index to last component + 1 */
3866 unsigned long _endCell = ULONG_MAX;
3867 public:
3879 explicit IdIterator(const Id & id, const bool setEnd=false) :
3880 _top(id) {
3881 /*
3882 * id must be a structure.
3883 */
3884 if (_top.GetCode() != SDS_STRUCT)
3885 {
3887 "Attempt to construct IdIterator on non-structured SDS item (code %)", _top.GetCode());
3888
3889 }
3890 /*
3891 * Grab the dimensions - can only work with a value of 0 or 1.
3892 */
3893 std::vector<unsigned> dims;
3894 _top.GetDims(&dims);
3895 if (dims.size() > 0)
3896 {
3897 /*
3898 * Array item.
3899 */
3900 _isArray = true;
3901 /*
3902 * Code does not yet handle dimensions greater then 1, as
3903 * that requires determining the order we index the
3904 * array etc.
3905 */
3906 if (dims.size() > 1)
3907 {
3909 "Attempt to construct IdIterator on an array of structures with more then 1 dimension - can't yet do that. ");
3910 }
3911 /*
3912 * Index of arrays starts at 1. dims[0] is one
3913 * past the last element.
3914 */
3915 _endCell = dims[0]+1;
3916 _curCell = 1;
3917 }
3918 else
3919 {
3920 /*
3921 * Indexing of structures starts at 1. GetNumItems() is
3922 * the maximum value.
3923 */
3924 _endCell = id.GetNumItems()+1;
3925 _curCell = 1;
3926 }
3927 /*
3928 * IF we are constructing the end item, set _curCell to _endCell.
3929 */
3930 if (setEnd)
3931 _curCell = _endCell;
3932 }
3933
3941 bool operator!= (const IdIterator& other) const {
3942 /* First ensure we are referring to the same SDS structure */
3943 if (&_top != &other._top)
3944 return false;
3945 return _curCell != other._curCell;
3946 }
3947
3953 Id operator* () const {
3954 if (_curCell >= _endCell)
3955 {
3957 "Attempt to dereference IdIterator past end of structure");
3958
3959
3960 }
3961 if (_isArray) {
3962 std::vector<unsigned long> indicies(1);
3963 indicies[0] = _curCell;
3964 return _top.Cell(indicies);
3965 } else {
3966 return _top.Index(_curCell);
3967 }
3975 const IdIterator & operator++ () {
3976 /*
3977 * Only increment if less then _endCell. This should ensure
3978 * we never advance past _endCell, ensuring that the comparison
3979 * against end() works correctly
3981 if (_curCell < _endCell)
3982 ++_curCell;
3983
3984 // although not strictly necessary for a range-based for loop
3985 // following the normal convention of returning a value from
3986 // operator++ is a good idea.
3987 return *this;
3988 }
3989
3990
3991 private:
3992 }; // class IdIterator
3993
3994
3995
4010 template <typename T>
4011 class ArrayContainer {
4012 public:
4014 typedef T value_type;
4016 typedef value_type& reference;
4018 typedef std::size_t size_type;
4019 private:
4020 T *_address = nullptr;
4021 size_type _size = 0;
4022 public:
4029 ArrayContainer(T *address, size_type size) :
4030 _address(address), _size(size){
4031 static_assert(
4032 std::is_standard_layout<T>::value,
4033 "The type T must be a standard layout and type");
4034 }
4039 bool empty() const {
4040 return (_size <= 0);
4046 size_type size() const {
4047 return _size;
4048 }
4055 return _address[n];
4059 ~ArrayContainer() {}
4060 }; // Class ArrayContainer
4061
4062
4063 inline drama::sds::IdIterator begin(const drama::sds::Id &id) {
4064 return drama::sds::IdIterator(id);
4065 }
4067 return drama::sds::IdIterator(id, true);
4068 }
4069
4070 } // namespace sds
4071
4072} // namespace drama
4074#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:4073
reference operator[](size_type n)
Returns an item at a particular address.
Definition sds.hh:4081
bool empty() const
Returns true if the container is empty.
Definition sds.hh:4066
value_type & reference
The type for a reference to the value.
Definition sds.hh:4043
T value_type
The value type.
Definition sds.hh:4041
ArrayContainer(T *address, size_type size)
Create a container to access the array.
Definition sds.hh:4056
std::size_t size_type
The type used for sizes.
Definition sds.hh:4045
~ArrayContainer()
Destroy the container, not the underlying array item.
Definition sds.hh:4086
A container for simple arrays for use with SDS templates.
Definition sds.hh:4038
Helper class for writing data to SDS Scalar Arrays.
Definition sdsarray.hh:303
const_iterator cend() const
Returns a const iterator pointing to the past-the-end element in the array.
Definition sds.hh:3816
iterator begin()
Returns an iterator pointing to the first element in the array.
Definition sds.hh:3775
const_iterator cbegin() const
Returns a const iterator pointing to the first element in the array.
Definition sds.hh:3806
bool empty() const
Returns true if container is empty.
Definition sds.hh:3830
const T * const_iterator
const iterator for this item
Definition sds.hh:3653
iterator end()
Returns an iterator pointing to the past-the-end element in the array.
Definition sds.hh:3782
unsigned long size() const
Return the number of elements in the array.
Definition sds.hh:3761
DataPointer(const drama::sds::Id &theId)
DataPointer Constructor.
Definition sds.hh:3666
const_iterator begin() const
Returns a const iterator pointing to the first element in the array.
Definition sds.hh:3789
unsigned long NumBytes() const
Return the size of the item in bytes.
Definition sds.hh:3768
~DataPointer()
DataPointer destructor.
Definition sds.hh:3748
T * iterator
iterator for this item
Definition sds.hh:3651
T value_type
Returns the type of T
Definition sds.hh:3655
DataPointer(drama::sds::Id *theId, bool outlives=false)
DataPointer Constructor.
Definition sds.hh:3709
const_iterator end() const
Returns a const iterator pointing to the past-the-end element in the array.
Definition sds.hh:3796
unsigned long NumBytes() const
Return the size of the item in bytes.
Definition sds.hh:3618
DataPointer(drama::sds::Id *theId, bool outlives)
DataPointer Constructor.
Definition sds.hh:3568
~DataPointer()
DataPointer destructor.
Definition sds.hh:3605
DataPointer(const drama::sds::Id &theId)
DataPointer Constructor.
Definition sds.hh:3530
A class that provides direct access to the data of an SDS item, via a sub-class of std::unique_ptr<>.
Definition sds.hh:3517
IdChecker(int line, const char *file, const char *function)
Construct an SdsChecker object.
Definition sds.hh:3448
virtual ~IdChecker()
SdsCheck destructor.
Definition sds.hh:3459
A class to check for SDS leaks.
Definition sds.hh:3421
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:3906
bool operator!=(const IdIterator &other) const
Inequality operator.
Definition sds.hh:3968
Id operator*() const
Dereference operator - return the sds::Id item the iterator is pointing to.
Definition sds.hh:3980
const IdIterator & operator++()
Increment operator (prefix version).
Definition sds.hh:4002
An iterator for working through SDS Structures and SDS arrays of structures.
Definition sds.hh:3875
virtual void SetFree()
Indicate the underlying SDS item should be free-ed when the sds::Id object is destroyed.
Definition sds.hh:1323
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:1009
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:1652
virtual std::string GetExtra() const
Get extra data from an SDS item.
Definition sds.hh:1620
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:2062
static Id FromFile(const std::string &filename)
Factory constructor method that reads an SDS structure from a file.
Id ArrayCreateAndAccess(const std::string &name, const unsigned nitems, sds::ArrayWriteHelper< T > *const data, const std::string &extra="")
Create a new child of primitive items and access that array, one dimensional.
Definition sds.hh:2782
void Get(const std::string &name, T *value) const
Fetch primitive value from a named component of the structure.
Definition sds.hh:3205
virtual void ClearDelete()
Indicate the underlying SDS structure should NOT be deleted when the sds::Id object is destroyed.
Definition sds.hh:1339
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:3323
unsigned GetNumItems() const
Return the number of components in an SDS structure.
Definition sds.hh:1772
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:1350
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:2588
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:2544
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:2920
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:1329
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:2123
virtual void Write(const std::string &filename) const
Write the contents of the structure to a file.
Definition sds.hh:2229
virtual void Rename(const std::string &name)
Rename the SDS item.
Definition sds.hh:2028
virtual void List() const
List the contents of the structure to standard output.
Definition sds.hh:2137
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:3168
static Id CreateFromSdsId(SdsId *item)
Factory constructor method that constructs an sds::Id item from an existing old C++ interface SdsId i...
virtual void DeleteIfExists(const std::string &name)
Delete the named SDS item within the current structured item.
Definition sds.hh:1407
virtual unsigned int GetUInt() const
If the SDS item refers to a scalar value, convert it to an unsigned integer.
Id ArrayCreateAndAccess(const std::string &name, const ContainerType &dims, sds::ArrayWriteHelper< T > *const data, const std::string &extra="")
Create a new child of primitive items and access that array, multi-dimensional.
Definition sds.hh:2847
void Put(T value)
Insert a primitive value into the item.
Definition sds.hh:3241
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:1830
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:1185
virtual void ToSdsId(::SdsId *target, const bool outlives=false)
Shallow copy to an SdsId type.
Definition sds.hh:2486
static Id CreateByImport(const ContainerType &container)
Factory constructor method that imports an exported SDS structure found in a byte stream.
Definition sds.hh:828
virtual void List(FILE *to) const
List the contents of the structure to a C file.
Definition sds.hh:2149
virtual void ValidateCode(SdsCodeType requiredCode) const
Validate the code of the SDS item.
Definition sds.hh:1701
void ExportDefined(ContainerType *container) const
Export the SDS structure into a buffer, defining any undefined data.
Definition sds.hh:1489
void Export(ContainerType *container) const
Export the SDS structure into a buffer.
Definition sds.hh:1443
void Pointer(T **data, unsigned long *length=0) const
Obtain a pointer to the data area of a primitive SDS item.
Definition sds.hh:1924
virtual SdsCodeType GetCode() const
Return the code of the SDS item.
Definition sds.hh:1679
void ArrayAccess(ArrayAccessHelper< T > *const data, ContainerType *dims) const
Access the data of an SDS primitive item array.
Definition sds.hh:2724
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:1124
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:2466
virtual void Delete()
Delete the SDS item.
Definition sds.hh:1378
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:1743
virtual ~Id()
sds::Id Destructor.
Definition sds.hh:1312
virtual void FillArray(const Id &elem)
Fill out the contents of this object, which is a structured array.
Definition sds.hh:1878
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:2361
void ArrayAccess(ArrayAccessHelper< T > *const data, long ndims, ContainerType *dims) const
Access the data of an SDS primitive item array.
Definition sds.hh:2647
virtual void Insert(Id &to_insert)
Insert an SDS object into this object.
Definition sds.hh:1794
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:2101
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:1586
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:3012
void Put(const std::string &value)
Insert a string value into the component.
Definition sds.hh:3263
virtual void Extract()
Extract the SDS structure from its parent.
Definition sds.hh:1522
virtual void PutExtra(const std::string &extra)
Put extra data into an SDS item.
Definition sds.hh:2013
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:3052
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:2421
void Put(const unsigned long length, const T *const data, const unsigned long offset=0)
Put data into an SDS item.
Definition sds.hh:1980
virtual void Flush()
Flush data modified by pointer.
Definition sds.hh:1548
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:3285
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:2976
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:943
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:2392
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:1060
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:3135
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:2249
virtual std::string toString(int maxlen=200)
Convert the structure to a string.
Definition sds.hh:3084
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:108
#define DramaTHROW(status_, message_)
Throw a Drama exception.
Definition exception.hh:87
DRAMA 2 Exception classes.
std::shared_ptr< Id > IdPtr
A shared pointer for sds::Id items.
Definition sds.hh:3484
void CreateRunDramaTask()
Create and run a DRAMA task, with standard exception handling.
Definition task.hh:1327
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.