STK++ 0.9.13
STK_ReadWriteCsv.h
Go to the documentation of this file.
1/*--------------------------------------------------------------------*/
2/* Copyright (C) 2004-2016 Serge Iovleff, Université Lille 1, Inria
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this program; if not, write to the
16 Free Software Foundation, Inc.,
17 59 Temple Place,
18 Suite 330,
19 Boston, MA 02111-1307
20 USA
21
22 Contact : S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
23*/
24
25/*
26 * Project: stkpp::DManager
27 * Purpose: Declaration of the class ReaWriteCsv.
28 * Author: Serge Iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
29 *
30 **/
31
38#ifndef STK_READWRITECSV_H
39#define STK_READWRITECSV_H
40
41#include <iomanip>
44#include "STK_Variable.h"
45
46namespace STK
47{
48
49template<typename Type> class TReadWriteCsv;
50
52
56namespace Csv
57{
60 static const bool DEFAULT_READNAMES = true;
63 static const bool DEFAULT_MAPPING = false;
66 static const bool DEFAULT_LAST_NL = true;
69 static const int DEFAULT_RESERVE = int(0x0FFFF);
72 static const String DEFAULT_DELIMITER = _T(",");
75 static const String ERRORCODES[] =
76 {
77 _T(""), // no message
78 _T("An unknown error occurred!"),
79 _T("Variable name not found!"),
80 _T("Filename not set!"),
81 _T("File not found!"),
82 _T("The Number of names is different from the Number of Data Columns!")
83 };
88 {
89 RW_APPEND_DATA = 0x00000004,
90 RW_REPLACE_DATA = 0x00000008
91 };
92}
93
106template<typename Type>
108{
109 public:
115 , with_names_(Csv::DEFAULT_READNAMES)
116 , with_mapping_(Csv::DEFAULT_MAPPING)
117 , with_last_nl_(Csv::DEFAULT_LAST_NL)
118 , delimiters_(Csv::DEFAULT_DELIMITER)
119 , reserve_(Csv::DEFAULT_RESERVE)
120 , msg_error_()
121 , nbVars_(0)
122 , nbRows_(0)
123
124 {}
133 inline TReadWriteCsv( std::string const& file_name
134 , bool read_names = Csv::DEFAULT_READNAMES
135 , String const& delimiters = Csv::DEFAULT_DELIMITER
136 )
139 , with_mapping_(Csv::DEFAULT_MAPPING)
140 , with_last_nl_(Csv::DEFAULT_LAST_NL)
142 , reserve_(Csv::DEFAULT_RESERVE)
143 , msg_error_()
144 , nbVars_(0)
145 , nbRows_(0)
146 {}
151 inline TReadWriteCsv(TReadWriteCsv const& rw) { *this = rw;}
153 inline ~TReadWriteCsv() {}
155 void clear()
156 {
157 msg_error_.clear();
158 str_data_.clear();
159 with_names_ = Csv::DEFAULT_READNAMES;
160 with_mapping_ = Csv::DEFAULT_MAPPING;
161 with_last_nl_ = Csv::DEFAULT_LAST_NL;
162 delimiters_ = Csv::DEFAULT_DELIMITER;
163 reserve_ = Csv::DEFAULT_RESERVE;
164 }
166 inline int begin() const { return str_data_.begin(); }
168 inline int end() const { return str_data_.end(); }
170 inline int size() const { return str_data_.size(); }
171
173 inline Range cols() const { return str_data_.range(); }
175 inline int beginCols() const { return str_data_.begin(); }
177 inline int endCols() const { return str_data_.end(); }
179 inline int sizeCols() const { return str_data_.size(); }
180
184 inline int firstRow( int icol) const { return str_data_.at(icol).begin();}
188 inline int endRow( int icol) const { return str_data_.at(icol).end();}
192 inline int lastRow( int icol) const { return str_data_.at(icol).lastIdx();}
196 inline int sizeRow( int icol) const { return str_data_.at(icol).size();}
198 inline int beginRows() const
199 {
200 if (size()<= 0) return baseIdx;
201 int retVal = firstRow(begin());
202 for (int i=begin()+1; i<=lastIdx(); i++)
203 { retVal = std::min(retVal, firstRow(i));}
204 return retVal;
205 }
207 inline int endRows() const
208 {
209 if (size()<= 0) return baseIdx;
210 int retVal = lastRow(begin());
211 for (int i=begin()+1; i<end(); i++)
212 { retVal = std::max(retVal, endRow(i));}
213 return retVal;
214 }
216 inline int sizeRows() const
217 {
218 if (size()<= 0) return 0;
219 int retVal = sizeRow(begin());
220 for (int i=begin()+1; i<end(); i++)
221 { retVal = std::max(retVal, sizeRow(i));}
222 return retVal;
223 }
225 inline int lastIdxRows() const
226 {
227 if (size()<= 0) return baseIdx-1;
228 int retVal = lastRow(begin());
229 for (int i=begin()+1; i<end(); i++)
230 { retVal = std::max(retVal, lastRow(i));}
231 return retVal;
232 }
234 inline Range rows() const { return Range(beginRows(), lastIdxRows(), 0); }
235
237 inline int lastIdx() const { return str_data_.lastIdx(); }
239 inline int lastIdxCols() const { return str_data_.lastIdx(); }
240
242 inline String const& error() const { return msg_error_; }
244 inline String const& delimiters() const { return delimiters_; }
246 inline bool withNames() const { return with_names_; }
250 inline void setDelimiters( String const& delimiters) const { delimiters_ = delimiters; }
254 inline void setWithNames( bool with_names) const { with_names_ = with_names; }
262 inline void setLast_nl( bool with_last_nl) const { with_last_nl_ = with_last_nl; }
266 inline void setReserve( int const& reserve) const { reserve_ = reserve; }
268 inline void setInMapping( std::map<String, Type> const& imapping)
269 { imapping_ = imapping;}
271 inline void setOutMapping( std::map<String, Type> const& omapping)
272 { omapping_ = omapping;}
278 bool setName( int const& icol, String const& name)
279 {
280 try
281 {
282 str_data_.at(icol).setName(name);
283 return true;
284 }
285 catch( Exception const& e) { msg_error_ = e.error(); }
286 catch(...) { msg_error_ = Csv::ERRORCODES[1]; }
287 return false;
288 }
289
294 inline Type& operator()( int const& iRow, int const& iCol)
295 { return str_data_.elt(iCol).elt(iRow);}
300 inline Type const operator()( int const& iRow, int const& iCol) const
301 { return str_data_.elt(iCol).elt(iRow);}
305 inline Var* clone(int icol) const { return str_data_.elt(icol).clone(); }
309 inline Var& var(int j) { return str_data_.elt(j); }
313 inline Var const& var(int icol) const { return str_data_.elt(icol); }
317 inline Var& at(int icol) { return str_data_.at(icol); }
321 inline Var const& at(int icol) const { return str_data_.at(icol); }
325 inline Var& operator[](int const& icol) { return str_data_[icol]; }
329 inline Var const operator[](int const& icol) const { return str_data_[icol]; }
331 inline Var& front() { return str_data_.at(begin());}
333 inline Var const& front() const { return str_data_.at(begin());}
335 inline Var& back() { return str_data_.at(lastIdx());}
337 inline Var const& back() const { return str_data_.at(lastIdx());}
342 bool push_back( Var const& data = Var())
343 {
344 try
345 {
346 str_data_.push_back(data);
347 //str_data_.back().reserve(reserve_);
348 return true;
349 }
350 catch(const Exception& e) { msg_error_ = e.error(); }
351 catch(...) { msg_error_ = Csv::ERRORCODES[1]; }
352 return false;
353 }
358 bool push_front( Var const& data = Var())
359 {
360 try
361 {
362 str_data_.push_front(data);
363 return true;
364 }
365 catch(const Exception& e) { msg_error_ = e.error(); }
366 catch(...) { msg_error_ = Csv::ERRORCODES[1]; }
367 return false;
368 }
373 inline void resize( int sizeRows, int sizeCols)
374 {
377 }
383 bool appendData( int const& icol, Type const& value)
384 {
385 try
386 {
387 if (Arithmetic<Type>::isNA(value))
388 str_data_[icol].push_back(Arithmetic<Type>::NA());
389 else
390 str_data_[icol].push_back(value);
391 return true;
392 }
393 catch(const Exception& e) { msg_error_ = e.error(); }
394 catch(...) { msg_error_ = Csv::ERRORCODES[1]; }
395 return false;
396 }
401 bool eraseColumn(int const& icol)
402 {
403 try
404 {
405 str_data_.erase(icol);
406 return true;
407 }
408 catch( Exception const& e) { msg_error_ = e.error(); }
409 catch(...) { msg_error_ = Csv::ERRORCODES[1]; }
410 return false;
411 }
416 {
417 file_name_ = rw.file_name_;
418 with_names_ = rw.with_names_;
419 delimiters_ = rw.delimiters_;
420 reserve_ = rw.reserve_;
422 str_data_ = rw.str_data_;
423 nbVars_ = rw.nbVars_;
424 nbRows_ = rw.nbRows_;
425 return *this;
426 }
431 {
432 for ( int i=rw.begin(); i<=rw.lastIdx(); i++)
433 { str_data_.push_back(rw.str_data_[i]);}
434 return *this;
435 }
440 { return TReadWriteCsv((*this)) += rw;}
442 template<class Array>
443 void exporter(ArrayBase<Array>& array) const
444 {
445 array.asDerived().resize(sizeRows(), sizeCols());
446 for (int j= beginCols(); j < endCols(); ++j)
447 {
448 for (int i= beginRows(); i < endRows(); ++i)
449 {
450 array.elt(i,j) = var(j)[i];
451 }
452
453 }
454 }
458 inline bool read() { return read(file_name_);}
462 inline bool read(std::map<String, Type> const& mapping)
463 { return read(file_name_);}
468 bool read(std::string const& file_name)
469 {
470 try
471 {
472 // update current file_name
474 // input file stream
476 // open file
477 inFile.open(file_name.c_str(),std::ios::in);
478 // check error
479 if (inFile.rdstate() & std::ios::failbit)
480 {
481 inFile.close();
482 msg_error_ = Csv::ERRORCODES[4];
483 msg_error_ += "\nFile: " + file_name;
484 return false;
485 }
486 read(inFile); // and read it
487 inFile.close();
488 // return
489 return true;
490 }
491 catch(const Exception& e)
492 { msg_error_ = e.error();}
493 catch(...)
494 { msg_error_ = Csv::ERRORCODES[1];}
495 return false;
496 }
505 inline bool write() { return write(file_name_);}
511 bool write( std::string const& file_name) const
512 {
514 try
515 {
516 ofstream os(file_name.c_str());
518 os.close();
519 return true;
520 }
521 catch(const Exception& e) { msg_error_ = e.error(); }
522 catch(...) { msg_error_ = Csv::ERRORCODES[1]; }
523 return false;
524 }
528 void write( ostream& os) const
538 void writeSelection( ostream& os, int top, int bottom, int left, int right) const;
539
542 {
543 if (!rw.read(in)) throw Exception(rw.msg_error_);
544 return in;
545 }
548 {
549 try
550 { rw.writeSelection( os, rw.beginRows(), rw.lastIdxRows(), rw.begin(), rw.lastIdx());}
551 // catch and re-throw any Exceptions
552 catch(const Exception& e) { throw e; }
553 catch(...) { throw Exception(Csv::ERRORCODES[1]); }
554 return os;
555 }
556
557 protected:
559 mutable std::string file_name_;
561 mutable bool with_names_;
563 mutable bool with_mapping_;
565 mutable bool with_last_nl_;
569 mutable int reserve_;
575 std::map<String, Type> imapping_;
577 std::map<Type, String> omapping_;
589 {
590 listDelimiters.clear();
591 listDelimiters.reserve(nbVars_);
592 // position of the delimiters in the file
593 String::size_type idx =0;
594 do
595 {
596 // Find delimiter
597 idx = line.find_first_of(delimiters_, idx);
598 // if the position of the delimiter char is not found
599 if (idx == line.npos) break;
600 listDelimiters.push_back(line[idx]);
601 ++idx;
602 } while(1);
603 // last delimiter is the end of line
604 listDelimiters.push_back(CHAR_NL);
605 listDelimiters.shift(1);
606 // return the number of fields
607 return listDelimiters.size();
608 }
616 {
617 if (inBuffer.eof()) return 0;
618 int nbField =0;
619 do
620 {
621 currentLine.clear();
622 std::getline(inBuffer, currentLine);
623 if (currentLine.size() == 0) {nbField = 0;}
624 else
625 {
627 nbField = (currentLine.size() == 0)
629 }
630 }
631 while ((nbField == 0)&&(!inBuffer.eof()));
632 return nbField;
633 }
638 {
641 // Count the number of names of the first line
643 if (nbField == 0) return;
644 // Declare an input string stream
646 for(int icol=1; icol<=nbField; icol++)
647 {
648 // Append a Col
649 String name;
651 push_back(Var(nbRows_, name));
652 }
653 // Update the number of var
654 nbVars_ = std::max(nbVars_, nbField);
655 }
661 {
664 // clear previous ReadCvs if any
665 str_data_.clear();
666 // get current position in the stream
667 std::streampos pos = inBuffer.tellg();
668 // Count the number of rows of the input stream
671 // revert to the current position in the stream
672 inBuffer.seekg(pos);
673 // initialize the initial number of variables to 0
674 nbVars_ = 0;
675 // If the names are at the top line
677 // get current position
678 pos = inBuffer.tellg();
679 // count number of fields in the first line
681 nbVars_ = std::max(nbVars_, nbField);
682 inBuffer.seekg(pos);
683 }
689 inline void fastSetData( int const& icol, int const& irow, Type const& value)
690 { str_data_.elt(icol).elt(irow) = value;}
694 inline void resizeRows( Range const& rows)
695 {
696 for (int iVar=begin(); iVar<=lastIdx(); iVar++ )
697 { str_data_.elt(iVar).resize(rows);}
698 }
702 inline void resizeCols( Range const& cols)
703 { str_data_.resize(cols);}
704};
705
706/* Reads the specified file with the specified read flags.
707 * @param file_name name of the file to read
708 * @return @c true if successful, @c false if an error is encountered.
709 **/
710template <typename Type>
712{
715 try
716 {
717 initRead(inBuffer);
718 resizeCols(nbVars_);
719 resizeRows(nbRows_);
720 // Read data : loop for all rows
721 int currentRow=beginRows()-1, countRows = 0;
722 for (; !inBuffer.eof();)
723 {
724 int nbField = readCurrentLine(inBuffer, currentLine, listDelimiters);
725 if (nbField == 0) { break;}
726 // add on the non-existing columns: will be done if (nbField >= nbVars_)
727 for (int iField=nbVars_+1; iField<=nbField; iField++)
728 { push_back(Var( nbRows_, Arithmetic<Type>::NA(), stringNa));
729 nbVars_++;
730 }
731 // first loop on the existing columns with data
734 int icol=begin();
735 for (int iField=1 ; iField<=nbField; iField++, icol++)
736 {
739 // append Data to the column
740 with_mapping_ ?
741 fastSetData(icol, currentRow, imapping_.count(field) ? imapping_.find(field)->second : Arithmetic<Type>::NA())
742 : fastSetData(icol, currentRow, stringToType<Type>(field));
743 }
744 // Append NA values if the row is not complete
745 for (; icol<end(); icol++) { fastSetData(icol, currentRow, Arithmetic<Type>::NA());}
746 }
747 // resize in case there exists too much rows
748 resizeRows(Range(countRows));
749 return true;
750 }
751 catch( Exception const& e) { msg_error_ = e.error(); }
752 catch(...) { msg_error_ = Csv::ERRORCODES[1]; }
753 return false;
754}
755
756template <typename Type>
757void TReadWriteCsv<Type>::writeSelection( ostream& os, int top, int bottom, int left, int right) const
758{
759 if ((right < left)|| (bottom < top)) return;
760 // create a vector for the format of the output
762 // for each variable, find the largest size
763 for(int iVar=left; iVar<=right; iVar++)
764 { format[iVar] = str_data_[iVar].maxLength(with_names_);}
765 // write if needed names variables
766 if (with_names_)
767 {
768 for(int iVar=left; iVar<right; iVar++)
769 {
770 os << std::setw(int(format[iVar])) << std::right
771 << Proxy<String>(str_data_.at(iVar).name())
772 << delimiters_.at(0);
773 }
774 os << std::setw(int(format[right])) << std::right
775 << Proxy<String>(str_data_[right].name())
776 << _T("\n");
777 }
778 // write data
779 for(int irow = top; irow<bottom; irow++)
780 {
781 for(int iVar = left; iVar<right; iVar++)
782 {
783 try
784 {
785 os << std::setw(format[iVar]) << std::right
786 << Proxy<Type>(str_data_[iVar].at(irow));
787 }
788 catch(...) // if an error occur, we put NA value
789 { os << std::setw(format[iVar]) << std::right << stringNa;}
790 os << delimiters_.at(0);
791 }
792 try
793 {
794 os << std::setw(format[right]) << std::right
795 << Proxy<Type>(str_data_[right].at(irow));
796 }
797 catch(...) // if an error occur, we put NA value
798 { os << std::setw(format[right]) << std::right << stringNa;}
799 os << _T("\n");
800 }
801 for(int iVar = left; iVar<right; iVar++)
802 {
803 try
804 {
805 os << std::setw(format[iVar]) << std::right
806 << Proxy<Type>(str_data_[iVar].at(bottom));
807 }
808 catch(...) // if an error occur, we put NA value
809 { os << std::setw(format[iVar]) << std::right << stringNa;}
810 os << delimiters_.at(0);
811 }
812 try
813 {
814 os << std::setw(format[right]) << std::right
815 << Proxy<Type>(str_data_[right].at(bottom));
816 }
817 catch(...) // if an error occur, we put NA value
818 { os << std::setw(format[right]) << std::right << stringNa;}
819 if (with_last_nl_) { os << _T("\n");}
820}
821
822} // namespace STK
823
824#endif // STK_READWRITECSV_H
In this file we define and implement the final class Array1D.
In this file we define the base class for Arrays.
#define _T(x)
Let x unmodified.
Implement the interface class IVariable as Variable.
Sdk class for all library Exceptions.
String msg_error_
String with the last error message.
Definition STK_IRunner.h:96
String const & error() const
get the last error message.
Definition STK_IRunner.h:82
The MultidimRegression class allows to regress a multidimensional output variable among a multivariat...
Index sub-vector region: Specialization when the size is unknown.
Definition STK_Range.h:265
the TReadWriteCsv class : allow to write and/or to read a csv file.
Var & operator[](int const &icol)
std::map< Type, String > omapping_
mapping Type -> String (output)
TReadWriteCsv()
The default constructor.
void writeSelection(ostream &os, int top, int bottom, int left, int right) const
Write to output stream a selection based on the coordinates passed (Think of it as highlighting cells...
std::string file_name_
Name of the Current file read.
TReadWriteCsv & operator+=(TReadWriteCsv const &rw)
Appends a TReadWriteCsv to another TReadWriteCsv.
String msg_error_
Contain the last error message.
Var const & at(int icol) const
int sizeRow(int icol) const
void setReserve(int const &reserve) const
Sets the reserve value for data storage (reserve_ is mutable).
int readCurrentLine(istream &inBuffer, String &currentLine, Array1D< Char > &listDelimiters)
Read the current line from the buffer.
void setInMapping(std::map< String, Type > const &imapping)
Set mapping to used when reading.
void clear()
reset all fields to default value and reclaims any allocated memory.
int reserve_
Size of the buffer.
Var const & back() const
int endRow(int icol) const
bool read(istream &inBuffer)
Reads the specified input stream with the specified read flags.
int lastRow(int icol) const
void exporter(ArrayBase< Array > &array) const
export to an array of the same Type
void resize(int sizeRows, int sizeCols)
resize the container str_data_.
void fastSetData(int const &icol, int const &irow, Type const &value)
Set without check the specified value to the element (icol, irow).
TReadWriteCsv & operator=(TReadWriteCsv const &rw)
Assigns a TReadWriteCsv equal to another TReadWriteCsv.
bool push_front(Var const &data=Var())
Attempts to add a column with the values contained in data.
String delimiters_
Delimiter(s)
void setLast_nl(bool with_last_nl) const
Sets the with_last_nl_ value for writing a new line after the last line.
int nbVars_
The number of variables we manage.
int nbRows_
The number of rows we manage.
~TReadWriteCsv()
destructor.
Type const operator()(int const &iRow, int const &iCol) const
Array1D< Var > str_data_
Array of array for the data.
Var * clone(int icol) const
String const & delimiters() const
int firstRow(int icol) const
bool appendData(int const &icol, Type const &value)
Attempts to append a data to the variable specified by icol.
bool read()
Reads the default file with the specified read flags.
void setOutMapping(std::map< String, Type > const &omapping)
Set mapping to used when writting.
void resizeCols(Range const &cols)
resize the TReadWriteCsv to the given range of columns.
int countFields(String const &line, Array1D< Char > &listDelimiters)
Counts the number of columns in a line stored in a String and return the position of the delimiters a...
bool with_mapping_
map the values stored
bool write(std::string const &file_name) const
Attempts to write the TReadWriteCsv to the location specified by file_name using the delimiters speci...
bool read(std::map< String, Type > const &mapping)
Reads the default file with the specified read flags using a map.
TReadWriteCsv(std::string const &file_name, bool read_names=Csv::DEFAULT_READNAMES, String const &delimiters=Csv::DEFAULT_DELIMITER)
Constructor with a specified file name.
String const & error() const
TReadWriteCsv operator+(TReadWriteCsv const &rw) const
Combines TReadWriteCsv(s)
void write(ostream &os) const
Write the csv to an output stream.
void setWithNames(bool with_names) const
Sets the with_names_ value for reading/writing variables names.
bool push_back(Var const &data=Var())
Attempts to add a column with the values contained in data.
Var const & front() const
friend istream & operator>>(istream &in, TReadWriteCsv &rw)
overload operator >> for rw
bool with_names_
Read or Write names of the variables.
bool setName(int const &icol, String const &name)
Set the variable name name at the specified index.
bool with_last_nl_
write a new line character at the end of the output
void initRead(istream &inBuffer)
Initial read.
Var const operator[](int const &icol) const
@ return a const reference to the value at the specified location.
bool eraseColumn(int const &icol)
Deletes the variable whose index is icol from a TReadWriteCsv.
void readNames(istream &inBuffer)
Read the names of rhe Csv file.
bool write()
write to the default file with the specified write flags.
Type & operator()(int const &iRow, int const &iCol)
void setWithMapping(bool with_mapping) const
Sets the with_mapping_ value for reading/writing variables names.
std::map< String, Type > imapping_
mapping String -> Type for (input)
void resizeRows(Range const &rows)
resize the TReadWriteCsv to the given range of rows.
Variable< Type > Var
TReadWriteCsv(TReadWriteCsv const &rw)
Copy constructor.
Var const & var(int icol) const
void setDelimiters(String const &delimiters) const
Sets the delimiters to use for parsing data (delimiters_ is mutable).
bool read(std::string const &file_name)
Reads the specified file with the specified read flags.
friend ostream & operator<<(ostream &os, TReadWriteCsv const &rw)
overload operator << for rw
String stringNa
Representation of a Not Available value.
readflags
TODO: These flags determine the behavior of the reading methods.
int nbEndOfLine(istream &is)
void removeCharBeforeAndAfter(String &str, Char c)
remove all occurrences of the char c at the beginning and the end of the string str.
istream & getField(istream &is, String &value, Char delimiter)
Get the current field from the input stream.
std::basic_string< Char > String
STK fundamental type of a String.
const int baseIdx
base index of the containers created in STK++.
std::basic_ostream< Char > ostream
ostream for Char
Definition STK_Stream.h:57
std::basic_ifstream< Char > ifstream
ifstream for Char
Definition STK_Stream.h:71
std::basic_istringstream< Char > istringstream
istringstream for Char
Definition STK_Stream.h:63
std::basic_istream< Char > istream
istream for Char
Definition STK_Stream.h:55
std::basic_ofstream< Char > ofstream
ofstream for Char
Definition STK_Stream.h:73
The namespace STK is the main domain space of the Statistical ToolKit project.
TRange< UnknownSize > Range
Definition STK_Range.h:59
Arithmetic properties of STK fundamental types.
static Type NA()
Adding a Non Available (NA) special number.