<
classTFieldType>
81 CRR_FieldType(TFieldType field_type,
const string& field_props =
string())
124 template<
typenameTTraits>
class CRowReader;
125 template<
typenameTTraits>
class CRR_Row;
128 #define UTIL___ROW_READER_INCLUDE__INL 130 #undef UTIL___ROW_READER_INCLUDE__INL 134 template<
typenameTTraits>
146 template<
typenameTValue>
147TValue
Get(
void)
const;
158 template<
typenameTValue> TValue
174 bool IsNull(
void)
const;
201 friend class CRR_Row<TTraits>;
219 template<
typenameTTraits>
356 template<
typenameTTraits>
379 const string& sourcename,
407 const string& sourcename,
426 void Validate(
typenameTTraits::ERR_ValidationMode validation_mode
427= TTraits::eRR_ValidationMode_Default,
648 typenameTTraits::TRR_Context
GetContext(
void)
const;
727 template<
typenameTTraits>
730 if(m_RowReader ==
nullptr)
731 return CTime(x_GetStringValue(), fmt);
733 return CTime(x_GetStringValue(), fmt);
735exc.
SetContext(m_RowReader->GetBasicContext().Clone());
739 "Cannot convert field value to CTime using " 741m_RowReader->GetBasicContext().Clone());
742}
catch(
constexception& exc) {
744exc.
what(), m_RowReader->GetBasicContext().Clone());
747 "Unknown error while converting field value to " 748 "CTime using format "+ fmt.
GetString(),
749m_RowReader->GetBasicContext().Clone());
754 template<
typenameTTraits>
755 template<
typenameTValue>
759 if(m_RowReader ==
nullptr) {
765exc.
SetContext(m_RowReader->GetBasicContext().Clone());
769 "Cannot convert field value to "+
770 string(
typeid(TValue).name()),
771m_RowReader->GetBasicContext().Clone());
772}
catch(
constexception& exc) {
774exc.
what(), m_RowReader->GetBasicContext().Clone());
777 "Unknown error while converting field value to "+
778 string(
typeid(TValue).name()),
779m_RowReader->GetBasicContext().Clone());
786 template<
typenameTTraits>
787 template<
typenameTValue> TValue
791 returndefault_value;
792 returnGet<TValue>();
796 template<
typenameTTraits>
803 template<
typenameTTraits>
806 returnm_OriginalData;
810 template<
typenameTTraits>
817 template<
typenameTTraits>
819m_OriginalDataCopy(other_field.m_OriginalData.
data(),
820other_field.m_OriginalData.
size()),
821m_IsNull(other_field.m_IsNull),
822m_Translated(other_field.m_Translated),
823m_OriginalData(m_OriginalDataCopy.
data(), m_OriginalDataCopy.
size()),
824m_TranslatedValue(other_field.m_TranslatedValue),
829 template<
typenameTTraits>
831m_OriginalDataCopy(std::move(other_field.m_OriginalDataCopy)),
832m_IsNull(other_field.m_IsNull),
833m_Translated(other_field.m_Translated),
834m_OriginalData(m_OriginalDataCopy.
data(), m_OriginalDataCopy.
size()),
835m_TranslatedValue(std::move(other_field.m_TranslatedValue)),
836m_RowReader(other_field.m_RowReader)
840 template<
typenameTTraits>
843 if(
this!= &other_field) {
848m_OriginalData.assign(m_OriginalDataCopy.data(),
849m_OriginalDataCopy.size());
851m_RowReader =
nullptr;
857 template<
typenameTTraits>
860 if(
this!= &other_field) {
861m_OriginalDataCopy = std::move(other_field.m_OriginalDataCopy);
862m_IsNull = other_field.m_IsNull;
863m_Translated = other_field.m_Translated;
864m_OriginalData.assign(m_OriginalDataCopy.data(),
865m_OriginalDataCopy.size());
866m_TranslatedValue = std::move(other_field.m_TranslatedValue);
867m_RowReader = other_field.m_RowReader;
873 template<
typenameTTraits>
878 "The field value is translated to NULL",
nullptr);
880 returnm_TranslatedValue;
881 returnm_OriginalData;
890 template<
typenameTTraits>
901 template<
typenameTTraits>
903m_RawData(other_row.m_RawData),
904m_RowType(other_row.m_RowType),
905m_MetaInfo(other_row.m_MetaInfo),
916 template<
typenameTTraits>
919 if(
this!= &other_row) {
924m_RowReader =
nullptr;
926x_CopyFields(other_row);
933 template<
typenameTTraits>
935m_RawData(std::move(other_row.m_RawData)),
936m_RowType(other_row.m_RowType),
937m_MetaInfo(std::move(other_row.m_MetaInfo)),
938m_Copied(other_row.m_Copied),
939m_Fields(std::move(other_row.m_Fields)),
940m_FieldsSize(other_row.m_FieldsSize),
941m_FieldsCapacity(other_row.m_FieldsCapacity),
942m_RowReader(other_row.m_RowReader)
946 template<
typenameTTraits>
949m_RawData = std::move(other_row.
m_RawData);
951m_MetaInfo = std::move(other_row.
m_MetaInfo);
953m_Fields = std::move(other_row.
m_Fields);
960 template<
typenameTTraits>
963 if(field >= GetNumberOfFields()) {
965 if(m_RowReader !=
nullptr)
966ctxt = m_RowReader->GetBasicContext().
Clone();
970 " is out of range for the current row", ctxt);
972 returnm_Fields[field];
976 template<
typenameTTraits>
980 TFieldNoindex = x_GetFieldIndex(field);
981 if(index >= GetNumberOfFields()) {
983 if(m_RowReader !=
nullptr)
984ctxt = m_RowReader->GetBasicContext().
Clone();
988 " provided for the field name '"+ field +
989 "' is out of range for the current row", ctxt);
991 returnm_Fields[index];
995 template<
typenameTTraits>
1002 template<
typenameTTraits>
1005 return static_cast<TFieldNo>(m_FieldsSize);
1009 template<
typenameTTraits>
1016 template<
typenameTTraits>
1025 template<
typenameTTraits>
1028m_FieldsSize = new_size;
1029 while(m_FieldsCapacity < new_size) {
1036 template<
typenameTTraits>
1046ptrdiff_t raw_data_delta = m_RawData.data() - other_row.
m_RawData.data();
1048 for(
size_tindex = 0; index < m_FieldsSize; ++index) {
1063m_Fields[index].m_RowReader =
nullptr;
1068 template<
typenameTTraits>
1073m_MetaInfo->SetFieldName(field, name, user_init);
1077 template<
typenameTTraits>
1084m_MetaInfo->SetFieldType(field,
type, user_init);
1088 template<
typenameTTraits>
1096m_MetaInfo->SetFieldTypeEx(field,
type, extended_type, user_init);
1100 template<
typenameTTraits>
1103 returnm_MetaInfo->GetDescribedFieldCount();
1107 template<
typenameTTraits>
1108vector<typename CRR_Row<TTraits>::SFieldMetaInfo>
1111vector<SFieldMetaInfo>
result;
1113 if(m_MetaInfo->m_FieldsInfo.empty())
1116 size_tlast_index =
min(
static_cast<size_t>(to),
1117m_MetaInfo->m_FieldsInfo.size() - 1);
1118 for(
size_tindex = from; index <= to && index <= last_index; ++index) {
1119 const auto& field_info = m_MetaInfo->m_FieldsInfo[index];
1120 if(field_info.IsInitialized()) {
1124 info.is_name_initialized =
1126 if(
info.is_name_initialized)
1127 info.name = *field_info.m_FieldName;
1128 info.is_type_initialized =
1130 info.type = field_info.m_FieldType;
1131 info.is_ext_type_initialized =
1133 info.ext_type = field_info.m_FieldExtType;
1142 template<
typenameTTraits>
1146m_MetaInfo->Clear(
true);
1151 template<
typenameTTraits>
1155m_MetaInfo->Clear(
false);
1160 template<
typenameTTraits>
1167m_MetaInfo.Reset(new_meta);
1173 template<
typenameTTraits>
1176 if(m_RowReader ==
nullptr)
1177 returnm_MetaInfo->GetFieldIndexByName(field);
1179 returnm_MetaInfo->GetFieldIndexByName(field);
1181exc.
SetContext(m_RowReader->GetBasicContext().Clone());
1185 "Cannot get field number by name ('" 1186+
string(field) +
"')",
1187m_RowReader->GetBasicContext().Clone());
1188}
catch(
constexception& exc) {
1190exc.
what(), m_RowReader->GetBasicContext().Clone());
1193 "Unknown error while getting field number by name ('" 1194+
string(field) +
"')",
1195m_RowReader->GetBasicContext().Clone());
1205 template<
typenameTTraits>
1217 template<
typenameTTraits>
1220 const string& sourcename,
1229 "Invalid data source stream",
nullptr);
1237 template<
typenameTTraits>
1253 template<
typenameTTraits>
1258 template<
typenameTTraits>
1261 const string& sourcename,
1266 "Invalid data source stream",
nullptr);
1275 template<
typenameTTraits>
1286 template<
typenameTTraits>
1288 typenameTTraits::ERR_ValidationMode validation_mode,
1294 "Data source stream has not been provided",
nullptr);
1297 size_tphys_lines_read;
1308 m_Traits.SetValidationMode(validation_mode);
1313 "Set validation mode error", ctxt);
1314}
catch(
constexception& exc) {
1322 "Unknown set validation mode error", ctxt);
1358field_validation_mode);
1365 "Validation error", ctxt);
1366}
catch(
constexception& exc) {
1374 "Unknown validating error", ctxt);
1406 template<
typenameTTraits>
1420 template<
typenameTTraits>
1434 template<
typenameTTraits>
1436 const string& name)
1443 template<
typenameTTraits>
1454 template<
typenameTTraits>
1466 template<
typenameTTraits>
1468 const string& name)
1475 template<
typenameTTraits>
1485 template<
typenameTTraits>
1496 template<
typenameTTraits>
1497vector<typename CRR_Row<TTraits>::SFieldMetaInfo>
1504 template<
typenameTTraits>
1511 template<
typenameTTraits>
1518 template<
typenameTTraits>
1525 template<
typenameTTraits>
1532 template<
typenameTTraits>
1542 template<
typenameTTraits>
1548 "It is prohibited to use iterators " 1549 "during the stream validation",
nullptr);
1554 template<
typenameTTraits>
1563 template<
typenameTTraits>
1564 typenameTTraits::TRR_Context
1580 template<
typenameTTraits>
1634 "Input stream failed before reaching the end",
1647}
catch(
constexception& exc) {
1661 template<
typenameTTraits>
1667 "Data source stream has not been provided prior " 1668 "to the first read",
nullptr);
1692 size_tphys_lines_read;
1732eInvalidAction,
"Invalid action "+
1734 " in response to the Tokenize() call.",
1744field_index <
m_Tokens.size(); ++field_index) {
1749field_index,
m_Tokens[field_index],
1775eLineProcessing,
"Error processing line", ctxt);
1776}
catch(
constexception& exc) {
1785 "Unknown line processing error", ctxt);
1819 template<
typenameTTraits>
1824open_mode |= ios_base::binary;
1831 template<
typenameTTraits>
1842 template<
typenameTTraits>
1860 template<
typenameTTraits>
1869 ERR_POST(
"Exception while getting traits context: "<< exc.
what());
1871}
catch(
constexception& exc) {
1872 ERR_POST(
"Exception while getting traits context: "<< exc.
what());
1875 ERR_POST(
"Unknown exception while getting traits context");
1881 template<
typenameTTraits>
1892 template<
typenameTTraits>
1917 return m_Traits.OnEvent(event, event_mode);
1920 "Traits error in handling the "+
1923}
catch(
constexception& exc) {
1928 "Unknown traits error in handling the "+
1939 template<
typenameTTraits>
1948 template<
typenameTTraits>
1952x_CheckFieldAccess();
1953 returnm_RowReader->m_CurrentRow[field];
1957 template<
typenameTTraits>
1961x_CheckDereferencing();
1962 returnm_RowReader->m_CurrentRow;
1966 template<
typenameTTraits>
1970x_CheckDereferencing();
1971 return&m_RowReader->m_CurrentRow;
1975 template<
typenameTTraits>
1980 _ASSERT(m_RowReader ==
i.m_RowReader);
1981 _ASSERT(m_IsEndIter ||
i.m_IsEndIter);
1983 if(m_RowReader !=
i.m_RowReader)
1986 if(!m_IsEndIter && !
i.m_IsEndIter)
1988 "Comparing two non end iterators is prohibited",
nullptr);
1990 if(m_IsEndIter &&
i.m_IsEndIter)
1994 return i.m_RowReader->m_AtEnd
1995&& (
i.m_RowReader->m_NextDataSource.m_Stream ==
nullptr);
1997 returnm_RowReader->m_AtEnd
1998&& (m_RowReader->m_NextDataSource.m_Stream ==
nullptr);
2002 template<
typenameTTraits>
2011 template<
typenameTTraits>
2013: m_RowReader(
i.m_RowReader), m_IsEndIter(
i.m_IsEndIter)
2017 template<
typenameTTraits>
2022 template<
typenameTTraits>
2026m_RowReader =
i.m_RowReader;
2027m_IsEndIter =
i.m_IsEndIter;
2032 template<
typenameTTraits>
2037m_RowReader->x_ReadNextRow();
2042 template<
typenameTTraits>
2046m_RowReader(s), m_IsEndIter(is_end)
2051 template<
typenameTTraits>
2060 template<
typenameTTraits>
2063 if(m_RowReader->m_Validation)
2065 "It is prohibited to use iterators " 2066 "during the stream validation",
nullptr);
2067 if(m_IsEndIter || m_RowReader->m_AtEnd)
2069 "Dereferencing end iterator is prohibited",
nullptr);
2070 if(!m_RowReader->m_RawDataAvailable)
2072 "Dereferencing iterator when no data is available",
2077 template<
typenameTTraits>
2080 if(m_RowReader->m_Validation)
2082 "It is prohibited to use iterators " 2083 "during the stream validation",
nullptr);
2085(m_RowReader->m_AtEnd && m_RowReader->m_NextDataSource.m_Stream ==
nullptr))
2087 "Advancing end iterator is prohibited",
nullptr);
2091 template<
typenameTTraits>
2094 if(m_RowReader->m_Validation)
2096 "It is prohibited to use iterators " 2097 "during the stream validation",
nullptr);
2098 if(m_IsEndIter || m_RowReader->m_AtEnd)
2100 "Accessing row field via end iterator",
nullptr);
The class represents the current delimited row stream context.
virtual CRR_Context * Clone(void) const
Basic or an extended field type with an added arbitrary string property.
CRR_FieldType(TFieldType field_type, const string &field_props=string())
TFieldType GetType(void) const
string GetProps(void) const
A single field in a row abstraction.
CTempString m_OriginalData
const CTempString GetOriginalData(void) const
Get the field original data.
bool IsNull(void) const
Check if the field value is NULL.
CTempString x_GetStringValue(void) const
TValue GetWithDefault(const TValue &default_value) const
Get the converted field value.
CRowReader< TTraits > * m_RowReader
string m_OriginalDataCopy
TValue Get(void) const
Get the converted field value.
CRR_Field & operator=(const CRR_Field &other_field)
Represents one row from an input stream.
CRowReader< TTraits > * m_RowReader
vector< CRR_Field< TTraits > > m_Fields
CRR_Row()
Construct an empty row.
TFieldNo x_GetFieldIndex(CTempString field) const
void x_ClearFieldsInfo(void)
void x_SetFieldType(TFieldNo field, const CRR_FieldType< ERR_FieldType > &type, bool user_init)
void x_AdjustFieldsSize(size_t new_size)
CRef< CRR_MetaInfo< TTraits > > m_MetaInfo
vector< SFieldMetaInfo > GetFieldsMetaInfo(TFieldNo from=0, TFieldNo to=numeric_limits< TFieldNo >::max())
Get the collected fields meta info.
ERR_RowType GetType(void) const
Get the row type.
void x_SetFieldName(TFieldNo field, const string &name, bool user_init)
TFieldNo GetNumberOfFields(void) const
Get the number of fields in the row.
void x_ClearTraitsProvidedFieldsInfo(void)
void x_SetFieldTypeEx(TFieldNo field, const CRR_FieldType< ERR_FieldType > &type, const CRR_FieldType< typename TTraits::TExtendedFieldType > &extended_type, bool user_init)
CRR_Row & operator=(const CRR_Row &other_row)
void x_CopyFields(const CRR_Row &other_row)
void x_DetachMetaInfo(void)
TFieldNo GetDescribedFieldCount(void) const
Get the number of a fields for which any kind of meta info is provided.
CTempString GetOriginalData(void) const
Get the row original data.
const CRR_Field< TTraits > & operator[](TFieldNo field) const
Get a row field.
static void GetFieldValueConverted(const CTempString &str_value, CTime &converted)
static string ERR_EventToString(ERR_Event event)
static void CheckExistanceAndPermissions(const string &sourcename)
static ERR_RowType ActionToRowType(ERR_Action action)
static string ERR_ActionToString(ERR_Action action)
Exception to be used throughout API.
void SetContext(CRR_Context *ctxt)
A (forward-only) iterator to iterate over the rows from a stream.
CRR_Row< TTraits > & operator*(void) const
Get a reference to the current row.
CRowIterator & operator=(const CRowIterator &iter)
bool operator==(const CRowIterator &iter) const
Compare this iterator with another.
bool operator!=(const CRowIterator &iter) const
This is an exact negation of operator==.
CRowIterator & operator++(void)
Advance the iterator to the next row.
void x_CheckDereferencing(void) const
const CRR_Field< TTraits > & operator[](TFieldNo field) const
Get a row field.
void x_CheckFieldAccess(void) const
void x_CheckAdvancing(void) const
CRowReader< TTraits > * m_RowReader
CRowIterator(const CRowIterator &iter)
CRR_Row< TTraits > * operator->(void) const
Get a pointer to the current row.
Callback style template to iterate over a row stream.
TStreamPos GetCurrentRowPos(void) const
Get the absolute position (in the current data source) of the beginning of the row that is currently ...
void SetDataSource(CNcbiIstream *is, const string &sourcename, EOwnership ownership=eNoOwnership)
Switch to processing data from another stream.
void Validate(typename TTraits::ERR_ValidationMode validation_mode=TTraits::eRR_ValidationMode_Default, ERR_FieldValidationMode field_validation_mode=eRR_FieldValidation)
Read and validate-only the stream, calling TTraits::Validate(row, validation_mode) on each row.
void ClearFieldsInfo(void)
Clear the information about all field names, types and extended types.
CRowIterator begin(void)
It works exactly(!) like CRowIterator::operator++, except it creates new iterator and therefore can a...
TTraits & GetTraits(void)
Get the traits object.
SRR_SourceInfo m_NextDataSource
TLineNo GetCurrentLineNo(void) const
Get the number of the line that is currently being processed.
void x_OpenFile(SRR_SourceInfo &stream_info)
CRR_Row< TTraits > m_CurrentRow
CRowReader & operator=(const CRowReader &)=delete
CRowReader & operator=(CRowReader &&)=delete
size_t m_PreviousPhysLinesRead
CRR_Context GetBasicContext(void) const
Get basic context.
vector< CTempString > m_Tokens
void SetFieldTypeEx(TFieldNo field, const CRR_FieldType< ERR_FieldType > &type, const CRR_FieldType< typename TTraits::TExtendedFieldType > &extended_type)
Set the (trait specific) data type of the field.
void x_ClearTraitsProvidedFieldsInfo(void)
CRR_Context * x_GetContextClone(void)
CRowReader(const CRowReader &)=delete
CRR_Field< TTraits > CField
bool x_GetRowData(size_t *phys_lines_read)
TStreamPos m_CurrentRowPos
ERR_EventAction x_OnEvent(ERR_Event event)
vector< typename CRR_Row< TTraits >::SFieldMetaInfo > GetFieldsMetaInfo(TFieldNo from=0, TFieldNo to=numeric_limits< TFieldNo >::max())
Get the collected fields meta info.
void x_SetFieldName(TFieldNo field, const string &name)
CRowReader(CRowReader &&)=delete
CRowIterator const_iterator
TFieldNo GetDescribedFieldCount(void) const
Get the number of a fields for which any kind of meta info is provided.
SRR_SourceInfo m_DataSource
void x_SetFieldType(TFieldNo field, const CRR_FieldType< ERR_FieldType > &type)
void SetFieldType(TFieldNo field, const CRR_FieldType< ERR_FieldType > &type)
Set the (basic) data type of the field.
CRowIterator end(void) const
Get iterator pointing to the end of the current underlying data source.
TTraits::TRR_Context GetContext(void) const
Get traits context.
CRowReader()
Construct a row reader.
void SetFieldName(TFieldNo field, const string &name)
Set the field name.
void x_UpdateCurrentLineNo(size_t phys_lines_read)
void x_SetFieldTypeEx(TFieldNo field, const CRR_FieldType< ERR_FieldType > &type, const CRR_FieldType< typename TTraits::TExtendedFieldType > &extended_type)
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Include a standard set of the NCBI C++ Toolkit most basic headers.
bool operator==(const CEquivRange &A, const CEquivRange &B)
@ eTakeOwnership
An object can take ownership of another.
@ eNoOwnership
No ownership is assumed.
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
#define NCBI_THROW2(exception_class, err_code, message, extra)
Throw exception with extra parameter.
#define NCBI_RETHROW2(prev_exception, exception_class, err_code, message, extra)
Re-throw exception with extra parameter.
virtual const char * what(void) const noexcept
Standard report (includes full backlog).
uint32_t Uint4
4-byte (32-bit) unsigned integer
uint64_t Uint8
8-byte (64-bit) unsigned integer
#define END_NCBI_SCOPE
End previously defined NCBI scope.
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Int8 NcbiStreamposToInt8(NCBI_NS_STD::char_traits< char >::pos_type stream_pos)
Convert stream position to 64-bit int.
IO_PREFIX::istream CNcbiIstream
Portable alias for istream.
IO_PREFIX::ifstream CNcbiIfstream
Portable alias for ifstream.
const char * data(void) const
Return a pointer to the array represented.
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
size_type size(void) const
Return the length of the represented array.
const string & GetString(void) const
Get format string.
enum ENcbiOwnership EOwnership
Ownership relations between objects.
const struct ncbi::grid::netcache::search::fields::SIZE size
Defines classes: CDirEntry, CFile, CDir, CSymLink, CMemoryFile, CFileUtil, CFileLock,...
std::istream & in(std::istream &in_, double &x_)
Uint4 TFieldNo
Field number (zero based)
ERR_FieldValidationMode
Whether to check validity of the fields (names and/or values)
@ eRR_FieldValidation
check that the field's value (or name) is valid
@ eRR_NoFieldValidation
don't validate fields' value and name
@ eRR_Metadata
row contains metadata
@ eRR_Invalid
row is invalid
@ eRR_Data
row contains data
@ eRR_Comment
row contains a comment
Uint8 TLineNo
Line number (in the data stream, zero based)
Uint8 TStreamPos
Position in the data stream (zero based)
ERR_FieldType
Basic field data types.
@ eRR_UseOriginal
No translation done.
@ eRR_Translated
The value has been translated to another string.
@ eRR_Null
The value has been translated to NULL.
ERR_Action
Delimited stream traits use the ERR_Action members to instruct what should be done next.
@ eRR_Continue_Data
Continue processing this line, in full.
@ eRR_Interrupt
Stop processing the stream.
@ eRR_Skip
Skip this line.
@ fRR_OpenFile_AsBinary
open file in a binary mode
ERR_EventAction
How to react to the potentially disruptive events.
@ eRR_EventAction_Continue
Resume processing.
@ eRR_EventAction_Stop
Stop further processing.
@ eRR_EventAction_Default
Do some default action.
ERR_EventMode
Indicate whether the "ERR_Event" event (passed to the OnEvent() callback) occured during regular read...
@ eRR_EventMode_Validating
We are performing data validation.
@ eRR_EventMode_Iterating
We are iterating through the rows.
ERR_Event
CRowReader passes such events to the Traits via OnEvent() callback.
@ eRR_Event_SourceEnd
Data source has hit EOF.
@ eRR_Event_SourceBegin
Data source has started or been switched (no reads yet though).
@ eRR_Event_SourceError
Data source has hit an error on read.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4