GammaLib 2.0.0
Loading...
Searching...
No Matches
GFitsTableStringCol.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GFitsTableStringCol.cpp - FITS table string column class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2010-2021 by Juergen Knoedlseder *
5 * ----------------------------------------------------------------------- *
6 * *
7 * This program is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 * *
20 ***************************************************************************/
21/**
22 * @file GFitsTableStringCol.cpp
23 * @brief FITS table string column class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <cstring> // std::strncpy, etc...
32#include <string>
33#include "GException.hpp"
34#include "GTools.hpp"
35#include "GFitsCfitsio.hpp"
37
38/* __ Method name definitions ____________________________________________ */
39#define G_INSERT "GFitsTableStringCol::insert(int&, int&)"
40#define G_REMOVE "GFitsTableStringCol::remove(int&, int&)"
41
42/* __ Macros _____________________________________________________________ */
43
44/* __ Coding definitions _________________________________________________ */
45
46/* __ Debug definitions __________________________________________________ */
47
48
49/*==========================================================================
50 = =
51 = Constructors/destructors =
52 = =
53 ==========================================================================*/
54
55/***********************************************************************//**
56 * @brief Constructor
57 ***************************************************************************/
59{
60 // Initialise class members for clean destruction
62
63 // Return
64 return;
65}
66
67
68/***********************************************************************//**
69 * @brief Constructor
70 *
71 * @param[in] name Name of column.
72 * @param[in] nrows Number of rows in column.
73 * @param[in] width Length of individual string.
74 * @param[in] size Number of strings in each column.
75 ***************************************************************************/
77 const int& nrows,
78 const int& width,
79 const int& size) :
80 GFitsTableCol(name, nrows, size, width)
81{
82 // Initialise class members for clean destruction
84
85 // Return
86 return;
87}
88
89
90/***********************************************************************//**
91 * @brief Copy constructor
92 *
93 * @param[in] column Table column.
94 ***************************************************************************/
96 GFitsTableCol(column)
97{
98 // Initialise class members for clean destruction
100
101 // Copy members
102 copy_members(column);
103
104 // Return
105 return;
106}
107
108
109/***********************************************************************//**
110 * @brief Destructor
111 ***************************************************************************/
113{
114 // Free members
115 free_members();
116
117 // Return
118 return;
119}
120
121
122/*==========================================================================
123 = =
124 = Operators =
125 = =
126 ==========================================================================*/
127
128/***********************************************************************//**
129 * @brief Assignment operator
130 *
131 * @param[in] column Table column.
132 * @return Table column.
133 ***************************************************************************/
135{
136 // Execute only if object is not identical
137 if (this != &column) {
138
139 // Copy base class members
140 this->GFitsTableCol::operator=(column);
141
142 // Free members
143 free_members();
144
145 // Initialise private members for clean destruction
146 init_members();
147
148 // Copy members
149 copy_members(column);
150
151 } // endif: object was not identical
152
153 // Return this object
154 return *this;
155}
156
157
158/***********************************************************************//**
159 * @brief Column data access operator
160 *
161 * @param[in] row Row of column to access.
162 * @param[in] inx Vector index in column row to access.
163 *
164 * Provides access to data in a column.
165 ***************************************************************************/
166std::string& GFitsTableStringCol::operator()(const int& row, const int& inx)
167{
168 // If data are not available then load them now
169 if (m_data == NULL) fetch_data();
170
171 // Return data bin
172 return m_data[offset(row, inx)];
173}
174
175
176/***********************************************************************//**
177 * @brief Column data access operator (const variant)
178 *
179 * @param[in] row Row of column to access.
180 * @param[in] inx Vector index in column row to access.
181 *
182 * Provides access to data in a column.
183 ***************************************************************************/
184const std::string& GFitsTableStringCol::operator()(const int& row, const int& inx) const
185{
186 // If data are not available then load them now
187 if (m_data == NULL) fetch_data();
188
189 // Return data bin
190 return m_data[offset(row, inx)];
191}
192
193
194/*==========================================================================
195 = =
196 = Public methods =
197 = =
198 ==========================================================================*/
199
200/***********************************************************************//**
201 * @brief Clear instance
202 *
203 * This method properly resets the object to an initial state.
204 ***************************************************************************/
206{
207 // Free class members (base and derived classes, derived class first)
208 free_members();
210
211 // Initialise members
213 init_members();
214
215 // Return
216 return;
217}
218
219
220/***********************************************************************//**
221 * @brief Clone column
222 ***************************************************************************/
224{
225 return new GFitsTableStringCol(*this);
226}
227
228
229/***********************************************************************//**
230 * @brief Get string value
231 *
232 * @param[in] row Table row.
233 * @param[in] inx Table column vector index.
234 *
235 * Returns value of specified row and vector index as string.
236 ***************************************************************************/
237std::string GFitsTableStringCol::string(const int& row, const int& inx) const
238{
239 // If data are not available then load them now
240 if (m_data == NULL) fetch_data();
241
242 // Return value
243 return m_data[offset(row,inx)];
244}
245
246
247/***********************************************************************//**
248 * @brief Get double precision value
249 *
250 * @param[in] row Table row.
251 * @param[in] inx Table column vector index.
252 *
253 * Returns value of specified row and vector index as double precision.
254 ***************************************************************************/
255double GFitsTableStringCol::real(const int& row, const int& inx) const
256{
257 // If data are not available then load them now
258 if (m_data == NULL) fetch_data();
259
260 // Assign string to double
261 double value = gammalib::todouble(m_data[offset(row,inx)]);
262
263 // Return value
264 return value;
265}
266
267
268/***********************************************************************//**
269 * @brief Get integer value
270 *
271 * @param[in] row Table row.
272 * @param[in] inx Table column vector index.
273 *
274 * Returns value of specified row and vector index as integer.
275 ***************************************************************************/
276int GFitsTableStringCol::integer(const int& row, const int& inx) const
277{
278 // If data are not available then load them now
279 if (m_data == NULL) fetch_data();
280
281 // Assign string to int
282 int value = gammalib::toint(m_data[offset(row,inx)]);
283
284 // Return value
285 return value;
286}
287
288
289/***********************************************************************//**
290 * @brief Insert rows in column
291 *
292 * @param[in] row Row after which rows should be inserted (0=first row).
293 * @param[in] nrows Number of rows to be inserted.
294 *
295 * @exception GException::out_of_range
296 * Specified row is invalid.
297 *
298 * Inserts rows into a FITS table. This implies that all columns will be
299 * loaded into memory.
300 ***************************************************************************/
301void GFitsTableStringCol::insert(const int& row, const int& nrows)
302{
303 // Make sure that row is valid
304 if (row < 0 || row > m_length) {
305 throw GException::out_of_range(G_INSERT, "FITS table row number",
306 row, m_length+1);
307 }
308
309 // Continue only if there are rows to be inserted
310 if (nrows > 0) {
311
312 // If we have no rows yet then simply set the length to the
313 // number of rows to be inserted
314 if (m_length == 0) {
315 m_length = nrows;
317 alloc_data();
318 init_data();
319 }
320
321 // ... otherwise fetch data, allocate new data and copy over
322 // the existing items
323 else {
324
325 // If data are not available then load them now
326 if (m_data == NULL) fetch_data();
327
328 // Compute new column length
329 int length = m_length + nrows;
330
331 // Calculate size of new memory
332 m_size = m_number * length;
333
334 // Allocate new data to hold the column
335 std::string* new_data = new std::string[m_size];
336
337 // Compute the number of elements before the insertion point,
338 // the number of elements that get inserted, and the total
339 // number of elements after the insertion point
340 int n_before = m_number * row;
341 int n_insert = m_number * nrows;
342 int n_after = m_number * (m_length - row);
343
344 // Copy and initialise data
345 std::string* src = m_data;
346 std::string* dst = new_data;
347 for (int i = 0; i < n_before; ++i) {
348 *dst++ = *src++;
349 }
350 for (int i = 0; i < n_insert; ++i) {
351 dst->clear();
352 dst++;
353 }
354 for (int i = 0; i < n_after; ++i) {
355 *dst++ = *src++;
356 }
357
358 // Free old data
359 if (m_data != NULL) delete [] m_data;
360
361 // Set pointer to new data and store length
362 m_data = new_data;
363 m_length = length;
364
365 } // endelse: there were already data
366
367 } // endfor: there were rows to be inserted
368
369 // Return
370 return;
371}
372
373
374/***********************************************************************//**
375 * @brief Remove rows from column
376 *
377 * @param[in] row Row after which rows should be removed (0=first row).
378 * @param[in] nrows Number of rows to be removed.
379 *
380 * @exception GException::out_of_range
381 * Specified row is invalid.
382 * Invalid number of rows specified.
383 *
384 * This method removes rows from a FITS table. This implies that the column
385 * will be loaded into memory.
386 ***************************************************************************/
387void GFitsTableStringCol::remove(const int& row, const int& nrows)
388{
389 // Make sure that row is valid
390 if (row < 0 || row >= m_length) {
391 throw GException::out_of_range(G_REMOVE, "FITS table row number",
392 row, m_length);
393 }
394
395 // Make sure that we don't remove beyond the limit
397 throw GException::out_of_range(G_REMOVE, "Number of FITS table rows",
398 nrows, m_length-row+1);
399 }
400
401 // Continue only if there are rows to be removed
402 if (nrows > 0) {
403
404 // If data are not available then load them now
405 if (m_data == NULL) fetch_data();
406
407 // Compute new column length
408 int length = m_length - nrows;
409
410 // Calculate size of new memory
411 m_size = m_number * length;
412
413 // If we have rows remaining then allocate new data to hold
414 // the column
415 if (m_size > 0) {
416
417 // Allocate new data to hold the column
418 std::string* new_data = new std::string[m_size];
419
420 // Compute the number of elements before the removal point,
421 // the number of elements that get removed, and the total
422 // number of elements after the removal point
423 int n_before = m_number * row;
424 int n_remove = m_number * nrows;
425 int n_after = m_number * (length - row);
426
427 // Copy data
428 std::string* src = m_data;
429 std::string* dst = new_data;
430 for (int i = 0; i < n_before; ++i) {
431 *dst++ = *src++;
432 }
433 src += n_remove;
434 for (int i = 0; i < n_after; ++i) {
435 *dst++ = *src++;
436 }
437
438 // Free old data
439 if (m_data != NULL) delete [] m_data;
440
441 // Set pointer to new data and store length
442 m_data = new_data;
443 m_length = length;
444
445 } // endif: there are still elements after removal
446
447 // ... otherwise just remove all data
448 else {
449
450 // Free old data
451 if (m_data != NULL) delete [] m_data;
452
453 // Set pointer to new data and store length
454 m_data = NULL;
455 m_length = length;
456 }
457
458 } // endfor: there were rows to be removed
459
460 // Return
461 return;
462}
463
464
465/***********************************************************************//**
466 * @brief Set nul value
467 *
468 * @param[in] value Nul value string.
469 *
470 * Allows the specification of the FITS table nul string. The default nul
471 * strings is an empty string which results in NULL entries in case that
472 * no data has been written.
473 *
474 * @todo To correctly reflect the nul value in the data, the column should
475 * be reloaded. However, the column may have been changed, so in principle
476 * saving is needed. However, we may not want to store the data, hence saving
477 * is also not desired. We thus have to develop a method to update the
478 * column information for a new nul value in place ...
479 ***************************************************************************/
480void GFitsTableStringCol::nulval(const std::string& value)
481{
482 // Allocate nul value
483 alloc_nulval(value);
484
485 // Update column
486// if (m_data != NULL) {
487// save();
488// load();
489// }
490
491 // Return
492 return;
493}
494
495
496/*==========================================================================
497 = =
498 = Private methods =
499 = =
500 ==========================================================================*/
501
502/***********************************************************************//**
503 * @brief Initialise class members
504 ***************************************************************************/
506{
507 // Initialise members
509 m_data = NULL;
510 m_buffer = NULL;
511 m_nulval = NULL;
512
513 // Initialise nul value
514 alloc_nulval("");
515
516 // Return
517 return;
518}
519
520
521/***********************************************************************//**
522 * @brief Copy class members
523 *
524 * @param[in] column Column.
525 *
526 * Sets the content of the vector column by copying from another column.
527 * If the code is compiled with the small memory option, and if the source
528 * column has not yet been loaded, then we only load the column temporarily
529 * for copying purposes and release it again once copying is finished.
530 ***************************************************************************/
532{
533 // Fetch data if necessary
534 bool not_loaded = (!column.is_loaded());
535 if (not_loaded) {
536 column.fetch_data();
537 }
538
539 // Copy attributes
540 m_type = column.m_type;
541 m_size = column.m_size;
542 m_varlen = column.m_varlen;
543 m_rowstart = column.m_rowstart;
544
545 // Copy column data
546 if (column.m_data != NULL && m_size > 0) {
547 if (m_data != NULL) delete [] m_data;
548 m_data = new std::string[m_size];
549 for (int i = 0; i < m_size; ++i) {
550 m_data[i] = column.m_data[i];
551 }
552 }
553
554 // Copy NULL value
555 if (column.m_nulval != NULL) {
556 if (m_nulval != NULL) delete [] m_nulval;
557 m_nulval = new char[m_width+1];
558 std::strncpy(m_nulval, column.m_nulval, m_width);
559 }
560
561 // Small memory option: release column if it was fetch above
562 #if defined(G_SMALL_MEMORY)
563 if (not_loaded) {
564 const_cast<GFitsTableStringCol*>(&column)->release_data();
565 }
566 #endif
567
568 // Return
569 return;
570}
571
572
573/***********************************************************************//**
574 * @brief Delete class members
575 ***************************************************************************/
577{
578 // Free memory
579 if (m_data != NULL) delete [] m_data;
580 if (m_nulval != NULL) delete [] m_nulval;
581
582 // Mark memory as freed
583 m_data = NULL;
584 m_nulval = NULL;
585
586 // Reset load flag
587 m_size = 0;
588
589 // Free buffer
590 free_buffer();
591
592 // Return
593 return;
594}
595
596
597/***********************************************************************//**
598 * @brief Save table column into FITS file
599 *
600 * The data is transferred from the internal string vector into a character
601 * transfer buffer that can be handled by the cfitsio routines.
602 *
603 * The table column is only saved if it is linked to a FITS file and if the
604 * data are indeed present in the class instance. This avoids saving of data
605 * that have not been modified.
606 *
607 * Refer to GFitsTableCol::save_column() for more information.
608 ***************************************************************************/
610{
611 // Free buffer
612 free_buffer();
613
614 // Allocate buffer. This also fills the entire buffer with '\0'
615 // characters.
616 alloc_buffer();
617
618 // Transfer string into buffer
619 for (int i = 0; i < m_size; ++i) {
620 if (m_data[i].length() > 0) {
621 std::strncpy(m_buffer[i], m_data[i].c_str(), m_width);
622 }
623 }
624
625 // Save column
626 save_column();
627
628 // Free buffer
629 free_buffer();
630
631 // Return
632 return;
633}
634
635
636/***********************************************************************//**
637 * @brief Returns format string of ASCII table
638 ***************************************************************************/
640{
641 // Initialize format string
642 std::string format;
643
644 // Set type code
645 format.append("A");
646
647 // Set width
648 format.append(gammalib::str(m_width));
649
650 // Return format
651 return format;
652}
653
654
655/***********************************************************************//**
656 * @brief Allocates column data
657 ***************************************************************************/
659{
660 // Free memory
661 if (m_data != NULL) delete [] m_data;
662
663 // Mark pointer as free
664 m_data = NULL;
665
666 // Allocate new data
667 if (m_size > 0) {
668 m_data = new std::string[m_size];
669 }
670
671 // Allocate also buffer
672 free_buffer();
673 alloc_buffer();
674
675 // Return
676 return;
677}
678
679
680/***********************************************************************//**
681 * @brief Fetch column data
682 *
683 * If a FITS file is attached to the column the data are loaded into memory
684 * from the FITS file. If no FITS file is attached, memory is allocated
685 * to hold the column data and all cells are set to 0.
686 *
687 * Refer to GFitsTableCol::load_column for more information.
688 ***************************************************************************/
690{
691 // Calculate size of memory
692 //m_size = m_number * m_length;
693
694 // Free old buffer memory
695 //free_buffer();
696
697 // Allocate buffer memory
698 //alloc_buffer();
699
700 // Load column
701 const_cast<GFitsTableStringCol*>(this)->load_column();
702
703 // Extract string from buffer
704 for (int i = 0; i < m_size; ++i) {
705 if (m_buffer[i] != NULL) {
706 m_data[i].assign(m_buffer[i]);
707 }
708 }
709
710 // Free buffer memory
711 free_buffer();
712
713 // Return
714 return;
715}
716
717
718/***********************************************************************//**
719 * @brief Resize column data
720 *
721 * @param[in] index Start index.
722 * @param[in] number Number of elements to add/remove.
723 *
724 * Adds or removes elements from specified index on. Adding is done if
725 * @p number is a positive number, removing if @p number is negative.
726 * Note that the method does not change the validity of the arguments.
727 * This needs to be done by the client.
728 ***************************************************************************/
729void GFitsTableStringCol::resize_data(const int& index, const int& number)
730{
731 // Continue only if number of elements is not zero
732 if (number != 0) {
733
734 // If data are not available then load them now
735 if (m_data == NULL) fetch_data();
736
737 // If elements should be removed then do not allocate new memory
738 // but just move elements forward and change the logical size of
739 // memory. Only if all elements should be removed the memory is
740 // released.
741 if (number < 0) {
742 int left = index - number;
743 std::string* dst = m_data + index;
744 std::string* src = m_data + left;
745 int num = m_size - left;
746 for (int i = 0; i < num; ++i) {
747 *dst++ = *src++;
748 }
749 m_size += number;
750 if (m_size < 1) {
751 release_data();
752 }
753 }
754
755 // If elements should be added then allocate new memory, copy over
756 // the old data and initialise the new elements
757 else {
758 int left = m_size - index;
759 m_size += number;
760 std::string* new_data = new std::string[m_size];
761 std::string* dst = new_data;
762 std::string* src = m_data;
763 for (int i = 0; i < index; ++i) {
764 *dst++ = *src++;
765 }
766 for (int i = 0; i < number; ++i) {
767 *dst++ = "";
768 }
769 for (int i = 0; i < left; ++i) {
770 *dst++ = *src++;
771 }
772 if (m_data != NULL) delete [] m_data;
773 m_data = new_data;
774 }
775
776 } // endif: number was non-zero
777
778 // Return
779 return;
780}
781
782
783/***********************************************************************//**
784 * @brief Release column data
785 ***************************************************************************/
787{
788 // Free any existing memory
789 if (m_data != NULL) delete [] m_data;
790
791 // Mark pointer as free and reset loaded vector size
792 m_data = NULL;
793 m_size = 0;
794
795 // Return
796 return;
797}
798
799
800/***********************************************************************//**
801 * @brief Allocate nul value
802 *
803 * @param[in] value Nul value string.
804 ***************************************************************************/
805void GFitsTableStringCol::alloc_nulval(const std::string& value)
806{
807 // Free any existing memory
808 if (m_nulval != NULL) delete [] m_nulval;
809
810 // Mark pointer as free
811 m_nulval = NULL;
812
813 // Allocate and initialise nul value
814 m_nulval = new char[m_width+1];
815 for (int j = 0; j <= m_width; ++j) {
816 m_nulval[j] = '\0';
817 }
818
819 // Set nul value
820 std::strncpy(m_nulval, value.c_str(), m_width);
821
822 // Return
823 return;
824}
825
826
827/***********************************************************************//**
828 * @brief Initialise column data
829 ***************************************************************************/
831{
832 // Initialise data if they exist
833 if (m_data != NULL) {
834 for (int i = 0; i < m_size; ++i) {
835 m_data[i].clear();
836 }
837 }
838
839 // Return
840 return;
841}
842
843
844/***********************************************************************//**
845 * @brief Allocate CFITSIO transfer buffer
846 *
847 * The CFITSIO transfer buffer allows transparent conversion from the CFITSIO
848 * storage format to a vector of strings.
849 ***************************************************************************/
851{
852 // Allocate buffer memory
853 if (m_size > 0) {
854 m_buffer = new char*[m_size];
855 for (int i = 0; i < m_size; ++i) {
856 m_buffer[i] = new char[m_width+1];
857 }
858 }
859
860 // Initialise buffer
861 if (m_buffer != NULL) {
862 for (int i = 0; i < m_size; ++i) {
863 for (int j = 0; j <= m_width; ++j) {
864 (m_buffer[i])[j] = '\0';
865 }
866 }
867 }
868
869 // Return
870 return;
871}
872
873
874/***********************************************************************//**
875 * @brief Free CFITSIO transfer buffer
876 *
877 * Release memory that has been allocated for the CFITSIO transfer buffer.
878 ***************************************************************************/
880{
881 // If there was a buffer allocated then free it
882 if (m_buffer != NULL) {
883 for (int i = 0; i < m_size; ++i) {
884 if (m_buffer[i] != NULL) delete [] m_buffer[i];
885 }
886 delete [] m_buffer;
887 m_buffer = NULL;
888 }
889
890 // Return
891 return;
892}
Exception handler interface definition.
CFITSIO interface header.
#define __TSTRING
#define G_INSERT
#define G_REMOVE
FITS table string column class interface definition.
Gammalib tools definition.
Abstract interface for FITS table column.
int m_type
Column type.
int m_length
Length of column (number of rows)
const int & nrows(void) const
Returns number of rows in column.
std::vector< int > m_rowstart
Start index of each row.
int m_size
Size of allocated data area (0 if not loaded)
int m_width
Width in Bytes of single column element.
int m_varlen
Maximum number of elements in variable-length.
GFitsTableCol & operator=(const GFitsTableCol &column)
Assignment operator.
const int & number(void) const
Returns number of elements in column.
void free_members(void)
Delete class members.
virtual void save_column(void)
Save table column into FITS file.
virtual void load_column(void)
Load table column from FITS file.
void init_members(void)
Initialise class members.
virtual int offset(const int &row, const int &inx) const
Compute offset of column element in memory.
int m_number
Number of elements in column.
FITS table string column.
virtual void insert(const int &row, const int &nrows)
Insert rows in column.
virtual void resize_data(const int &index, const int &number)
Resize column data.
virtual ~GFitsTableStringCol(void)
Destructor.
virtual bool is_loaded(void) const
Checks if column has been loaded.
std::string & operator()(const int &row, const int &inx=0)
Column data access operator.
char ** m_buffer
Data area for CFITSIO transfer.
virtual void fetch_data(void) const
Fetch column data.
virtual void clear(void)
Clear instance.
void free_members(void)
Delete class members.
virtual std::string string(const int &row, const int &col=0) const
Get string value.
std::string * m_data
Data area.
virtual void release_data(void)
Release column data.
GFitsTableStringCol & operator=(const GFitsTableStringCol &column)
Assignment operator.
GFitsTableStringCol(void)
Constructor.
void free_buffer(void) const
Free CFITSIO transfer buffer.
char * m_nulval
NULL string.
virtual double real(const int &row, const int &col=0) const
Get double precision value.
void init_members(void)
Initialise class members.
virtual void save(void)
Save table column into FITS file.
char * nulval(void)
Returns pointer to nul value.
virtual GFitsTableStringCol * clone(void) const
Clone column.
virtual void alloc_data(void)
Allocates column data.
virtual int integer(const int &row, const int &col=0) const
Get integer value.
void alloc_nulval(const std::string &value)
Allocate nul value.
void alloc_buffer(void) const
Allocate CFITSIO transfer buffer.
virtual std::string ascii_format(void) const
Returns format string of ASCII table.
virtual void remove(const int &row, const int &nrows)
Remove rows from column.
void copy_members(const GFitsTableStringCol &column)
Copy class members.
virtual void init_data(void)
Initialise column data.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
double todouble(const std::string &arg)
Convert string into double precision value.
Definition GTools.cpp:926
int toint(const std::string &arg)
Convert string into integer value.
Definition GTools.cpp:821