14#ifndef DOXYGEN_SHOULD_IGNORE_THIS
19const size_t kInciSize = 12;
22template <
typename EDTTYPE, EXTAG TAG>
23class __FCSimpleEDTStruct :
public EDTTYPE
29 { memset(
this, 0,
sizeof(*
this)); }
31 __FCSimpleEDTStruct(
const EDTTYPE& edtStruct) : EDTTYPE(edtStruct)
32 { memset(&_id, 0,
sizeof(_id)); }
35 void InitializeEDTStruct()
37 EDTTYPE * pEDT =
dynamic_cast<EDTTYPE *
>(
this);
38 assert(pEDT !=
nullptr);
39 memset(pEDT, 0,
sizeof(EDTTYPE));
42 bool Load(std::optional<std::reference_wrapper<EDTTYPE>> copyToStruct = std::nullopt)
44 fourbyte datasize =
sizeof(EDTTYPE);
45 bool retval = FX_LoadEData(TAG, &_id,
static_cast<EDTTYPE *
>(
this), &datasize);
46 if (retval && copyToStruct.has_value())
47 copyToStruct.value().get() = *
static_cast<EDTTYPE *
>(
this);
56 if (Load())
return true;
60 bool LoadNext() {
return FX_NextEData(TAG, &_id,
static_cast<EDTTYPE *
>(
this),
sizeof(EDTTYPE)); }
61 bool LoadPrevious() {
return FX_PreviousEData(TAG, &_id,
static_cast<EDTTYPE *
>(
this),
sizeof(EDTTYPE)); }
62 bool Save() {
return FX_SaveEData(TAG, &_id,
static_cast<EDTTYPE *
>(
this),
sizeof(EDTTYPE)); }
63 bool Create() {
return FX_CreateEData(TAG, &_id,
static_cast<EDTTYPE *
>(
this),
sizeof(EDTTYPE)); }
64 bool Delete() {
return FX_DeleteEData(TAG, &_id); }
67template <
typename EDTTYPE, EXTAG TAG>
68class __FCSimpleOther :
public __FCSimpleEDTStruct<EDTTYPE,TAG>
71 __FCSimpleOther(
const CMPER cmper = kNewCmper,
const twobyte inci = 0)
73 __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.other.cmper = cmper;
74 __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.other.inci = inci;
77 __FCSimpleOther(
const EDTTYPE& edtStruct,
const CMPER cmper = kNewCmper,
const twobyte inci = 0) : __FCSimpleEDTStruct<EDTTYPE,TAG>(edtStruct)
79 __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.other.cmper = cmper;
80 __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.other.inci = inci;
83 CMPER GetCmper()
const
84 {
return __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.other.cmper; }
86 void SetCmper(
const CMPER cmper)
87 { __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.other.cmper = cmper; }
89 twobyte GetInci()
const
90 {
return __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.other.inci; }
92 void SetInci(
const twobyte inci)
93 { __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.other.inci = inci; }
96template <
typename EDTTYPE, EXTAG TAG>
97class __FCSimpleDetail :
public __FCSimpleEDTStruct<EDTTYPE,TAG>
100 __FCSimpleDetail(
const CMPER cmper1 = kNewCmper,
const CMPER cmper2 = kNewCmper2,
const twobyte inci = 0)
102 __FCSimpleDetail<EDTTYPE,TAG>::_id.detail.cmper1 = cmper1;
103 __FCSimpleDetail<EDTTYPE,TAG>::_id.detail.cmper2 = cmper2;
104 __FCSimpleDetail<EDTTYPE,TAG>::_id.detail.inci = inci;
107 __FCSimpleDetail(
const EDTTYPE& edtStruct,
const CMPER cmper1 = kNewCmper,
const CMPER cmper2 = kNewCmper2,
const twobyte inci = 0) :
108 __FCSimpleEDTStruct<EDTTYPE,TAG>(edtStruct)
110 __FCSimpleDetail<EDTTYPE,TAG>::_id.detail.cmper1 = cmper1;
111 __FCSimpleDetail<EDTTYPE,TAG>::_id.detail.cmper2 = cmper2;
112 __FCSimpleDetail<EDTTYPE,TAG>::_id.detail.inci = inci;
115 CMPER GetCmper1()
const
116 {
return __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.detail.cmper1; }
118 void SetCmper1(
const CMPER cmper)
119 { __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.detail.cmper1 = cmper; }
121 CMPER GetCmper2()
const
122 {
return __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.detail.cmper2; }
124 void SetCmper2(
const CMPER cmper)
125 { __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.detail.cmper2 = cmper; }
127 twobyte GetInci()
const
128 {
return __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.detail.inci; }
130 void SetInci(
const twobyte inci)
131 { __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.detail.inci = inci; }
134template <
typename EDTTYPE, EXTAG TAG>
135class __FCSimpleEntryDetail :
public __FCSimpleEDTStruct<EDTTYPE,TAG>
138 __FCSimpleEntryDetail(
const ENTNUM entryNumber = kNewEntryNum,
const twobyte inci = 0)
140 __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.entryDetail.entryNumber = entryNumber;
141 __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.entryDetail.inci = inci;
144 ENTNUM GetEntryNumber()
const
145 {
return __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.entryDetail.entryNumber; }
147 void SetEntryNumber(
const ENTNUM entryNumber)
148 { __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.entryDetail.entryNumber = entryNumber; }
150 twobyte GetInci()
const
151 {
return __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.entryDetail.inci; }
153 void SetInci(
const twobyte inci)
154 { __FCSimpleEDTStruct<EDTTYPE,TAG>::_id.entryDetail.inci = inci; }
158template <
typename EDTTYPE, EXTAG TAG>
161 static_assert(HI_UTWOBYTE(TAG) == edOther || HI_UTWOBYTE(TAG) == edDetail,
"EXTAG must be edDetail or edOther");
162 static constexpr bool IS_DETAIL = HI_UTWOBYTE(TAG) == edDetail;
168 std::vector<char> _buffer;
170 static constexpr size_t INCISIZE = std::conditional_t<IS_DETAIL, std::integral_constant<size_t, 5>, std::integral_constant<size_t, 6>>::value;
173 twobyte inci[INCISIZE];
176 void AddToBuffer(
const INCITYPE& inci)
178 size_t currsize = _buffer.size();
179 _buffer.resize(currsize +
sizeof(inci));
180 memcpy(&_buffer[currsize], &inci,
sizeof(inci));
185 if constexpr(IS_DETAIL)
186 return __FCSimpleDetail<INCITYPE, TAG>(_cmper1, _cmper2, 0);
188 return __FCSimpleOther<INCITYPE, TAG>(_cmper1, 0);
191 bool GetInci(
size_t incino, INCITYPE& inci)
193 size_t buffx = incino *
sizeof(inci);
194 if (buffx < _buffer.size())
196 memset(&inci, 0,
sizeof(inci));
197 memcpy(&inci, &_buffer[buffx], (std::min)(
sizeof(inci), _buffer.size() - buffx));
204 void StoreCmpers(
const T& inci)
206 if constexpr(IS_DETAIL)
208 _cmper1 = inci.GetCmper1();
209 _cmper2 = inci.GetCmper2();
213 _cmper1 = inci.GetCmper();
219 void AssignBuffer(
const void* buffer,
size_t numbytes)
222 _buffer.resize(numbytes);
223 memcpy(_buffer.data(), buffer, _buffer.size());
226 bool _Load(CMPER cmper1, CMPER cmper2)
230 auto loader = GetInciType();
232 for (EINCI inci = 0;
true; inci++)
234 loader.SetInci(inci);
235 if (!loader.Load())
break;
238 return _buffer.size() > 0;
241 bool _SaveAs(CMPER cmper1, CMPER cmper2)
248 bool _Delete(CMPER cmper1, CMPER cmper2)
255 CMPER _GetCmper1()
const {
return _cmper1; }
256 CMPER _GetCmper2()
const {
return _cmper2; }
258 void _SetCmper1(CMPER cmper) { _cmper1 = cmper; }
259 void _SetCmper2(CMPER cmper) { _cmper2 = cmper; }
261 const void* GetBuffer()
const {
return _buffer.data(); }
263 __FCEnigmaArray(
const int maxelements) : _cmper1(kNewCmper), _cmper2(0), _maxelements(maxelements)
265 if (maxelements) AllocateFor(maxelements);
270 EDTTYPE& operator[](
const size_t x)
272 const size_t requiredSize = (x + 1) *
sizeof(EDTTYPE);
273 if (requiredSize > _buffer.size())
274 _buffer.resize(requiredSize);
275 return reinterpret_cast<EDTTYPE *
>(_buffer.data())[x];
278 const EDTTYPE& operator[](
const size_t x)
const
280 assert(x *
sizeof(EDTTYPE) <= _buffer.size() -
sizeof(EDTTYPE));
281 return reinterpret_cast<const EDTTYPE *
>(_buffer.data())[x];
289 int NumElements()
const
291 assert(_buffer.size() %
sizeof(EDTTYPE) == 0);
292 int _physicalElements =
static_cast<int>(_buffer.size() /
sizeof(EDTTYPE));
294 return (std::min)(_physicalElements, _maxelements);
295 return _physicalElements;
298 void AllocateFor(
const int numelements)
300 assert(numelements >= 0);
304 size_t newsize = numelements *
sizeof(EDTTYPE);
305 size_t remainder = newsize % INCISIZE*
sizeof(twobyte);
306 if (remainder) newsize += remainder;
307 _buffer.resize(newsize);
309 _maxelements = numelements;
314 auto inci = GetInciType();
315 inci.SetInci(TWOBYTE_MAX);
319 return _Load(_cmper1, _cmper2);
326 if (_Load(0,0))
return true;
333 auto saver = GetInciType();
334 for (
int inci = 0; GetInci(inci, saver); inci++)
337 bool success = (_cmper1 == kNewCmper) ? saver.Create() : saver.Save();
338 if (!success)
return false;
346 auto deleter = GetInciType();
347 bool deletedSomething =
false;
348 while (deleter.Delete())
349 deletedSomething =
true;
350 return deletedSomething;
354template <
typename EDTTYPE, EXTAG TAG>
355class __FCEnigmaOtherArray :
public __FCEnigmaArray<EDTTYPE, TAG>
357 static_assert(HI_UTWOBYTE(TAG) == edOther,
"EXTAG must be edOther");
358 using __FCEnigmaOtherArrayBase = __FCEnigmaArray<EDTTYPE, TAG>;
367 __FCEnigmaOtherArray(
const int maxelements = 0) : __FCEnigmaOtherArrayBase(maxelements) {}
369 CMPER GetCmper()
const {
return this->_GetCmper1(); }
370 void SetCmper(CMPER cmper) { this->_SetCmper1(cmper); }
372 bool Load(CMPER cmper) {
return this->_Load(cmper, 0); }
373 bool SaveAs(CMPER cmper) {
return this->_SaveAs(cmper, 0); }
374 bool Delete(CMPER cmper) {
return this->_Delete(cmper, 0); }
377template <
typename EDTTYPE, EXTAG TAG>
378class __FCEnigmaDetailArray :
public __FCEnigmaArray<EDTTYPE, TAG>
380 static_assert(HI_UTWOBYTE(TAG) == edDetail,
"EXTAG must be edDetail");
381 using __FCEnigmaDetailArrayBase = __FCEnigmaArray<EDTTYPE, TAG>;
390 __FCEnigmaDetailArray(
const int maxelements = 0) : __FCEnigmaDetailArrayBase(maxelements) {}
392 using __FCEnigmaDetailArrayBase::LoadFirst;
394 CMPER GetCmper1()
const {
return this->_GetCmper1(); }
395 CMPER GetCmper2()
const {
return this->_GetCmper2(); }
397 void SetCmper1(CMPER cmper) { this->_SetCmper1(cmper); }
398 void SetCmper2(CMPER cmper) { this->_SetCmper2(cmper); }
400 bool Load(CMPER cmper1, CMPER cmper2) {
return this->_Load(cmper1, cmper2); }
401 bool SaveAs(CMPER cmper1, CMPER cmper2) {
return this->_SaveAs(cmper1, cmper2); }
402 bool Delete(CMPER cmper1, CMPER cmper2) {
return this->_Delete(cmper1, cmper2); }
404 bool LoadNext(CMPER cmper1)
406 if (!__FCEnigmaDetailArrayBase::LoadNext())
return false;
407 return (cmper1 == GetCmper1());
410 bool LoadFirst(CMPER cmper1)
412 if (Load(cmper1, 0))
return true;
413 return LoadNext(cmper1);
416 bool LoadNextCmper1()
418 if (GetCmper1() == kNewCmper)
return false;
419 if (Load(GetCmper1() + 1, 0))
return true;
420 return __FCEnigmaDetailArrayBase::LoadNext();
423 bool Delete(CMPER cmper1)
425 if (LoadFirst(cmper1))
427 Delete(cmper1, GetCmper2());
428 while (LoadNext(cmper1))
429 Delete(cmper1, GetCmper2());
436template <
typename CHARTYPE, EXTAG TAG>
437class __FCEnigmaArrayString :
public std::conditional_t<HI_UTWOBYTE(TAG) == edDetail, __FCEnigmaDetailArray<CHARTYPE, TAG>, __FCEnigmaOtherArray<CHARTYPE, TAG>>
439 static_assert(std::is_integral<CHARTYPE>::value,
"CHARTYPE must be an integer type");
440 using __FCEnigmaArrayStringBase = std::conditional_t<HI_UTWOBYTE(TAG) == edDetail, __FCEnigmaDetailArray<CHARTYPE, TAG>, __FCEnigmaOtherArray<CHARTYPE, TAG>>;
443 __FCEnigmaArrayString() : __FCEnigmaArrayStringBase() {}
445 template<std::
size_t N>
446 __FCEnigmaArrayString(
const CHARTYPE (&inpstr)[N]) : __FCEnigmaArrayStringBase()
447 { AssignString<N>(inpstr); }
449 template<std::
size_t N>
450 void AssignString(
const CHARTYPE (&inpstr)[N])
452 const std::size_t bufLen =
sizeof(CHARTYPE) * (std::min)(N, std::char_traits<CHARTYPE>::length(inpstr) + 1);
453 __FCEnigmaArrayStringBase::AssignBuffer(inpstr, bufLen);
456 void AssignString(
const CHARTYPE* inpstr)
458 const std::size_t bufLen =
sizeof(CHARTYPE) * std::char_traits<CHARTYPE>::length(inpstr) + 1;
459 __FCEnigmaArrayStringBase::AssignBuffer(inpstr, bufLen);
462 const CHARTYPE* GetString()
const {
return reinterpret_cast<const CHARTYPE*
>(this->GetBuffer()); }
466struct __FCEnigmaInciStruct
469 const twobyte& operator[](
size_t index)
const {
return data[index]; }
470 twobyte& operator[](
size_t index) {
return data[index]; }
473class __FCEnigmaOtherInci :
public __FCSimpleOther<__FCEnigmaInciStruct<6>, TAG>
476 __FCEnigmaOtherInci(CMPER cmper, twobyte inci) : __FCSimpleOther<__FCEnigmaInciStruct<6>, TAG>(cmper, inci) {}