GAMS Data eXchange (GDX) API
Low-level "eXPert level" C++ API for reading and writing GAMS Data eXchange files
Loading...
Searching...
No Matches
gxfile.hpp
1/*
2 * GAMS - General Algebraic Modeling System GDX API
3 *
4 * Copyright (c) 2017-2025 GAMS Software GmbH <support@gams.com>
5 * Copyright (c) 2017-2025 GAMS Development Corp. <support@gams.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26#pragma once
27
28// Description:
29// This unit defines the GDX Object as a C++ object.
30
31#include "datastorage.hpp" // for TLinkedData
32#include <gclgms.h> // for GLOBAL_MAX_INDEX_DIM, GMS_MAX_INDEX_DIM
33#include "gmsdata.hpp" // for TTblGamsData
34#include "gmsobj.hpp" // for TBooleanBitArray, TXList, TXStrings
35#include "strhash.hpp" // for TXCSStrHashList, TXStrHashList
36#include "utils.hpp"
37#include <array> // for array
38#include <cstdint> // for int64_t, uint8_t
39#include <cstring> // for size_t
40#include <initializer_list>// for initializer_list
41#include <limits> // for numeric_limits
42#include <memory> // for unique_ptr, allocator
43#include <optional> // for optional
44#include <string> // for string
45
46namespace gdlib::gmsstrm
47{
48class TXStream;
49}// namespace gdx::gmsstrm
50
51//======================================================================================================================
52
53namespace gdx
54{
55
56class TgdxUELIndex : public std::array<int, GMS_MAX_INDEX_DIM> {
57public:
58 constexpr explicit operator int *() noexcept { return data(); }
59 constexpr explicit operator const int *() const noexcept { return data(); }
60};
61class TgdxValues : public std::array<double, GMS_VAL_SCALE + 1> {
62public:
63 constexpr explicit operator double*() noexcept { return data(); }
64 constexpr explicit operator const double *() const noexcept { return data(); }
65};
66
67using TDomainIndexProc_t = void ( * )( int RawIndex, int MappedIndex, void *Uptr );
68using TDataStoreProc_t = void ( * )( const int *Indx, const double *Vals );
69using TDataStoreFiltProc_t = int ( * )( const int *Indx, const double *Vals, void *Uptr );
70using TDataStoreExProc_t = int ( * )( const int *Indx, const double *Vals, const int afdim, void *Uptr );
71
72using TDataStoreExProc_F = int ( * )( const int *Indx, const double *Vals, const int afdim, int64_t Uptr );
73using TDataStoreFiltProc_F = int ( * )( const int *Indx, const double *Vals, int64_t Uptr );
74using TDomainIndexProc_F = void ( * )( int RawIndex, int MappedIndex, int64_t Uptr );
75
76const std::array<int, GMS_DT_ALIAS + 1> DataTypSize { 1, 1, 5, 5, 0 };
77
78constexpr int DOMC_UNMAPPED = -2,// indicator for unmapped index pos
79 DOMC_EXPAND = -1, // indicator growing index pos
80 DOMC_STRICT = 0; // indicator mapped index pos
81
82const std::string BADUEL_PREFIX = "?L__",
83 BADStr_PREFIX = "?Str__",
84 strGDXCOMPRESS = "GDXCOMPRESS",
85 strGDXCONVERT = "GDXCONVERT";
86
87struct TDFilter final {
88 int FiltNumber {}, FiltMaxUel {};
89 gdlib::gmsobj::TBooleanBitArray FiltMap {};
90 bool FiltSorted {};
91
92 TDFilter( int Nr, int UserHigh ) : FiltNumber { Nr },
93 FiltMaxUel { UserHigh }
94 {
95 }
96
97 ~TDFilter() = default;
98
99 [[nodiscard]] int MemoryUsed() const
100 {
101 return FiltMap.MemoryUsed();
102 }
103
104 [[nodiscard]] bool InFilter( int V ) const
105 {
106 return V >= 0 && V <= FiltMaxUel && FiltMap.GetBit( V );
107 }
108
109 void SetFilter( int ix, bool v )
110 {
111 FiltMap.SetBit( ix, v );
112 }
113};
114
115using TSetBitMap = gdlib::gmsobj::TBooleanBitArray;
116
117enum class TgdxDAction : uint8_t
118{
119 dm_unmapped,
120 dm_strict,
121 dm_filter,
122 dm_expand
123};
124
125struct TDomain {
126 TDFilter *DFilter;
127 TgdxDAction DAction;
128};
129
130using TDomainList = std::array<TDomain, GLOBAL_MAX_INDEX_DIM>;
131
132using TCommentsList = gdlib::gmsobj::TXStrings;
133
134struct TgdxSymbRecord final {
135 int SSyNr;
136 int64_t SPosition;
137 int SDim, SDataCount, SErrors;
138 gdxSyType SDataType;
139 int SUserInfo;
140 bool SSetText;
141 utils::sstring SExplTxt;
142 bool SIsCompressed;
143 bool SScalarFrst; // not stored
144 std::unique_ptr<int[]> SDomSymbols,// real domain info
145 SDomStrings;// relaxed domain info
146 std::optional<TCommentsList> SCommentsList;
147 std::unique_ptr<TSetBitMap> SSetBitMap;// for 1-dim sets only
148};
150
151enum TgdxIntlValTyp : uint8_t
152{// values stored internally via the indicator byte
153 vm_valund,
154 vm_valna,
155 vm_valpin,
156 vm_valmin,
157 vm_valeps,
158 vm_zero,
159 vm_one,
160 vm_mone,
161 vm_half,
162 vm_two,
163 vm_normal,
164 vm_count
165};
166
167enum TgxFileMode : uint8_t
168{
169 f_not_open,
170 fr_init,
171 fw_init,
172 fw_dom_raw,
173 fw_dom_map,
174 fw_dom_str,
175 fw_raw_data,
176 fw_map_data,
177 fw_str_data,
178 f_raw_elem,
179 f_map_elem,
180 f_str_elem,
181 fr_raw_data,
182 fr_map_data,
183 fr_mapr_data,
184 fr_str_data,
185 fr_filter,
186 fr_slice,
187 tgxfilemode_count
188};
189
190class TgxModeSet final : public utils::IContainsPredicate<TgxFileMode>
191{
192 std::array<bool, tgxfilemode_count> modeActive {};
193 uint8_t count {};
194
195public:
196 TgxModeSet( const std::initializer_list<TgxFileMode> &modes );
197 ~TgxModeSet() override = default;
198 [[nodiscard]] bool contains( const TgxFileMode &mode ) const override;
199 [[nodiscard]] bool empty() const;
200};
201
202const TgxModeSet AnyWriteMode { fw_init, fw_dom_raw, fw_dom_map, fw_dom_str, fw_raw_data, fw_map_data, fw_str_data },
203 AnyReadMode { fr_init, fr_raw_data, fr_map_data, fr_mapr_data, fr_str_data };
204
205enum class TgdxElemSize : uint8_t
206{
207 sz_byte,
208 sz_word,
209 sz_integer
210};
211
212// N.B.: we store integers in [0..high(integer)] in TIntegerMapping, so
213// FMAXCAPACITY = high(integer) + 1 is all we will ever need, and we will
214// never get a request to grow any larger. The checks and code
215// in growMapping reflect this
217{
218 int64_t FCapacity {}, FMapBytes {};
219 int64_t FMAXCAPACITY { std::numeric_limits<int>::max() + static_cast<int64_t>( 1 ) };
220 int FHighestIndex {};
221 int *PMap {};
222
223 void growMapping( int F );
224
225public:
226 TIntegerMapping() = default;
228 [[nodiscard]] int MemoryUsed() const;
229 [[nodiscard]] int GetHighestIndex() const;
230 [[nodiscard]] int GetMapping( int F ) const;
231 void SetMapping( int F, int T );
232 [[nodiscard]] int size() const;
233 [[nodiscard]] bool empty() const;
234 void reset();
235};
236
237enum class TUELUserMapStatus : uint8_t
238{
239 map_unknown,
240 map_unsorted,
241 map_sorted,
242 map_sortgrow,
243 map_sortfull
244};
245
246template<typename T>
247using TXStrHashListImpl = gdlib::strhash::TXStrHashList<T>;
248
249template<typename T>
250using TXCSStrHashListImpl = gdlib::strhash::TXCSStrHashList<T>;
251
252class TUELTable final : public TXStrHashListImpl<int>
253{
254 TUELUserMapStatus FMapToUserStatus { TUELUserMapStatus::map_unknown };
255
256public:
257 std::unique_ptr<TIntegerMapping> UsrUel2Ent {};// from user uelnr to table entry
258 TUELTable();
259 ~TUELTable() override = default;
260 [[nodiscard]] int size() const;
261 [[nodiscard]] bool empty() const;
262 [[nodiscard]] int GetUserMap( int i ) const;
263 void SetUserMap( int EN, int N );
264 int NewUsrUel( int EN );
265 int AddUsrNew( const char *s, size_t slen );
266 int AddUsrIndxNew( const char *s, size_t slen, int UelNr );
267 [[nodiscard]] int GetMaxUELLength() const;
268 int IndexOf( const char *s );
269 int AddObject( const char *id, size_t idlen, int mapping );
270 int StoreObject( const char *id, size_t idlen, int mapping );
271 const char *operator[]( int index ) const;
272 void RenameEntry( int N, const char *s );
273 [[nodiscard]] int MemoryUsed() const;
274 void SaveToStream( gdlib::gmsstrm::TXStream &S );
275 void LoadFromStream( gdlib::gmsstrm::TXStream &S );
276 TUELUserMapStatus GetMapToUserStatus();
277 void ResetMapToUserStatus();
278};
279
280int MakeGoodExplText( char *s );
281
282struct TAcronym final {
283 std::string AcrName, AcrText;
284 int AcrMap {}, AcrReadMap { -1 };
285 bool AcrAutoGen {};
286
287 TAcronym( const char *Name, const char *Text, int Map );
288 explicit TAcronym( gdlib::gmsstrm::TXStream &S );
289 TAcronym() = default;
290 ~TAcronym() = default;
291 [[nodiscard]] int MemoryUsed() const;
292 void SaveToStream( gdlib::gmsstrm::TXStream &S ) const;
293 void SetNameAndText( const char *Name, const char *Text );
294};
295
296class TAcronymList final
297{
298 bool useBatchAlloc {};
299 gdlib::gmsobj::TXList<TAcronym> FList;
300 gdlib::batchalloc::BatchAllocator<sizeof(TAcronym)> batchAlloc;
301
302public:
303 TAcronymList() = default;
304 explicit TAcronymList(bool _useBatchAlloc) : useBatchAlloc{_useBatchAlloc} {}
306 int FindEntry( int Map );
307 int FindName( const char *Name );
308 int AddEntry( const char *Name, const char *Text, int Map );
309 void CheckEntry( int Map );
310 void SaveToStream( gdlib::gmsstrm::TXStream &S );
311 void LoadFromStream( gdlib::gmsstrm::TXStream &S );
312 int MemoryUsed();
313 [[nodiscard]] int size() const;
314 TAcronym &operator[]( int Index );
315};
316
317class TFilterList final
318{
319 gdlib::gmsobj::TXList<TDFilter> FList;
320
321public:
322 TFilterList() = default;
323 ~TFilterList();
324 void AddFilter( TDFilter *F );
325 void DeleteFilter( int ix );
326 TDFilter *FindFilter( int Nr );
327 [[nodiscard]] size_t MemoryUsed() const;
328};
329
330using TIntlValueMapDbl = std::array<double, vm_count>;
331using TIntlValueMapI64 = std::array<int64_t, vm_count>;
332
333using LinkedDataType = gdlib::datastorage::TLinkedData<int, double>;
334using LinkedDataIteratorType = gdlib::datastorage::TLinkedDataRec<int, double> *;
335
336using TSetTextList = TXCSStrHashListImpl<int>;
337
338using TNameList = TXStrHashListImpl<PgdxSymbRecord>;
339
340template<typename T>
341using TTblGamsDataImpl = gdlib::gmsdata::TTblGamsData<T>;
342
343using TDomainStrList = TXStrHashListImpl<uint8_t>;
344
345enum tvarvaltype : uint8_t
346{
347 vallevel, // 1
348 valmarginal,// 2
349 vallower, // 3
350 valupper, // 4
351 valscale // 5
352};
353
354extern std::string DLLLoadPath;// can be set by loader, so the "dll" knows where it is loaded from
355
357{
358 int64_t i;
359 void *p;
360};
361
362bool IsGoodIdent( const char *S );
363bool CanBeQuoted( const char *s, size_t slen );
364bool GoodUELString( const char *s, size_t slen );
365
366int ConvertGDXFile( const std::string &fn, const std::string &MyComp );
367
368}// namespace gdx
Definition: gxfile.hpp:297
Definition: gxfile.hpp:318
Definition: gxfile.hpp:217
Definition: gxfile.hpp:253
Definition: gxfile.hpp:56
Definition: gxfile.hpp:61
Definition: gxfile.hpp:191
Definition: gxfile.hpp:282
Definition: gxfile.hpp:87
Definition: gxfile.hpp:125
Definition: gxfile.hpp:134
Definition: gxfile.hpp:357