NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
stringmemory.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2019 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19#include "stringmemory.hpp"
20#include "../utils/tools.hpp"
21
22using namespace std;
23
24// STRINGINTERNALMEMORY IMPLEMENTATION
25
26// Implementation for the "Sorter" object
27int StringInternalMemory::compare(int i, int j, int col)
28{
29 if (sStrings.size() <= (size_t)col)
30 return 0;
31
32 // Ensure that the coordinates reference a
33 // valid string object
34 if (i <= j && sStrings[col].size() <= (size_t)i)
35 return 0;
36 else if (i < j && sStrings[col].size() <= (size_t)j)
37 return -1;
38 else if (i > j && sStrings[col].size() <= (size_t)j)
39 return 0;
40 else if (i > j && sStrings[col].size() <= (size_t)i)
41 return 1;
42
43 // Comparsion currently done depending on the
44 // value of the internal private member variable
46 {
47 if (toLowerCase(sStrings[col][i]) < toLowerCase(sStrings[col][j]))
48 return -1;
49 else if (toLowerCase(sStrings[col][i]) == toLowerCase(sStrings[col][j]))
50 return 0;
51 }
52 else
53 {
54 if (sStrings[col][i] < sStrings[col][j])
55 return -1;
56 else if (sStrings[col][i] == sStrings[col][j])
57 return 0;
58 }
59 return 1;
60}
61
62// Implementation for the "Sorter" object
63bool StringInternalMemory::isValue(int line, int col)
64{
65 if (sStrings.size() <= (size_t)col)
66 return false;
67 if (sStrings[col].size() <= (size_t)line)
68 return false;
69
70 return sStrings[col][line].length();
71}
72
73// Entry point into the sorting algorithm. Prepares the indices
74// and the ColumnKeys object, if necessary
75vector<int> StringInternalMemory::sortElements(long long int i1, long long int i2, long long int j1, long long int j2, const string& sSortingExpression)
76{
77 if (!sStrings.size())
78 return vector<int>();
79
80 bool bError = false;
81 bool bReturnIndex = false;
83 int nSign = 1;
84 vector<int> vIndex;
85
86 // Look for command line parameters
87 if (findParameter(sSortingExpression, "desc"))
88 nSign = -1;
89
90 if (findParameter(sSortingExpression, "ignorecase"))
92
93 if (findParameter(sSortingExpression, "index"))
94 bReturnIndex = true;
95
96 // Prepare the indices
97 if (i2 == -1)
98 i2 = i1;
99
100 if (j2 == -1)
101 j2 = j1;
102
103 if (j2 >= sStrings.size())
104 j2 = sStrings.size() - 1;
105
106 // Create the sorting index
107 for (int i = i1; i <= i2; i++)
108 vIndex.push_back(i);
109
110 // Enter the quicksort algorithm
111 if (!findParameter(sSortingExpression, "cols", '=') && !findParameter(sSortingExpression, "c", '='))
112 {
113 // Sort everything
114 for (int i = j1; i <= j2; i++)
115 {
116 if (!qSort(&vIndex[0], i2-i1+1, i, 0, i2-i1, nSign))
117 {
118 throw SyntaxError(SyntaxError::CANNOT_SORT_DATA, "sort string" + sSortingExpression, SyntaxError::invalid_position);
119 }
120
121 // If the sorting index is requested,
122 // then only sort the first column and return
123 if (bReturnIndex)
124 {
125 break;
126 }
127
128 reorderColumn(vIndex, i1, i2, i);
129
130 // Re-create the plain index
131 for (int j = i1; j <= i2; j++)
132 vIndex[j] = j;
133 }
134 }
135 else
136 {
137 // Sort a column selection or sort hierarchically
138 string sCols = "";
139
140 // Extract the column definitions
141 if (findParameter(sSortingExpression, "cols", '='))
142 {
143 sCols = getArgAtPos(sSortingExpression, findParameter(sSortingExpression, "cols", '=')+4);
144 }
145 else
146 {
147 sCols = getArgAtPos(sSortingExpression, findParameter(sSortingExpression, "c", '=')+1);
148 }
149
150 // Decode the column definitions and apply the
151 // sorting algorithm it to the columns
152 while (sCols.length())
153 {
154 // Create a ColumnKeys object
155 ColumnKeys* keys = evaluateKeyList(sCols, j2-j1+1);
156
157 if (!keys)
158 throw SyntaxError(SyntaxError::CANNOT_SORT_DATA, "string() " + sSortingExpression, SyntaxError::invalid_position);
159
160 // The keys work as regular column indices, prepare them
161 if (keys->nKey[1] == -1)
162 keys->nKey[1] = keys->nKey[0]+1;
163
164 // Apply the sorting algorithm to every column in the range
165 // of the two keys
166 for (int j = keys->nKey[0]; j < keys->nKey[1]; j++)
167 {
168 if (!qSort(&vIndex[0], i2-i1+1, j+j1, 0, i2-i1, nSign))
169 {
170 throw SyntaxError(SyntaxError::CANNOT_SORT_DATA, "string() " + sSortingExpression, SyntaxError::invalid_position);
171 }
172
173 // Subkey list: sort hierarchically
174 if (keys->subkeys && keys->subkeys->subkeys)
175 {
176 if (!sortSubList(&vIndex[0], i2-i1+1, keys, i1, i2, j1, nSign, sStrings.size()))
177 {
178 delete keys;
179 throw SyntaxError(SyntaxError::CANNOT_SORT_CACHE, "string() " + sSortingExpression, SyntaxError::invalid_position);
180 }
181 }
182
183 // If the index is requested, stop the process here
184 if (bReturnIndex)
185 break;
186
187 // Reorder the columns
188 reorderColumn(vIndex, i1, i2, j+j1);
189
190 ColumnKeys* subKeyList = keys->subkeys;
191
192 // Apply the sorted index to every column in the subkey list
193 while (subKeyList)
194 {
195 if (subKeyList->nKey[1] == -1)
196 subKeyList->nKey[1] = subKeyList->nKey[0]+1;
197
198 for (int _j = subKeyList->nKey[0]; _j < subKeyList->nKey[1]; _j++)
199 {
200 reorderColumn(vIndex, i1, i2, _j+j1);
201 }
202
203 subKeyList = subKeyList->subkeys;
204 }
205
206 // Re-create the plain index
207 for (int _j = i1; _j <= i2; _j++)
208 vIndex[_j] = _j;
209 }
210
211 // Free the memory of the ColumnKeys object
212 delete keys;
213
214 if (bReturnIndex)
215 break;
216 }
217 }
218
219 // If the index was requested, increment every index by one
220 if (bReturnIndex)
221 {
222 for (int i = 0; i <= i2-i1; i++)
223 vIndex[i]++;
224 }
225
226 if (bError || !bReturnIndex)
227 return vector<int>();
228
229 return vIndex;
230}
231
232// Private member function to reorder a selected column based
233// upon the passed index
234void StringInternalMemory::reorderColumn(const vector<int>& vIndex, long long int i1, long long int i2, long long int j1)
235{
236 // Create new memory on the heap
237 string* sSortVector = new string[i2-i1+1];
238
239 // Copy the elements in the new order
240 // into the prepared memory
241 for (int i = 0; i <= i2-i1; i++)
242 {
243 sSortVector[i] = sStrings[j1][vIndex[i]];
244 }
245
246 // Copy the contents directly from the
247 // prepared in the new order
248 for (int i = 0; i <= i2-i1; i++)
249 {
250 sStrings[j1][i+i1] = sSortVector[i];
251 }
252
253 // Free the prepared memory
254 delete[] sSortVector;
255}
256
257
258
259
260// STRINGMEMORY IMPLEMENTATION
261
262// This member function is used for writing strings into the "string()" object
263bool StringMemory::writeString(const string& _sString, unsigned int _nthString, unsigned int nCol)
264{
265 // If this is the first string to be written
266 if (_stringIntMem.sStrings.empty())
267 {
268 // Only do something, if the source string is not empty
269 if (_sString.length())
270 {
271 // Prepare the storage if needed
272 for (unsigned int i = 0; i <= nCol; i++)
273 {
274 _stringIntMem.sStrings.push_back(vector<string>());
275 }
276 if (_nthString == string::npos)
277 {
278 _stringIntMem.sStrings[nCol].push_back(_sString);
279 }
280 else
281 {
282 _stringIntMem.sStrings[nCol].resize(_nthString+1,"");
283 _stringIntMem.sStrings[nCol][_nthString] = _sString;
284 }
285 }
286 return true;
287 }
288
289 // Add a new column, if needed
290 if (nCol >= _stringIntMem.sStrings.size())
291 {
292 for (unsigned int i = _stringIntMem.sStrings.size(); i <= nCol; i++)
293 _stringIntMem.sStrings.push_back(vector<string>());
294 }
295
296 // If the string shall be appended at the end or the current
297 // column is empty, add a new string element
298 if (_nthString == string::npos || !_stringIntMem.sStrings[nCol].size())
299 {
300 if (_sString.length())
301 _stringIntMem.sStrings[nCol].push_back(_sString);
302 return true;
303 }
304
305 // If the string is not empty but shall be written to a larger location
306 // than the storage size, resize the storage correspondingly
307 while (_nthString >= _stringIntMem.sStrings[nCol].size() && _sString.length())
308 _stringIntMem.sStrings[nCol].resize(_nthString+1, "");
309
310 // All other cases
311 if (!_sString.length() && _nthString+1 == _stringIntMem.sStrings[nCol].size())
312 {
313 // this is an empty string, and it allows to reduce the size of
314 // the storage
315 _stringIntMem.sStrings[nCol].pop_back();
316 while (_stringIntMem.sStrings[nCol].size() && !_stringIntMem.sStrings[nCol].back().length())
317 _stringIntMem.sStrings[nCol].pop_back();
318 }
319 else if (_nthString < _stringIntMem.sStrings[nCol].size())
320 _stringIntMem.sStrings[nCol][_nthString] = _sString;
321 return true;
322}
323
324// This member function is the interface to read strings from the "string()" object
325string StringMemory::readString(unsigned int _nthString, unsigned int nCol)
326{
327 // Ensure that the selected column exists
328 if (nCol >= _stringIntMem.sStrings.size())
329 return "";
330
331 // Select the string from the table
332 if (_nthString == string::npos)
333 {
334 if (_stringIntMem.sStrings[nCol].size())
335 return _stringIntMem.sStrings[nCol].back();
336
337 return "";
338 }
339 else if (_nthString >= _stringIntMem.sStrings[nCol].size())
340 return "";
341 else
342 return _stringIntMem.sStrings[nCol][_nthString];
343
344 return "";
345}
346
347// This member function returns the maximal string in the "string()" object
348// in the selected column
349string StringMemory::maxString(unsigned int i1, unsigned int i2, unsigned int nCol)
350{
351 // Ensure that the selected column exists
352 if (nCol >= _stringIntMem.sStrings.size())
353 return "";
354
355 // Fill the second line index automatically
356 if (i2 == string::npos || i2 > _stringIntMem.sStrings[nCol].size())
357 i2 = _stringIntMem.sStrings[nCol].size();
358
359 // Return an empty string, if the second column does not exist
360 if (!i2 || _stringIntMem.sStrings[nCol].empty())
361 return "";
362
363 string sMax = _stringIntMem.sStrings[nCol][i1];
364
365 // Search for the maximal string
366 for (unsigned int i = i1+1; i < i2; i++)
367 {
368 if (sMax < _stringIntMem.sStrings[nCol][i])
369 sMax = _stringIntMem.sStrings[nCol][i];
370 }
371
372 return sMax;
373}
374
375// This member function returns the maximal string in the "string()" object
376// in the selected column
378{
379 // Ensure that the selected column exists
380 if (_vCol.front() >= (int)_stringIntMem.sStrings.size())
381 return "";
382
383 // Fill the second line index automatically
384 if (_vLine.isOpenEnd() || _vLine.last() > (int)_stringIntMem.sStrings[_vCol.front()].size())
385 _vLine.setRange(0, _stringIntMem.sStrings[_vCol.front()].size()-1);
386
387 // Return an empty string, if the second column does not exist
388 if (!_vLine.last() || _stringIntMem.sStrings[_vCol.front()].empty())
389 return "";
390
391 string sMax = _stringIntMem.sStrings[_vCol.front()][_vLine[0]];
392
393 // Search for the maximal string
394 for (size_t i = 1; i < _vLine.size(); i++)
395 {
396 if (sMax < _stringIntMem.sStrings[_vCol.front()][_vLine[i]])
397 sMax = _stringIntMem.sStrings[_vCol.front()][_vLine[i]];
398 }
399
400 return sMax;
401}
402
403// This member function returns the minimal string in the "string()" object
404// in the selected column
405string StringMemory::minString(unsigned int i1, unsigned int i2, unsigned int nCol)
406{
407 // Ensure that the selected column exists
408 if (nCol >= _stringIntMem.sStrings.size())
409 return "";
410
411 // Fill the second line index automatically
412 if (i2 == string::npos || i2 > _stringIntMem.sStrings[nCol].size())
413 i2 = _stringIntMem.sStrings[nCol].size();
414
415 // Return an empty string, if the second column does not exist
416 if (!i2 || _stringIntMem.sStrings[nCol].empty())
417 return "";
418
419 string sMin = _stringIntMem.sStrings[nCol][i1];
420
421 // Search for the minimal string
422 for (unsigned int i = i1+1; i < i2; i++)
423 {
424 if (sMin > _stringIntMem.sStrings[nCol][i])
425 sMin = _stringIntMem.sStrings[nCol][i];
426 }
427
428 return sMin;
429}
430
431// This member function returns the minimal string in the "string()" object
432// in the selected column
434{
435 // Ensure that the selected column exists
436 if (_vCol.front() >= (int)_stringIntMem.sStrings.size())
437 return "";
438
439 // Fill the second line index automatically
440 if (_vLine.isOpenEnd() || _vLine.last() > (int)_stringIntMem.sStrings[_vCol.front()].size())
441 _vLine.setRange(0, _stringIntMem.sStrings[_vCol.front()].size()-1);
442
443 // Return an empty string, if the second column does not exist
444 if (!_vLine.last() || _stringIntMem.sStrings[_vCol.front()].empty())
445 return "";
446
447 string sMin = _stringIntMem.sStrings[_vCol.front()][_vLine[0]];
448
449 // Search for the minimal string
450 for (size_t i = 1; i < _vLine.size(); i++)
451 {
452 if (sMin > _stringIntMem.sStrings[_vCol.front()][_vLine[i]])
453 sMin = _stringIntMem.sStrings[_vCol.front()][_vLine[i]];
454 }
455
456 return sMin;
457}
458
459// This member function concatenates the strings in the "string()" object
460// in the selected range and returns it
461string StringMemory::sumString(unsigned int i1, unsigned int i2, unsigned int nCol)
462{
463 // Ensure that the selected column exists
464 if (nCol >= _stringIntMem.sStrings.size())
465 return "";
466
467 // Fill the second line index automatically
468 if (i2 == string::npos || i2 > _stringIntMem.sStrings[nCol].size())
469 i2 = _stringIntMem.sStrings[nCol].size();
470
471 // Return an empty string, if the second column does not exist
472 if (!i2 || _stringIntMem.sStrings[nCol].empty())
473 return "";
474
475 string sSum = "";
476
477 // Concatenate the strings
478 for (unsigned int i = i1; i < i2; i++)
479 {
480 sSum += _stringIntMem.sStrings[nCol][i];
481 }
482
483 return sSum;
484}
485
486// This member function concatenates the strings in the "string()" object
487// in the selected range and returns it
489{
490 // Ensure that the selected column exists
491 if (_vCol.front() >= (int)_stringIntMem.sStrings.size())
492 return "";
493
494 // Fill the second line index automatically
495 if (_vLine.isOpenEnd() || _vLine.last() > (int)_stringIntMem.sStrings[_vCol.front()].size())
496 _vLine.setRange(0, _stringIntMem.sStrings[_vCol.front()].size()-1);
497
498 // Return an empty string, if the second column does not exist
499 if (!_vLine.last() || _stringIntMem.sStrings[_vCol.front()].empty())
500 return "";
501
502 string sSum = "";
503
504 // Concatenate the strings
505 for (size_t i = 0; i < _vLine.size(); i++)
506 {
507 sSum += _stringIntMem.sStrings[_vCol.front()][_vLine[i]];
508 }
509
510 return sSum;
511}
std::string toLowerCase(const std::string &)
Converts uppercase to lowercase letters.
ColumnKeys * evaluateKeyList(std::string &sKeyList, long long int nColumnCount)
This public member function creates a ColumnKeys object from a string containing the hierarchical sor...
Definition: sorter.cpp:252
bool qSort(int *nIndex, int nElements, int nColumn, long long int nLeft, long long int nRight, int nSign)
This public member function is the interface to the quicksort algorithm, which itself is implemented ...
Definition: sorter.cpp:40
bool sortSubList(int *nIndex, int nElements, ColumnKeys *KeyList, long long int i1, long long int i2, long long int j1, int nSign, long long int nColumns)
This public member function handles the hierarchical sorting process of many columns together....
Definition: sorter.cpp:196
virtual int compare(int i, int j, int col) override
std::vector< int > sortElements(long long int i1, long long int i2, long long int j1, long long int j2, const std::string &sSortingExpression)
std::vector< std::vector< std::string > > sStrings
virtual bool isValue(int line, int col) override
void reorderColumn(const std::vector< int > &vIndex, long long int i1, long long int i2, long long int j1=0)
bool writeString(const std::string &_sString, unsigned int _nthString=std::string::npos, unsigned int nCol=0)
StringInternalMemory _stringIntMem
std::string maxString(unsigned int i1=0, unsigned int i2=std::string::npos, unsigned int nCol=0)
std::string readString(unsigned int _nthString=std::string::npos, unsigned int nCol=0)
std::string minString(unsigned int i1=0, unsigned int i2=std::string::npos, unsigned int nCol=0)
std::string sumString(unsigned int i1=0, unsigned int i2=std::string::npos, unsigned int nCol=0)
Common exception class for all exceptions thrown in NumeRe.
Definition: error.hpp:32
@ CANNOT_SORT_CACHE
Definition: error.hpp:84
@ CANNOT_SORT_DATA
Definition: error.hpp:85
static size_t invalid_position
Definition: error.hpp:235
This class abstracts all the index logics, i.e. the logical differences between single indices and in...
Definition: structures.hpp:42
int last() const
This member function returns the last index value, which can be reached by the values stored internal...
Definition: structures.hpp:693
size_t size() const
This member function returns the size of the indices stored in this class.
Definition: structures.hpp:314
bool isOpenEnd() const
This member function determines, whether the internal index set has an open end.
Definition: structures.hpp:614
void setRange(int nMin, int nMax)
This member function can be used to force the indices stored internally to be in a defined interval....
Definition: structures.hpp:712
int & front()
This member function returns a reference to the first index value stored internally.
Definition: structures.hpp:640
int findParameter(const std::string &sCmd, const std::string &sParam, const char cFollowing)
This function searches the passed parameter in the passed command string. If something is found,...
Definition: tools.cpp:113
Structure for the sorting functionality: used for the recursive definition of the index columns for s...
ColumnKeys * subkeys
string getArgAtPos(const string &sCmd, unsigned int nPos, int extraction)
Extracts a options value at the selected position and applies automatic parsing, if necessary.
Definition: tools.cpp:1598