Merge branch 'api2021'

This commit is contained in:
Tomasz Sowa 2021-07-06 22:45:54 +02:00
commit 6c41e0a803
22 changed files with 2143 additions and 829 deletions

View File

@ -3,41 +3,42 @@
./convert/inttostr.o: ./convert/inttostr.h ./convert/inttostr.o: ./convert/inttostr.h
./convert/misc.o: ./convert/misc.h ./convert/text.h ./convert/misc.o: ./convert/misc.h ./convert/text.h
./convert/text.o: ./convert/text.h ./convert/text_private.h ./convert/text.o: ./convert/text.h ./convert/text_private.h
./convert/double.o: ./convert/double.h textstream/textstream.h
./convert/double.o: textstream/stream.h space/space.h textstream/types.h
./convert/double.o: convert/inttostr.h utf8/utf8.h textstream/stream.h
./convert/double.o: utf8/utf8_templates.h utf8/utf8_private.h date/date.h
./convert/double.o: membuffer/membuffer.h textstream/types.h
./date/date.o: ./date/date.h convert/inttostr.h ./date/date.o: ./date/date.h convert/inttostr.h
./log/filelog.o: ./log/filelog.h textstream/textstream.h space/space.h ./log/filelog.o: ./log/filelog.h textstream/textstream.h textstream/stream.h
./log/filelog.o: textstream/types.h convert/inttostr.h date/date.h ./log/filelog.o: space/space.h textstream/types.h convert/inttostr.h
./log/filelog.o: membuffer/membuffer.h textstream/types.h utf8/utf8.h ./log/filelog.o: utf8/utf8.h textstream/stream.h utf8/utf8_templates.h
./log/filelog.o: utf8/utf8_templates.h utf8/utf8_private.h ./log/filelog.o: utf8/utf8_private.h date/date.h membuffer/membuffer.h
./log/log.o: ./log/log.h textstream/textstream.h space/space.h ./log/filelog.o: textstream/types.h
./log/log.o: textstream/types.h convert/inttostr.h date/date.h ./log/log.o: ./log/log.h textstream/textstream.h textstream/stream.h
./log/log.o: membuffer/membuffer.h textstream/types.h ./log/filelog.h ./log/log.o: space/space.h textstream/types.h convert/inttostr.h utf8/utf8.h
./log/log.o: utf8/utf8.h utf8/utf8_templates.h utf8/utf8_private.h ./log/log.o: textstream/stream.h utf8/utf8_templates.h utf8/utf8_private.h
./log/log.o: date/date.h membuffer/membuffer.h textstream/types.h
./log/log.o: ./log/filelog.h
./space/space.o: ./space/space.h textstream/types.h convert/inttostr.h ./space/space.o: ./space/space.h textstream/types.h convert/inttostr.h
./space/space.o: utf8/utf8.h textstream/textstream.h space/space.h ./space/space.o: utf8/utf8.h textstream/stream.h utf8/utf8_templates.h
./space/space.o: date/date.h membuffer/membuffer.h textstream/types.h ./space/space.o: utf8/utf8_private.h convert/convert.h ./convert/inttostr.h
./space/space.o: utf8/utf8_templates.h utf8/utf8_private.h convert/convert.h ./space/space.o: convert/patternreplacer.h textstream/textstream.h
./space/space.o: ./convert/inttostr.h convert/patternreplacer.h ./space/space.o: textstream/stream.h space/space.h date/date.h
./space/space.o: convert/strtoint.h ./convert/text.h ./convert/misc.h ./space/space.o: membuffer/membuffer.h textstream/types.h convert/strtoint.h
./space/space.o: ./convert/text.h ./convert/misc.h ./convert/double.h
./space/spaceparser.o: ./space/spaceparser.h ./space/space.h ./space/spaceparser.o: ./space/spaceparser.h ./space/space.h
./space/spaceparser.o: textstream/types.h convert/inttostr.h utf8/utf8.h ./space/spaceparser.o: textstream/types.h convert/inttostr.h utf8/utf8.h
./space/spaceparser.o: textstream/textstream.h space/space.h date/date.h ./space/spaceparser.o: textstream/stream.h utf8/utf8_templates.h
./space/spaceparser.o: membuffer/membuffer.h textstream/types.h ./space/spaceparser.o: utf8/utf8_private.h convert/strtoint.h
./space/spaceparser.o: utf8/utf8_templates.h utf8/utf8_private.h ./space/spaceparser.o: ./convert/text.h ./convert/misc.h
./space/spaceparser.o: convert/strtoint.h ./convert/text.h ./convert/misc.h ./utf8/utf8.o: ./utf8/utf8.h textstream/stream.h utf8/utf8_templates.h
./utf8/utf8.o: ./utf8/utf8.h textstream/textstream.h space/space.h
./utf8/utf8.o: textstream/types.h convert/inttostr.h date/date.h
./utf8/utf8.o: membuffer/membuffer.h textstream/types.h utf8/utf8_templates.h
./utf8/utf8.o: utf8/utf8_private.h ./utf8/utf8.o: utf8/utf8_private.h
./utf8/utf8_private.o: utf8/utf8_private.h textstream/textstream.h ./utf8/utf8_private.o: utf8/utf8_private.h
./utf8/utf8_private.o: space/space.h textstream/types.h convert/inttostr.h
./utf8/utf8_private.o: date/date.h membuffer/membuffer.h textstream/types.h
./csv/csvparser.o: ./csv/csvparser.h space/space.h textstream/types.h ./csv/csvparser.o: ./csv/csvparser.h space/space.h textstream/types.h
./csv/csvparser.o: convert/inttostr.h utf8/utf8.h textstream/textstream.h ./csv/csvparser.o: convert/inttostr.h utf8/utf8.h textstream/stream.h
./csv/csvparser.o: date/date.h membuffer/membuffer.h textstream/types.h
./csv/csvparser.o: utf8/utf8_templates.h utf8/utf8_private.h ./csv/csvparser.o: utf8/utf8_templates.h utf8/utf8_private.h
./mainoptions/mainoptionsparser.o: ./mainoptions/mainoptionsparser.h ./mainoptions/mainoptionsparser.o: ./mainoptions/mainoptionsparser.h
./mainoptions/mainoptionsparser.o: space/space.h textstream/types.h ./mainoptions/mainoptionsparser.o: space/space.h textstream/types.h
./mainoptions/mainoptionsparser.o: convert/inttostr.h utf8/utf8.h ./mainoptions/mainoptionsparser.o: convert/inttostr.h utf8/utf8.h
./mainoptions/mainoptionsparser.o: textstream/textstream.h date/date.h ./mainoptions/mainoptionsparser.o: textstream/stream.h utf8/utf8_templates.h
./mainoptions/mainoptionsparser.o: membuffer/membuffer.h textstream/types.h ./mainoptions/mainoptionsparser.o: utf8/utf8_private.h
./mainoptions/mainoptionsparser.o: utf8/utf8_templates.h utf8/utf8_private.h

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2012-2018, Tomasz Sowa * Copyright (c) 2012-2021, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -43,5 +43,6 @@
#include "patternreplacer.h" #include "patternreplacer.h"
#include "strtoint.h" #include "strtoint.h"
#include "text.h" #include "text.h"
#include "double.h"
#endif #endif

225
src/convert/double.cpp Normal file
View File

@ -0,0 +1,225 @@
/*
* This file is a part of PikoTools
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdlib>
#include <cwchar>
#include "double.h"
#include "textstream/textstream.h"
namespace pt
{
float to_float(const char * str, const char ** after)
{
char * after_local;
float res = std::strtof(str, &after_local);
if( after )
{
*after = after_local;
}
return res;
}
float to_float(const wchar_t * str, const wchar_t ** after)
{
wchar_t * after_local;
float res = std::wcstof(str, &after_local);
if( after )
{
*after = after_local;
}
return res;
}
double to_double(const char * str, const char ** after)
{
char * after_local;
double res = std::strtod(str, &after_local);
if( after )
{
*after = after_local;
}
return res;
}
double to_double(const wchar_t * str, const wchar_t ** after)
{
wchar_t * after_local;
double res = std::wcstod(str, &after_local);
if( after )
{
*after = after_local;
}
return res;
}
long double to_long_double(const char * str, const char ** after)
{
char * after_local;
long double res = std::strtold(str, &after_local);
if( after )
{
*after = after_local;
}
return res;
}
long double to_long_double(const wchar_t * str, const wchar_t ** after)
{
wchar_t * after_local;
long double res = std::wcstold(str, &after_local);
if( after )
{
*after = after_local;
}
return res;
}
float to_float(const std::string & str, const char ** after)
{
return to_float(str.c_str(), after);
}
float to_float(const std::wstring & str, const wchar_t ** after)
{
return to_float(str.c_str(), after);
}
double to_double(const std::string & str, const char ** after)
{
return to_double(str.c_str(), after);
}
double to_double(const std::wstring & str, const wchar_t ** after)
{
return to_double(str.c_str(), after);
}
long double to_long_double(const std::string & str, const char ** after)
{
return to_long_double(str.c_str(), after);
}
long double to_long_double(const std::wstring & str, const wchar_t ** after)
{
return to_long_double(str.c_str(), after);
}
std::string to_str(float val)
{
TextStream str;
str << val;
return str.to_str();;
}
std::wstring to_wstr(float val)
{
TextStream str;
str << val;
return str.to_wstr();;
}
std::string to_str(double val)
{
TextStream str;
str << val;
return str.to_str();;
}
std::wstring to_wstr(double val)
{
TextStream str;
str << val;
return str.to_wstr();;
}
std::string to_str(long double val)
{
TextStream str;
str << val;
return str.to_str();;
}
std::wstring to_wstr(long double val)
{
TextStream str;
str << val;
return str.to_wstr();;
}
}

80
src/convert/double.h Normal file
View File

@ -0,0 +1,80 @@
/*
* This file is a part of PikoTools
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef headerfile_picotools_membuffer_convert_double
#define headerfile_picotools_membuffer_convert_double
#include <string>
namespace pt
{
float to_float(const char * str, const char ** after = nullptr);
float to_float(const wchar_t * str, const wchar_t ** after = nullptr);
double to_double(const char * str, const char ** after = nullptr);
double to_double(const wchar_t * str, const wchar_t ** after = nullptr);
long double to_long_double(const char * str, const char ** after = nullptr);
long double to_long_double(const wchar_t * str, const wchar_t ** after = nullptr);
float to_float(const std::string & str, const char ** after = nullptr);
float to_float(const std::wstring & str, const wchar_t ** after = nullptr);
double to_double(const std::string & str, const char ** after = nullptr);
double to_double(const std::wstring & str, const wchar_t ** after = nullptr);
long double to_long_double(const std::string & str, const char ** after = nullptr);
long double to_long_double(const std::wstring & str, const wchar_t ** after = nullptr);
std::string to_str(float val);
std::wstring to_wstr(float val);
std::string to_str(double val);
std::wstring to_wstr(double val);
std::string to_str(long double val);
std::wstring to_wstr(long double val);
}
#endif

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2018, Tomasz Sowa * Copyright (c) 2018-2021, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -86,7 +86,7 @@ private:
params.clear(); params.clear();
AddParams(types...); AddParams(types...);
ReplacePattern(pattern); ReplacePattern(pattern);
buffer.to_string(output_string); buffer.to_str(output_string);
params.clear(); params.clear();
buffer.clear(); buffer.clear();
@ -104,7 +104,7 @@ private:
{ {
buffer.clear(); buffer.clear();
buffer << type; buffer << type;
buffer.to_string(temp_str); buffer.to_str(temp_str);
params.push_back(temp_str); params.push_back(temp_str);
temp_str.clear(); temp_str.clear();

View File

@ -463,8 +463,76 @@ bool is_substr_nc(const std::wstring & short_str, const std::wstring & long_str)
} }
void trim_first_white(std::string & str, bool check_additional_chars, bool treat_new_line_as_white)
{
pt_private::trim_first_white_generic(str, check_additional_chars, treat_new_line_as_white);
}
void trim_first_white(std::wstring & str, bool check_additional_chars, bool treat_new_line_as_white)
{
pt_private::trim_first_white_generic(str, check_additional_chars, treat_new_line_as_white);
}
void trim_last_white(std::string & str, bool check_additional_chars, bool treat_new_line_as_white)
{
pt_private::trim_last_white_generic(str, check_additional_chars, treat_new_line_as_white);
}
void trim_last_white(std::wstring & str, bool check_additional_chars, bool treat_new_line_as_white)
{
pt_private::trim_last_white_generic(str, check_additional_chars, treat_new_line_as_white);
}
void trim_white(std::string & str, bool check_additional_chars, bool treat_new_line_as_white)
{
pt_private::trim_white_generic(str, check_additional_chars, treat_new_line_as_white);
}
void trim_white(std::wstring & str, bool check_additional_chars, bool treat_new_line_as_white)
{
pt_private::trim_white_generic(str, check_additional_chars, treat_new_line_as_white);
}
void trim_first(std::string & str, wchar_t c)
{
pt_private::trim_first_generic(str, c);
}
void trim_first(std::wstring & str, wchar_t c)
{
pt_private::trim_first_generic(str, c);
}
void trim_last(std::string & str, wchar_t c)
{
pt_private::trim_last_generic(str, c);
}
void trim_last(std::wstring & str, wchar_t c)
{
pt_private::trim_last_generic(str, c);
}
void trim(std::string & str, wchar_t c)
{
pt_private::trim_generic(str, c);
}
void trim(std::wstring & str, wchar_t c)
{
pt_private::trim_generic(str, c);
}

View File

@ -143,6 +143,26 @@ bool is_substr_nc(const std::string & short_str, const std::string & long_str);
bool is_substr_nc(const std::wstring & short_str, const std::wstring & long_str); bool is_substr_nc(const std::wstring & short_str, const std::wstring & long_str);
void trim_first_white(std::string & str, bool check_additional_chars = true, bool treat_new_line_as_white = true);
void trim_first_white(std::wstring & str, bool check_additional_chars = true, bool treat_new_line_as_white = true);
void trim_last_white(std::string & str, bool check_additional_chars = true, bool treat_new_line_as_white = true);
void trim_last_white(std::wstring & str, bool check_additional_chars = true, bool treat_new_line_as_white = true);
void trim_white(std::string & str, bool check_additional_chars = true, bool treat_new_line_as_white = true);
void trim_white(std::wstring & str, bool check_additional_chars = true, bool treat_new_line_as_white = true);
void trim_first(std::string & str, wchar_t c);
void trim_first(std::wstring & str, wchar_t c);
void trim_last(std::string & str, wchar_t c);
void trim_last(std::wstring & str, wchar_t c);
void trim(std::string & str, wchar_t c);
void trim(std::wstring & str, wchar_t c);
} }

View File

@ -299,6 +299,112 @@ bool is_substr_nc_generic(const StringType1 * short_str, const StringType2 * lon
template<typename StringType>
void trim_first_white_generic(StringType & s, bool check_additional_chars, bool treat_new_line_as_white)
{
size_t i;
if( s.empty() )
return;
// looking for white characters at the beginning
for(i=0 ; i<s.size() && is_white(s[i], check_additional_chars, treat_new_line_as_white) ; ++i);
// deleting white characters at the beginning
if( i != 0 )
s.erase(0, i);
}
template<typename StringType>
void trim_last_white_generic(StringType & s, bool check_additional_chars, bool treat_new_line_as_white)
{
size_t i;
if( s.empty() )
return;
// looking for white characters at the end
for(i=s.size()-1 ; i>0 && is_white(s[i], check_additional_chars, treat_new_line_as_white) ; --i);
if( i==0 && is_white(s[i], check_additional_chars, treat_new_line_as_white) )
{
// the whole string has white characters
s.clear();
return;
}
// deleting white characters at the end
if( i != s.size() - 1 )
s.erase(i+1, StringType::npos);
}
template<typename StringType>
void trim_white_generic(StringType & s, bool check_additional_chars, bool treat_new_line_as_white)
{
if( s.empty() )
return;
trim_last_white_generic(s, check_additional_chars, treat_new_line_as_white);
trim_first_white_generic(s, check_additional_chars, treat_new_line_as_white);
}
template<typename StringType>
void trim_first_generic(StringType & s, wchar_t c)
{
size_t i;
if( s.empty() )
return;
// looking for the 'c' characters at the beginning
for(i=0 ; i<s.size() && s[i]==c ; ++i);
// deleting the 'c' characters at the beginning
if( i != 0 )
s.erase(0, i);
}
template<typename StringType>
void trim_last_generic(StringType & s, wchar_t c)
{
size_t i;
if( s.empty() )
return;
// looking for the 'c' characters at the end
for(i=s.size()-1 ; i>0 && s[i]==c ; --i);
if( i==0 && s[i]==c )
{
// the whole string has the 'c' characters
s.clear();
return;
}
// deleting 'c' characters at the end
if( i != s.size() - 1 )
s.erase(i+1, StringType::npos);
}
template<typename StringType>
void trim_generic(StringType & s, wchar_t c)
{
if( s.empty() )
return;
trim_last_generic(s, c);
trim_first_generic(s, c);
}
} // namespace pt_private } // namespace pt_private

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2012-2018, Tomasz Sowa * Copyright (c) 2012-2021, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -251,12 +251,21 @@ public:
int WeekDay() const; int WeekDay() const;
/*
this method outputs to the given stream the number of a month in Roman numerals
e.g: if month is equal to 3 then III will be put to 'out'
month should be in the range [1,12]
*/
template<class Stream>
static void SerializeMonthAsRoman(Stream & out, int month);
/* /*
this method outputs to the given stream: YYYY-MM-DD, eg. 1990-02-12 this method outputs to the given stream: YYYY-MM-DD, eg. 1990-02-12
ISO 8601 format ISO 8601 format
*/ */
template<class Stream> template<class Stream>
void SerializeYearMonthDay(Stream & out) const; void SerializeYearMonthDay(Stream & out, bool roman_month = false) const;
/* /*
@ -271,7 +280,7 @@ public:
this method outputs to the given stream: MM-DD, eg. 02-12 (02 month, 12 day) this method outputs to the given stream: MM-DD, eg. 02-12 (02 month, 12 day)
*/ */
template<class Stream> template<class Stream>
void SerializeMonthDay(Stream & out) const; void SerializeMonthDay(Stream & out, bool roman_month = false) const;
/* /*
@ -286,7 +295,7 @@ public:
ISO 8601 format ISO 8601 format
*/ */
template<class Stream> template<class Stream>
void Serialize(Stream & out) const; void Serialize(Stream & out, bool roman_month = false, bool with_seconds = true) const;
/* /*
@ -547,13 +556,32 @@ void Date::SerializeInt(Stream & out, int val) const
} }
template<class Stream>
void Date::SerializeMonthAsRoman(Stream & out, int month)
{
const char * month_roman[] = { "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII" };
if( month >= 1 && month <= 12 )
{
const char * month_str = month_roman[month - 1];
for( ; *month_str ; ++month_str)
out << *month_str;
}
}
template<class Stream> template<class Stream>
void Date::SerializeYearMonthDay(Stream & out) const void Date::SerializeYearMonthDay(Stream & out, bool roman_month) const
{ {
SerializeInt(out, year, 4); SerializeInt(out, year, 4);
out << '-'; out << '-';
SerializeInt(out, month);
if( roman_month )
SerializeMonthAsRoman(out, month);
else
SerializeInt(out, month);
out << '-'; out << '-';
SerializeInt(out, day); SerializeInt(out, day);
} }
@ -571,9 +599,13 @@ void Date::SerializeHourMinSec(Stream & out) const
template<class Stream> template<class Stream>
void Date::SerializeMonthDay(Stream & out) const void Date::SerializeMonthDay(Stream & out, bool roman_month) const
{ {
SerializeInt(out, month); if( roman_month )
SerializeMonthAsRoman(out, month);
else
SerializeInt(out, month);
out << '-'; out << '-';
SerializeInt(out, day); SerializeInt(out, day);
} }
@ -589,17 +621,22 @@ void Date::SerializeHourMin(Stream & out) const
template<class Stream> template<class Stream>
void Date::Serialize(Stream & out) const void Date::Serialize(Stream & out, bool roman_month, bool with_seconds) const
{ {
SerializeYearMonthDay(out); SerializeYearMonthDay(out, roman_month);
out << ' '; out << ' ';
SerializeHourMinSec(out);
if( with_seconds )
SerializeHourMinSec(out);
else
SerializeHourMin(out);
} }
template<class Stream> template<class Stream>
void Date::SerializeISO(Stream & out) const void Date::SerializeISO(Stream & out) const
{ {
SerializeYearMonthDay(out); SerializeYearMonthDay(out, false);
out << 'T'; out << 'T';
SerializeHourMinSec(out); SerializeHourMinSec(out);
out << 'Z'; out << 'Z';

View File

@ -41,7 +41,7 @@
#include "date/date.h" #include "date/date.h"
#include "utf8/utf8.h" #include "utf8/utf8.h"
#ifdef PT_HAS_MORM #ifdef PT_HAS_MORM_LIBRARY
#include "morm.h" #include "morm.h"
#endif #endif
@ -54,89 +54,156 @@ Log::Log()
{ {
buffer = nullptr; buffer = nullptr;
file_log = nullptr; file_log = nullptr;
current_level = 4; current_level = 4;
max_buffer_length = 2 * 1024 * 1024; // 2MB max_buffer_length = 2 * 1024 * 1024;
} }
Log::~Log() Log::~Log()
{ {
// IMPROVE ME
// I am not sure if this is a correct behaviour
// the log buffer and file logger may not exist now
// (life time of objects)
// may would be better to have a flag 'clear_at_the_end'
// and if true then call this method?
save_log_and_clear();
} }
void Log::SetLogBuffer(WTextStream * buffer) bool Log::can_put_log()
{ {
this->buffer = buffer; return (buffer && file_log && current_level <= file_log->get_log_level());
} }
WTextStream * Log::GetLogBuffer() bool Log::is_char_stream() const
{ {
return buffer; return false;
} }
void Log::SetMaxBufferLength(size_t max_buffer_length) bool Log::is_wchar_stream() const
{ {
this->max_buffer_length = max_buffer_length; return true;
} }
size_t Log::GetMaxBufferLength()
{
return max_buffer_length;
}
void Log::clear()
void Log::SetFileLog(FileLog * file_log)
{
this->file_log = file_log;
}
FileLog * Log::GetFileLog()
{
return file_log;
}
Log & Log::IntMinWidth(size_t min_width)
{ {
if( buffer ) if( buffer )
{ {
buffer->int_min_width(min_width); buffer->clear();
} }
return *this;
} }
Log & Log::operator<<(const void * s) bool Log::empty() const
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( buffer )
{ {
(*buffer) << s; return buffer->empty();
} }
return *this; return true;
}
size_t Log::size() const
{
if( buffer )
{
buffer->size();
}
return 0;
}
void Log::reserve(size_t len)
{
if( buffer )
{
buffer->reserve(len);
}
}
size_t Log::capacity() const
{
if( buffer )
{
buffer->capacity();
}
return 0;
}
void Log::to_str(std::string & str, bool clear_string) const
{
if( buffer )
{
buffer->to_str(str, clear_string);
}
}
void Log::to_str(std::wstring & str, bool clear_string) const
{
if( buffer )
{
buffer->to_str(str, clear_string);
}
}
std::string Log::to_str() const
{
if( buffer )
{
return buffer->to_str();
}
return std::string();
}
std::wstring Log::to_wstr() const
{
if( buffer )
{
return buffer->to_wstr();
}
return std::wstring();
}
char Log::get_char(size_t index) const
{
if( buffer )
{
return buffer->get_char(index);
}
return 0;
}
wchar_t Log::get_wchar(size_t index) const
{
if( buffer )
{
return buffer->get_wchar(index);
}
return 0;
} }
Log & Log::operator<<(const char * s) Log & Log::operator<<(const char * s)
{ {
if( buffer && file_log && s && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
utf8_to_wide(s, *buffer, false); (*buffer) << s;
} }
return *this; return *this;
@ -146,34 +213,18 @@ Log & Log::operator<<(const char * s)
Log & Log::operator<<(const std::string & s) Log & Log::operator<<(const std::string & s)
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
utf8_to_wide(s, *buffer, false); (*buffer) << s;
} }
return *this; return *this;
} }
Log & Log::operator<<(const std::string * s)
{
if( buffer && file_log && current_level <= file_log->get_log_level() )
{
utf8_to_wide(*s, *buffer, false);
}
return *this;
}
Log & Log::operator<<(const wchar_t * s) Log & Log::operator<<(const wchar_t * s)
{ {
if( buffer && file_log && s && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
(*buffer) << s; (*buffer) << s;
} }
@ -182,10 +233,9 @@ Log & Log::operator<<(const wchar_t * s)
} }
Log & Log::operator<<(const std::wstring & s) Log & Log::operator<<(const std::wstring & s)
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
(*buffer) << s; (*buffer) << s;
} }
@ -194,89 +244,151 @@ Log & Log::operator<<(const std::wstring & s)
} }
Log & Log::operator<<(char val)
Log & Log::operator<<(const std::wstring * s)
{ {
if( buffer && file_log && s && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
(*buffer) << *s; (*buffer) << val;
} }
return *this; return *this;
} }
Log & Log::operator<<(unsigned char val)
{
if( can_put_log() )
{
(*buffer) << val;
}
return *this;
}
Log & Log::operator<<(wchar_t val)
Log & Log::operator<<(int s)
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( buffer && file_log && current_level <= file_log->get_log_level() )
{ {
(*buffer) << s; (*buffer) << val;
} }
return *this; return *this;
} }
Log & Log::operator<<(bool val)
Log & Log::operator<<(long s)
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
(*buffer) << s; (*buffer) << val;
} }
return *this; return *this;
} }
Log & Log::operator<<(long long s) Log & Log::operator<<(short val)
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
(*buffer) << s; (*buffer) << val;
} }
return *this; return *this;
} }
Log & Log::operator<<(char s) Log & Log::operator<<(int val)
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
(*buffer) << s; (*buffer) << val;
} }
return *this; return *this;
} }
Log & Log::operator<<(wchar_t s)
Log & Log::operator<<(long val)
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
(*buffer) << s; (*buffer) << val;
} }
return *this; return *this;
} }
Log & Log::operator<<(size_t s) Log & Log::operator<<(long long val)
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
(*buffer) << s; (*buffer) << val;
} }
return *this; return *this;
} }
Log & Log::operator<<(unsigned short val)
{
if( can_put_log() )
{
(*buffer) << val;
}
return *this;
}
Log & Log::operator<<(unsigned int val)
{
if( can_put_log() )
{
(*buffer) << val;
}
return *this;
}
Log & Log::operator<<(unsigned long val)
{
if( can_put_log() )
{
(*buffer) << val;
}
return *this;
}
Log & Log::operator<<(unsigned long long val)
{
if( can_put_log() )
{
(*buffer) << val;
}
return *this;
}
Log & Log::operator<<(float val)
{
if( can_put_log() )
{
(*buffer) << val;
}
return *this;
}
Log & Log::operator<<(double s) Log & Log::operator<<(double s)
{ {
@ -289,10 +401,20 @@ Log & Log::operator<<(double s)
} }
Log & Log::operator<<(long double val)
Log & Log::operator<<(const Space & s)
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{
(*buffer) << val;
}
return *this;
}
Log & Log::operator<<(const void * s)
{
if( can_put_log() )
{ {
(*buffer) << s; (*buffer) << s;
} }
@ -301,10 +423,31 @@ Log & Log::operator<<(const Space & s)
} }
Log & Log::operator<<(const Stream & stream)
{
if( can_put_log() )
{
(*buffer) << stream;
}
return *this;
}
Log & Log::operator<<(const Space & s)
{
if( can_put_log() )
{
(*buffer) << s;
}
return *this;
}
Log & Log::operator<<(const Date & date) Log & Log::operator<<(const Date & date)
{ {
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
(*buffer) << date; (*buffer) << date;
} }
@ -313,7 +456,7 @@ Log & Log::operator<<(const Date & date)
} }
#ifdef PT_HAS_MORM #ifdef PT_HAS_MORM_LIBRARY
Log & Log::operator<<(morm::Model & model) Log & Log::operator<<(morm::Model & model)
{ {
operator<<(model.to_string()); operator<<(model.to_string());
@ -322,13 +465,35 @@ Log & Log::operator<<(morm::Model & model)
#endif #endif
Log & Log::write(const char * buf, size_t len)
{
if( can_put_log() )
{
buffer->write(buf, len);
}
return *this;
}
Log & Log::write(const wchar_t * buf, size_t len)
{
if( can_put_log() )
{
buffer->write(buf, len);
}
return *this;
}
Log & Log::operator<<(Manipulators m) Log & Log::operator<<(Manipulators m)
{ {
switch(m) switch(m)
{ {
case lend:
case logend: case logend:
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
(*buffer) << '\n'; (*buffer) << '\n';
@ -337,27 +502,22 @@ Log & Log::operator<<(Manipulators m)
} }
break; break;
case lsave:
case logsave: case logsave:
save_log_and_clear(); save_log_and_clear();
break; break;
case l1:
case log1: case log1:
current_level = 1; current_level = 1;
break; break;
case l2:
case log2: case log2:
current_level = 2; current_level = 2;
break; break;
case l3:
case log3: case log3:
current_level = 3; current_level = 3;
break; break;
case l4:
case log4: case log4:
current_level = 4; current_level = 4;
break; break;
@ -370,20 +530,65 @@ Log & Log::operator<<(Manipulators m)
} }
Log & Log::LogString(const std::string & value, size_t max_size) void Log::set_log_buffer(WTextStream * buffer)
{
this->buffer = buffer;
}
WTextStream * Log::get_log_buffer()
{
return buffer;
}
void Log::set_max_buffer_length(size_t max_buffer_length)
{
this->max_buffer_length = max_buffer_length;
}
size_t Log::get_max_buffer_length()
{
return max_buffer_length;
}
void Log::set_file_log(FileLog * file_log)
{
this->file_log = file_log;
}
FileLog * Log::get_file_log()
{
return file_log;
}
Log & Log::int_min_width(size_t min_width)
{
if( buffer )
{
buffer->int_min_width(min_width);
}
return *this;
}
Log & Log::put_string(const std::string & value, size_t max_size)
{ {
return log_string_generic(value, max_size); return log_string_generic(value, max_size);
} }
Log & Log::LogString(const std::wstring & value, size_t max_size) Log & Log::put_string(const std::wstring & value, size_t max_size)
{ {
return log_string_generic(value, max_size); return log_string_generic(value, max_size);
} }
char Log::get_hex_digit(unsigned char c) char Log::get_hex_digit(unsigned char c)
{ {
if( c < 10 ) if( c < 10 )
@ -393,7 +598,6 @@ return c - 10 + 'A';
} }
void Log::to_hex(char * buf, unsigned char c) void Log::to_hex(char * buf, unsigned char c)
{ {
buf[0] = get_hex_digit(c >> 4); buf[0] = get_hex_digit(c >> 4);
@ -402,12 +606,12 @@ void Log::to_hex(char * buf, unsigned char c)
} }
Log & Log::LogBinary(const char * blob, size_t blob_len) Log & Log::put_binary_blob(const char * blob, size_t blob_len)
{ {
size_t i=0; size_t i=0;
char buf[3]; char buf[3];
if( buffer && file_log && blob && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
while( i < blob_len ) while( i < blob_len )
{ {
@ -454,13 +658,12 @@ char buf[3];
} }
Log & Log::LogBinary(const std::string & blob) Log & Log::put_binary_blob(const std::string & blob)
{ {
return LogBinary(blob.c_str(), blob.size()); return put_binary_blob(blob.c_str(), blob.size());
} }
void Log::save_log_and_clear() void Log::save_log_and_clear()
{ {
save_log(); save_log();
@ -483,7 +686,3 @@ void Log::save_log()
} // namespace } // namespace

View File

@ -45,22 +45,16 @@
namespace morm
{
class Model;
}
namespace pt namespace pt
{ {
class Log : public Stream
class Log
{ {
public: public:
/* /*
log1 - the first level log1 - the first level
log2 log2
@ -76,81 +70,91 @@ public:
log3, log3,
log4, log4,
l1,
l2,
l3,
l4,
logend, logend,
lend,
logsave, logsave,
lsave,
}; };
Log(); Log();
virtual ~Log(); ~Log();
virtual void SetLogBuffer(WTextStream * buffer); bool is_char_stream() const;
virtual WTextStream * GetLogBuffer(); bool is_wchar_stream() const;
void SetFileLog(FileLog * file_log); void clear();
FileLog * GetFileLog(); bool empty() const;
size_t size() const;
void reserve(size_t len);
size_t capacity() const;
void SetMaxBufferLength(size_t max_buffer_length); void to_str(std::string & str, bool clear_string = true) const;
size_t GetMaxBufferLength(); void to_str(std::wstring & str, bool clear_string = true) const;
virtual Log & IntMinWidth(size_t min_width); std::string to_str() const;
std::wstring to_wstr() const;
virtual Log & operator<<(const void * s); char get_char(size_t index) const;
wchar_t get_wchar(size_t index) const;
virtual Log & operator<<(const char * s); Log & operator<<(const char * s);
virtual Log & operator<<(const std::string * s); Log & operator<<(const std::string & s);
virtual Log & operator<<(const std::string & s); Log & operator<<(const wchar_t * s);
Log & operator<<(const std::wstring & s);
virtual Log & operator<<(const wchar_t * s); Log & operator<<(char val);
virtual Log & operator<<(const std::wstring * s); Log & operator<<(unsigned char val);
virtual Log & operator<<(const std::wstring & s); Log & operator<<(wchar_t val);
Log & operator<<(bool val);
Log & operator<<(short val);
Log & operator<<(int s);
Log & operator<<(long s);
Log & operator<<(long long s);
Log & operator<<(unsigned short val);
Log & operator<<(unsigned int val);
Log & operator<<(unsigned long val);
Log & operator<<(unsigned long long val);
Log & operator<<(float val);
Log & operator<<(double s);
Log & operator<<(long double val);
Log & operator<<(const void * s);
virtual Log & operator<<(char s); Log & operator<<(const Stream & stream);
virtual Log & operator<<(wchar_t s); Log & operator<<(const Space & space);
Log & operator<<(const Date & date);
virtual Log & operator<<(int s); #ifdef PT_HAS_MORM_LIBRARY
virtual Log & operator<<(long s);
virtual Log & operator<<(long long s);
// add unsigned long, unsigned int
virtual Log & operator<<(size_t s);
//virtual Log & operator<<(float s); // added
virtual Log & operator<<(double s);
virtual Log & operator<<(const Space & space);
virtual Log & operator<<(const Date & date);
#ifdef PT_HAS_MORM
virtual Log & operator<<(morm::Model & model); virtual Log & operator<<(morm::Model & model);
#endif #endif
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
Log & operator<<(const TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg);
Log & write(const char * buf, size_t len);
Log & write(const wchar_t * buf, size_t len);
/*
* methods specific to Log class
*
*/
virtual Log & operator<<(Manipulators m); virtual Log & operator<<(Manipulators m);
virtual void set_log_buffer(WTextStream * buffer);
virtual WTextStream * get_log_buffer();
void set_file_log(FileLog * file_log);
FileLog * get_file_log();
void set_max_buffer_length(size_t max_buffer_length);
size_t get_max_buffer_length();
virtual Log & LogString(const std::string & value, size_t max_size); virtual Log & int_min_width(size_t min_width);
virtual Log & LogString(const std::wstring & value, size_t max_size);
virtual Log & put_string(const std::string & value, size_t max_size);
virtual Log & put_string(const std::wstring & value, size_t max_size);
template<typename char_type, size_t stack_size, size_t heap_block_size> virtual Log & put_binary_blob(const char * blob, size_t blob_len);
Log & operator<<(const TextStreamBase<char_type, stack_size, heap_block_size> & buf); virtual Log & put_binary_blob(const std::string & blob);
virtual Log & LogBinary(const char * blob, size_t blob_len);
virtual Log & LogBinary(const std::string & blob);
@ -176,6 +180,7 @@ protected:
template<class StringType> template<class StringType>
Log & log_string_generic(const StringType & value, size_t max_size); Log & log_string_generic(const StringType & value, size_t max_size);
virtual bool can_put_log();
virtual void save_log(); virtual void save_log();
virtual void save_log_and_clear(); virtual void save_log_and_clear();
@ -183,12 +188,24 @@ protected:
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
Log & Log::operator<<(const TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg)
{
if( can_put_log() )
{
(*buffer) << arg;
}
return *this;
}
template<class StringType> template<class StringType>
Log & Log::log_string_generic(const StringType & value, size_t max_size) Log & Log::log_string_generic(const StringType & value, size_t max_size)
{ {
std::size_t min_size = value.size() < max_size ? value.size() : max_size; std::size_t min_size = value.size() < max_size ? value.size() : max_size;
if( buffer && file_log && current_level <= file_log->get_log_level() ) if( can_put_log() )
{ {
for(size_t i=0 ; i < min_size ; ++i) for(size_t i=0 ; i < min_size ; ++i)
{ {
@ -204,19 +221,6 @@ Log & Log::log_string_generic(const StringType & value, size_t max_size)
template<typename char_type, size_t stack_size, size_t heap_block_size>
Log & Log::operator<<(const TextStreamBase<char_type, stack_size, heap_block_size> & buf)
{
if( buffer && file_log && current_level <= file_log->get_log_level() )
{
(*buffer) << buf;
}
return *this;
}
} // namespace } // namespace

View File

@ -346,7 +346,7 @@ void MainOptionsParser::parse_non_option_arguments(size_t argc, const char ** ar
void MainOptionsParser::add_option_to_space(const std::wstring & option, const std::vector<std::wstring> & arguments) void MainOptionsParser::add_option_to_space(const std::wstring & option, const std::vector<std::wstring> & arguments)
{ {
Space * option_table = space->get_object_field(option); Space * option_table = space->get_space(option);
if( !option_table ) if( !option_table )
{ {

File diff suppressed because it is too large Load Diff

View File

@ -44,9 +44,10 @@
#include <map> #include <map>
#include <cstdio> #include <cstdio>
#include <cwchar> #include <cwchar>
#include <errno.h>
#include "textstream/types.h" #include "textstream/types.h"
#include "convert/inttostr.h" #include "convert/inttostr.h"
#include <errno.h> #include "utf8/utf8.h"
@ -135,9 +136,6 @@ public:
typedef std::map<std::wstring, Space*> ObjectType; typedef std::map<std::wstring, Space*> ObjectType;
typedef std::vector<Space*> TableType; typedef std::vector<Space*> TableType;
constexpr static const wchar_t * child_spaces_field_table_name = L"child_spaces";
constexpr static const wchar_t * child_spaces_name = L"name";
enum Escape enum Escape
{ {
no_escape, no_escape,
@ -152,6 +150,7 @@ public:
type_long, type_long,
type_float, type_float,
type_double, type_double,
type_long_double,
type_string, type_string,
type_wstring, type_wstring,
type_object, type_object,
@ -164,6 +163,7 @@ public:
long long value_long; long long value_long;
float value_float; float value_float;
double value_double; double value_double;
long double value_long_double;
std::string value_string; std::string value_string;
std::wstring value_wstring; std::wstring value_wstring;
ObjectType value_object; ObjectType value_object;
@ -201,6 +201,7 @@ public:
Space(unsigned long long val); Space(unsigned long long val);
Space(float val); Space(float val);
Space(double val); Space(double val);
Space(long double val);
Space(const char * str); Space(const char * str);
Space(const wchar_t * str); Space(const wchar_t * str);
Space(const std::string & str); Space(const std::string & str);
@ -234,6 +235,7 @@ public:
void set(unsigned long long val); void set(unsigned long long val);
void set(float val); void set(float val);
void set(double val); void set(double val);
void set(long double val);
void set(const char * str); void set(const char * str);
void set(const wchar_t * str); void set(const wchar_t * str);
void set(const std::string & str); void set(const std::string & str);
@ -255,6 +257,7 @@ public:
Space & add(unsigned long long val); Space & add(unsigned long long val);
Space & add(float val); Space & add(float val);
Space & add(double val); Space & add(double val);
Space & add(long double val);
Space & add(const char * val); Space & add(const char * val);
Space & add(const wchar_t * val); Space & add(const wchar_t * val);
Space & add(const std::string & val); Space & add(const std::string & val);
@ -278,6 +281,7 @@ public:
Space & add(const wchar_t * field, unsigned long long val); Space & add(const wchar_t * field, unsigned long long val);
Space & add(const wchar_t * field, float val); Space & add(const wchar_t * field, float val);
Space & add(const wchar_t * field, double val); Space & add(const wchar_t * field, double val);
Space & add(const wchar_t * field, long double val);
Space & add(const wchar_t * field, const char * val); Space & add(const wchar_t * field, const char * val);
Space & add(const wchar_t * field, const wchar_t * val); Space & add(const wchar_t * field, const wchar_t * val);
Space & add(const wchar_t * field, const std::string & val); Space & add(const wchar_t * field, const std::string & val);
@ -298,6 +302,7 @@ public:
Space & add(const std::wstring & field, unsigned long long val); Space & add(const std::wstring & field, unsigned long long val);
Space & add(const std::wstring & field, float val); Space & add(const std::wstring & field, float val);
Space & add(const std::wstring & field, double val); Space & add(const std::wstring & field, double val);
Space & add(const std::wstring & field, long double val);
Space & add(const std::wstring & field, const char * val); Space & add(const std::wstring & field, const char * val);
Space & add(const std::wstring & field, const wchar_t * val); Space & add(const std::wstring & field, const wchar_t * val);
Space & add(const std::wstring & field, const std::string & val); Space & add(const std::wstring & field, const std::string & val);
@ -313,7 +318,7 @@ public:
Space & add_stream(const wchar_t * field, StreamType & str) Space & add_stream(const wchar_t * field, StreamType & str)
{ {
std::wstring temp; std::wstring temp;
str.to_string(temp); str.to_str(temp);
return add(field, temp); return add(field, temp);
} }
@ -322,7 +327,7 @@ public:
Space & add_stream(const std::wstring & field, StreamType & str) Space & add_stream(const std::wstring & field, StreamType & str)
{ {
std::wstring temp; std::wstring temp;
str.to_string(temp); str.to_str(temp);
return add(field, temp); return add(field, temp);
} }
@ -335,6 +340,7 @@ public:
bool is_long_long() const; bool is_long_long() const;
bool is_float() const; bool is_float() const;
bool is_double() const; bool is_double() const;
bool is_long_double() const;
bool is_numeric() const; bool is_numeric() const;
bool is_str() const; bool is_str() const;
bool is_wstr() const; bool is_wstr() const;
@ -355,6 +361,9 @@ public:
unsigned long to_ulong() const; unsigned long to_ulong() const;
unsigned long long to_ullong() const; unsigned long long to_ullong() const;
unsigned long long to_ulong_long() const; unsigned long long to_ulong_long() const;
float to_float() const;
double to_double() const;
long double to_long_double() const;
std::string to_str() const; std::string to_str() const;
std::wstring to_wstr() const; std::wstring to_wstr() const;
@ -418,6 +427,7 @@ public:
long long * get_long_long(); long long * get_long_long();
float * get_float(); float * get_float();
double * get_double(); double * get_double();
long double * get_long_double();
std::string * get_str(); std::string * get_str();
std::wstring * get_wstr(); std::wstring * get_wstr();
ObjectType * get_object(); ObjectType * get_object();
@ -443,17 +453,21 @@ public:
// size_t argument will be only for tables, wchar_t* or std::wstring for objects? // size_t argument will be only for tables, wchar_t* or std::wstring for objects?
// getters from object // getters from object
Space * get_object_field(const wchar_t * field); // may a better name? Space * get_space(const wchar_t * field);
const Space * get_object_field(const wchar_t * field) const; // may a better name? const Space * get_space(const wchar_t * field) const;
Space * get_object_field(const std::wstring & field); Space * get_space(const std::wstring & field);
const Space * get_object_field(const std::wstring & field) const; // may a better name? const Space * get_space(const std::wstring & field) const;
// find for such a space in an object, if not found then create one
Space & get_add_space(const wchar_t * field);
Space & get_add_space(const std::wstring & field);
bool * get_bool(const wchar_t * field); bool * get_bool(const wchar_t * field);
long long * get_llong(const wchar_t * field); long long * get_llong(const wchar_t * field);
long long * get_long_long(const wchar_t * field); long long * get_long_long(const wchar_t * field);
float * get_float(const wchar_t * field); float * get_float(const wchar_t * field);
double * get_double(const wchar_t * field); double * get_double(const wchar_t * field);
long double * get_long_double(const wchar_t * field);
std::string * get_str(const wchar_t * field); std::string * get_str(const wchar_t * field);
std::wstring * get_wstr(const wchar_t * field); std::wstring * get_wstr(const wchar_t * field);
ObjectType * get_object(const wchar_t * field); ObjectType * get_object(const wchar_t * field);
@ -466,6 +480,7 @@ public:
const long long * get_long_long() const; const long long * get_long_long() const;
const float * get_float() const; const float * get_float() const;
const double * get_double() const; const double * get_double() const;
const long double * get_long_double() const;
const std::string * get_str() const; const std::string * get_str() const;
const std::wstring * get_wstr() const; const std::wstring * get_wstr() const;
const ObjectType * get_object() const; const ObjectType * get_object() const;
@ -480,6 +495,7 @@ public:
const long long * get_long_long(const wchar_t * field) const; const long long * get_long_long(const wchar_t * field) const;
const float * get_float(const wchar_t * field) const; const float * get_float(const wchar_t * field) const;
const double * get_double(const wchar_t * field) const; const double * get_double(const wchar_t * field) const;
const long double * get_long_double(const wchar_t * field) const;
const std::string * get_str(const wchar_t * field) const; const std::string * get_str(const wchar_t * field) const;
const std::wstring * get_wstr(const wchar_t * field) const; const std::wstring * get_wstr(const wchar_t * field) const;
const ObjectType * get_object(const wchar_t * field) const; const ObjectType * get_object(const wchar_t * field) const;
@ -488,10 +504,10 @@ public:
// no case, has O(n) complexity // no case, has O(n) complexity
Space * get_object_field_nc(const wchar_t * field); Space * get_space_nc(const wchar_t * field);
Space * get_object_field_nc(const std::wstring & field); Space * get_space_nc(const std::wstring & field);
const Space * get_object_field_nc(const wchar_t * field) const; const Space * get_space_nc(const wchar_t * field) const;
const Space * get_object_field_nc(const std::wstring & field) const; const Space * get_space_nc(const std::wstring & field) const;
@ -499,6 +515,29 @@ public:
void remove(const wchar_t * field); void remove(const wchar_t * field);
void remove(const std::wstring & field); void remove(const std::wstring & field);
// remove a table item
void remove(size_t table_index);
template<typename StreamType>
void serialize_to_string(StreamType & stream) const
{
if( type == type_wstring )
{
stream << value.value_wstring;
}
else
if( type == type_string )
{
stream << value.value_string;
}
else
{
serialize_to_json_stream(stream);
}
}
std::string serialize_to_space_str(bool pretty_print = false) const; std::string serialize_to_space_str(bool pretty_print = false) const;
std::wstring serialize_to_space_wstr(bool pretty_print = false) const; std::wstring serialize_to_space_wstr(bool pretty_print = false) const;
@ -510,7 +549,7 @@ public:
{ {
if( is_object() ) if( is_object() )
{ {
serialize_to_space_stream(str, pretty_print, 0, true); serialize_to_space_stream(str, pretty_print, -1, true);
} }
} }
@ -524,6 +563,13 @@ public:
template<typename StreamType> template<typename StreamType>
void serialize_to_json_stream(StreamType & str, bool pretty_print = false) const void serialize_to_json_stream(StreamType & str, bool pretty_print = false) const
{
serialize_to_json_stream(str, pretty_print, 0);
}
// make me private
template<typename StreamType>
void serialize_to_json_stream(StreamType & str, bool pretty_print, int level) const
{ {
switch(type) switch(type)
{ {
@ -547,6 +593,10 @@ public:
serialize_json_double(str); serialize_json_double(str);
break; break;
case type_long_double:
serialize_json_long_double(str);
break;
case type_string: case type_string:
serialize_json_string(str); serialize_json_string(str);
break; break;
@ -556,11 +606,11 @@ public:
break; break;
case type_object: case type_object:
serialize_json_object(str); serialize_json_object(str, pretty_print, level + 1);
break; break;
case type_table: case type_table:
serialize_json_table(str); serialize_json_table(str, pretty_print, level + 1);
break; break;
} }
} }
@ -580,39 +630,7 @@ public:
bool has_value(const wchar_t * field, const std::wstring & val) const; bool has_value(const wchar_t * field, const std::wstring & val) const;
// for child spaces (used only in Space format)
TableType * find_child_space_table();
const TableType * find_child_space_table() const;
bool child_spaces_empty() const;
size_t child_spaces_size() const;
Space * find_child_space(const wchar_t * name);
Space * find_child_space(const std::wstring & name);
const Space * find_child_space(const wchar_t * name) const;
const Space * find_child_space(const std::wstring & name) const;
Space * find_child_space(size_t table_index);
const Space * find_child_space(size_t table_index) const;
Space & add_child_space();
Space & add_child_space(const wchar_t * space_name);
Space & add_child_space(const std::wstring & space_name);
Space & find_add_child_space(const wchar_t * name);
Space & find_add_child_space(const std::wstring & name);
std::wstring * find_child_space_name();
const std::wstring * find_child_space_name() const;
std::wstring get_child_space_name() const;
bool is_child_space_name(const wchar_t * name) const;
bool is_child_space_name(const std::wstring & name) const;
void remove_child_space(const wchar_t * name);
void remove_child_space(const std::wstring & name);
void remove_child_space(size_t index);
protected: protected:
@ -634,9 +652,16 @@ protected:
Space & add_generic(const wchar_t * field, const ArgType & val) Space & add_generic(const wchar_t * field, const ArgType & val)
{ {
initialize_value_object_if_needed(); initialize_value_object_if_needed();
auto insert_res = value.value_object.insert(std::make_pair(field, nullptr)); auto insert_res = value.value_object.insert(std::make_pair(field, nullptr));
insert_res.first->second = new Space(val);
if( insert_res.second )
{
insert_res.first->second = new Space(val);
}
else
{
insert_res.first->second->set(val);
}
return *(insert_res.first->second); return *(insert_res.first->second);
} }
@ -733,7 +758,7 @@ protected:
if( clear_list ) if( clear_list )
output_list.clear(); output_list.clear();
const Space * space = get_object_field(field); const Space * space = get_space(field);
if( space ) if( space )
{ {
@ -751,7 +776,7 @@ protected:
if( clear_list ) if( clear_list )
output_list.clear(); output_list.clear();
const Space * space = get_object_field(field); const Space * space = get_space(field);
if( space ) if( space )
{ {
@ -948,7 +973,7 @@ protected:
wchar_t buffer[100]; wchar_t buffer[100];
size_t buffer_len = sizeof(buffer) / sizeof(wchar_t); size_t buffer_len = sizeof(buffer) / sizeof(wchar_t);
int chars_written = std::swprintf(buffer, buffer_len, L"%e", static_cast<double>(value.value_float)); int chars_written = std::swprintf(buffer, buffer_len, L"%g", static_cast<double>(value.value_float));
if( errno == EOVERFLOW || chars_written < 0 ) if( errno == EOVERFLOW || chars_written < 0 )
buffer[0] = 0; buffer[0] = 0;
@ -962,7 +987,21 @@ protected:
wchar_t buffer[100]; wchar_t buffer[100];
size_t buffer_len = sizeof(buffer) / sizeof(wchar_t); size_t buffer_len = sizeof(buffer) / sizeof(wchar_t);
int chars_written = std::swprintf(buffer, buffer_len, L"%e", value.value_double); int chars_written = std::swprintf(buffer, buffer_len, L"%g", value.value_double);
if( errno == EOVERFLOW || chars_written < 0 )
buffer[0] = 0;
serialize_string_buffer(buffer, str, Escape::escape_space);
}
template<typename StreamType>
void serialize_space_long_double(StreamType & str) const
{
wchar_t buffer[100];
size_t buffer_len = sizeof(buffer) / sizeof(wchar_t);
int chars_written = std::swprintf(buffer, buffer_len, L"%Lg", value.value_long_double);
if( errno == EOVERFLOW || chars_written < 0 ) if( errno == EOVERFLOW || chars_written < 0 )
buffer[0] = 0; buffer[0] = 0;
@ -992,19 +1031,26 @@ protected:
if( !is_main_object ) if( !is_main_object )
{ {
str << '{'; str << '{';
print_if(pretty_print && (!value.value_object.empty() || !child_spaces_empty()), str, '\n');
} }
bool is_first = true; bool is_first = true;
for(auto & map_item : value.value_object) for(auto & map_item : value.value_object)
{ {
if( !is_first ) if( is_first )
print_if(pretty_print, str, '\n', ','); {
print_if(pretty_print, str, '\n');
print_level(pretty_print, level, str);
}
else
{
str << ',';
print_if(pretty_print, str, '\n');
print_level(pretty_print, level, str);
}
bool quote_field = should_field_be_quoted(map_item.first); bool quote_field = should_field_be_quoted(map_item.first);
print_level(pretty_print, level, str);
print_if(quote_field, str, '"'); print_if(quote_field, str, '"');
serialize_string_buffer(map_item.first.c_str(), str, Escape::escape_space); serialize_string_buffer(map_item.first.c_str(), str, Escape::escape_space);
print_if(quote_field, str, '"'); print_if(quote_field, str, '"');
@ -1013,87 +1059,52 @@ protected:
str << '='; str << '=';
print_if(pretty_print, str, ' '); print_if(pretty_print, str, ' ');
map_item.second->serialize_to_space_stream(str, pretty_print, level + 1, false); map_item.second->serialize_to_space_stream(str, pretty_print, level, false);
is_first = false; is_first = false;
} }
print_if(!is_first && pretty_print, str, '\n');
serialize_child_spaces(str, pretty_print, level);
if( !is_main_object ) if( !is_main_object )
{ {
print_level(pretty_print, level - 1, str); print_if(pretty_print && !is_first, str, '\n');
print_level(pretty_print && !is_first, level - 1, str);
str << '}'; str << '}';
print_if(pretty_print, str, '\n');
} }
} }
template<typename StreamType>
void serialize_child_spaces(StreamType & str, bool pretty_print, int level) const
{
const TableType * child_table = find_child_space_table();
if( child_table && !child_table->empty() )
{
print_if(pretty_print, str, '\n');
for(Space * child_space : *child_table)
{
print_if(!pretty_print, str, ' ');
const std::wstring * name = child_space->get_wstr(child_spaces_name);
if( name && !name->empty() )
{
bool quote_field = should_field_be_quoted(*name);
print_level(pretty_print, level, str);
print_if(quote_field, str, '"');
serialize_string_buffer(name->c_str(), str, Escape::escape_space);
print_if(quote_field, str, '"');
str << ' ';
}
child_space->serialize_to_space_stream(str, pretty_print, level + 1, false);
print_if(pretty_print, str, '\n');
}
}
}
template<typename StreamType> template<typename StreamType>
void serialize_space_table(StreamType & str, bool pretty_print, int level) const void serialize_space_table(StreamType & str, bool pretty_print, int level) const
{ {
bool multivalue_table = false;
bool is_first = true; bool is_first = true;
if( value.value_table.size() > 1 )
{
multivalue_table = true;
}
str << '('; str << '(';
print_if(pretty_print && multivalue_table, str, '\n');
for(Space * space : value.value_table) for(Space * space : value.value_table)
{ {
if( !is_first ) if( is_first )
print_if(pretty_print, str, '\n', ','); {
print_if(pretty_print, str, '\n');
print_level(pretty_print, level, str);
}
else
{
str << ',';
print_if(pretty_print, str, '\n');
print_level(pretty_print, level, str);
}
print_level(pretty_print && multivalue_table, level, str); space->serialize_to_space_stream(str, pretty_print, level, false);
space->serialize_to_space_stream(str, pretty_print, level + 1, false);
is_first = false; is_first = false;
} }
print_if(pretty_print && multivalue_table, str, '\n'); print_if(pretty_print && !is_first, str, '\n');
print_level(pretty_print && multivalue_table, level - 1, str); print_level(pretty_print && !is_first, level - 1, str);
str << ')'; str << ')';
} }
protected:
template<typename StreamType> template<typename StreamType>
@ -1132,7 +1143,7 @@ protected:
wchar_t buffer[100]; wchar_t buffer[100];
size_t buffer_len = sizeof(buffer) / sizeof(wchar_t); size_t buffer_len = sizeof(buffer) / sizeof(wchar_t);
int chars_written = std::swprintf(buffer, buffer_len, L"%e", static_cast<double>(value.value_float)); int chars_written = std::swprintf(buffer, buffer_len, L"%g", static_cast<double>(value.value_float));
if( errno == EOVERFLOW || chars_written < 0 ) if( errno == EOVERFLOW || chars_written < 0 )
buffer[0] = 0; buffer[0] = 0;
@ -1146,7 +1157,21 @@ protected:
wchar_t buffer[100]; wchar_t buffer[100];
size_t buffer_len = sizeof(buffer) / sizeof(wchar_t); size_t buffer_len = sizeof(buffer) / sizeof(wchar_t);
int chars_written = std::swprintf(buffer, buffer_len, L"%e", value.value_double); int chars_written = std::swprintf(buffer, buffer_len, L"%g", value.value_double);
if( errno == EOVERFLOW || chars_written < 0 )
buffer[0] = 0;
serialize_string_buffer(buffer, str, Escape::escape_json);
}
template<typename StreamType>
void serialize_json_long_double(StreamType & str) const
{
wchar_t buffer[100];
size_t buffer_len = sizeof(buffer) / sizeof(wchar_t);
int chars_written = std::swprintf(buffer, buffer_len, L"%Lg", value.value_long_double);
if( errno == EOVERFLOW || chars_written < 0 ) if( errno == EOVERFLOW || chars_written < 0 )
buffer[0] = 0; buffer[0] = 0;
@ -1171,53 +1196,70 @@ protected:
} }
template<typename StreamType> template<typename StreamType>
void serialize_json_object(StreamType & str) const void serialize_json_object(StreamType & str, bool pretty_print, int level) const
{ {
str << '{'; str << '{';
bool is_first = true; bool is_first = true;
for(auto & map_item : value.value_object) for(auto & map_item : value.value_object)
{ {
if( !is_first ) if( is_first )
{
print_if(pretty_print, str, '\n');
print_level(pretty_print, level, str);
}
else
{ {
str << ','; str << ',';
print_if(pretty_print, str, '\n');
print_level(pretty_print, level, str);
} }
str << '"'; str << '"';
serialize_string_buffer(map_item.first.c_str(), str, Escape::escape_json); serialize_string_buffer(map_item.first.c_str(), str, Escape::escape_json);
str << '"'; str << '"';
str << ':'; str << ':';
map_item.second->serialize_to_json_stream(str); print_if(pretty_print, str, ' ');
map_item.second->serialize_to_json_stream(str, pretty_print, level);
is_first = false; is_first = false;
} }
print_if(pretty_print && !is_first, str, '\n');
print_level(pretty_print && !is_first, level - 1, str);
str << '}'; str << '}';
} }
template<typename StreamType> template<typename StreamType>
void serialize_json_table(StreamType & str) const void serialize_json_table(StreamType & str, bool pretty_print, int level) const
{ {
str << '['; str << '[';
bool is_first = true; bool is_first = true;
for(Space * space : value.value_table) for(Space * space : value.value_table)
{ {
if( !is_first ) if( is_first )
{
print_if(pretty_print, str, '\n');
print_level(pretty_print, level, str);
}
else
{ {
str << ','; str << ',';
print_if(pretty_print, str, '\n');
print_level(pretty_print, level, str);
} }
space->serialize_to_json_stream(str); space->serialize_to_json_stream(str, pretty_print, level);
is_first = false; is_first = false;
} }
print_if(pretty_print && !is_first, str, '\n');
print_level(pretty_print && !is_first, level - 1, str);
str << ']'; str << ']';
} }
protected:
template<typename StreamType> template<typename StreamType>
void serialize_to_space_stream(StreamType & str, bool pretty_print, int level, bool is_main_object) const void serialize_to_space_stream(StreamType & str, bool pretty_print, int level, bool is_main_object) const
@ -1244,6 +1286,10 @@ protected:
serialize_space_double(str); serialize_space_double(str);
break; break;
case type_long_double:
serialize_space_long_double(str);
break;
case type_string: case type_string:
serialize_space_string(str); serialize_space_string(str);
break; break;
@ -1253,11 +1299,11 @@ protected:
break; break;
case type_object: case type_object:
serialize_space_object(str, pretty_print, level, is_main_object); serialize_space_object(str, pretty_print, level + 1, is_main_object);
break; break;
case type_table: case type_table:
serialize_space_table(str, pretty_print, level); serialize_space_table(str, pretty_print, level + 1);
break; break;
} }
} }
@ -1303,17 +1349,7 @@ protected:
str << c; str << c;
} }
template<typename StreamType>
void print_if(bool condition, StreamType & str, wchar_t c1, wchar_t c2) const
{
if( condition )
str << c1;
else
str << c2;
}
void copy_value_from(const Space & space);
void copy_from(const Space & space); void copy_from(const Space & space);
void copy_value_object(const Value & value_from); void copy_value_object(const Value & value_from);
@ -1328,6 +1364,7 @@ protected:
void initialize_value_long_if_needed(); void initialize_value_long_if_needed();
void initialize_value_float_if_needed(); void initialize_value_float_if_needed();
void initialize_value_double_if_needed(); void initialize_value_double_if_needed();
void initialize_value_long_double_if_needed();
void initialize_value_string_if_needed(); void initialize_value_string_if_needed();
void initialize_value_string_if_needed(std::string && str); void initialize_value_string_if_needed(std::string && str);
void initialize_value_wstring_if_needed(); void initialize_value_wstring_if_needed();
@ -1336,16 +1373,12 @@ protected:
void initialize_value_object_if_needed(ObjectType && obj); void initialize_value_object_if_needed(ObjectType && obj);
void initialize_value_table_if_needed(); void initialize_value_table_if_needed();
void initialize_value_table_if_needed(TableType && tab); void initialize_value_table_if_needed(TableType && tab);
void initialize_child_spaces_if_needed();
void remove_value(); void remove_value();
void remove_value_string(); void remove_value_string();
void remove_value_wstring(); void remove_value_wstring();
void remove_value_object(); void remove_value_object(bool only_clear = false);
void remove_value_table(); void remove_value_table(bool only_clear = false);
const Space * find_child_space_const(const wchar_t * name) const;
const Space * find_child_space_const(size_t table_index) const;
}; };

View File

@ -499,7 +499,7 @@ void SpaceParser::parse_key_value_pairs(Space * space)
if( parsing_space ) if( parsing_space )
{ {
// in space format a space_end character is allowed to be after the last table item // in space format a space_end character is allowed to be after the option_delimiter
skip_white(); skip_white();
if( lastc == space_end ) if( lastc == space_end )
@ -530,12 +530,6 @@ void SpaceParser::parse_key_value_pairs(Space * space)
parse(&new_space, true, false); parse(&new_space, true, false);
} }
else else
if( parsing_space && lastc == space_start )
{
Space & new_space = space->add_child_space(token.c_str());
parse_space(&new_space);
}
else
{ {
status = syntax_error; status = syntax_error;
} }

149
src/textstream/stream.h Normal file
View File

@ -0,0 +1,149 @@
/*
* This file is a part of PikoTools
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef headerfile_picotools_textstream_stream
#define headerfile_picotools_textstream_stream
#include <string>
#ifdef PT_HAS_MORM_LIBRARY
namespace morm
{
class Model;
}
#endif
namespace pt
{
class Space;
class Date;
class Stream
{
public:
virtual ~Stream() {};
virtual bool is_char_stream() const = 0;
virtual bool is_wchar_stream() const = 0;
virtual void clear() = 0;
virtual bool empty() const = 0;
virtual size_t size() const = 0;
virtual void reserve(size_t len) = 0;
virtual size_t capacity() const = 0;
virtual void to_str(std::string & str, bool clear_string = true) const = 0;
virtual void to_str(std::wstring & str, bool clear_string = true) const = 0;
virtual std::string to_str() const = 0;
virtual std::wstring to_wstr() const = 0;
virtual char get_char(size_t index) const = 0;
virtual wchar_t get_wchar(size_t index) const = 0;
virtual Stream & operator<<(const char * str) = 0;
virtual Stream & operator<<(const std::string & str) = 0;
virtual Stream & operator<<(const wchar_t * str) = 0;
virtual Stream & operator<<(const std::wstring & str) = 0;
/*
* IMPROVEME
* https://en.cppreference.com/w/cpp/string
* add support for:
* char8_t
* char16_t
* char32_t
* const char8_t *
* const char16_t *
* const char32_t *
* std::u8string
* std::u16string
* std::u32string
* std::string_view
* std::wstring_view
* std::u8string_view
* std::u16string_view
* std::u32string_view
*
*/
virtual Stream & operator<<(char) = 0;
virtual Stream & operator<<(unsigned char) = 0;
virtual Stream & operator<<(wchar_t) = 0;
virtual Stream & operator<<(bool) = 0;
virtual Stream & operator<<(short) = 0;
virtual Stream & operator<<(int) = 0;
virtual Stream & operator<<(long) = 0;
virtual Stream & operator<<(long long) = 0;
virtual Stream & operator<<(unsigned short) = 0;
virtual Stream & operator<<(unsigned int) = 0;
virtual Stream & operator<<(unsigned long) = 0;
virtual Stream & operator<<(unsigned long long) = 0;
virtual Stream & operator<<(float) = 0;
virtual Stream & operator<<(double) = 0;
virtual Stream & operator<<(long double) = 0;
virtual Stream & operator<<(const void *) = 0; // printing a pointer
virtual Stream & operator<<(const Stream & stream) = 0;
virtual Stream & operator<<(const Space & space) = 0;
virtual Stream & operator<<(const Date & date) = 0;
#ifdef PT_HAS_MORM_LIBRARY
/*
* this Stream base class can be used by other consumers so creating this operator
* as a pure virtual would be inconvinient for them if they do not use morm library
*/
virtual Stream & operator<<(morm::Model & model) { operator<<("serializing morm::Model objects not available"); return *this; };
#endif
virtual Stream & write(const char * buf, size_t len) = 0;
virtual Stream & write(const wchar_t * buf, size_t len) = 0;
};
}
#endif

View File

@ -39,16 +39,18 @@
#define headerfile_picotools_textstream_textstream #define headerfile_picotools_textstream_textstream
#include <string> #include <string>
#include "stream.h"
#include "space/space.h" #include "space/space.h"
#include "date/date.h" #include "date/date.h"
#include "convert/inttostr.h" #include "convert/inttostr.h"
#include "membuffer/membuffer.h" #include "membuffer/membuffer.h"
#include "types.h" #include "types.h"
#include "utf8/utf8.h"
// for snprintf // for snprintf
#include <cstdio> #include <cstdio>
namespace pt namespace pt
{ {
@ -58,10 +60,9 @@ namespace pt
similar to std::ostringstream similar to std::ostringstream
StringType can be either std::string or std::wstring StringType can be either std::string or std::wstring
this class doesn't use UTF-8 in any kind
*/ */
template<typename CharT, size_t stack_size, size_t heap_block_size> template<typename CharT, size_t stack_size, size_t heap_block_size>
class TextStreamBase class TextStreamBase : public Stream
{ {
public: public:
@ -74,6 +75,9 @@ public:
typedef typename buffer_type::const_iterator const_iterator; typedef typename buffer_type::const_iterator const_iterator;
bool is_char_stream() const;
bool is_wchar_stream() const;
void clear(); void clear();
bool empty() const; bool empty() const;
size_t size() const; size_t size() const;
@ -86,47 +90,59 @@ public:
const_iterator begin() const; const_iterator begin() const;
const_iterator end() const; const_iterator end() const;
void to_string(std::string & str, bool clear_string = true) const; // IMPROVE ME
void to_string(std::wstring & str, bool clear_string = true) const; // add cbegin(), cend(), rbegin(), rend(), crbegin(), crend()
void to_str(std::string & str, bool clear_string = true) const;
void to_str(std::wstring & str, bool clear_string = true) const;
std::string to_str() const;
std::wstring to_wstr() const;
char get_char(size_t index) const;
wchar_t get_wchar(size_t index) const;
char_type & operator[](size_t index); char_type & operator[](size_t index);
char_type operator[](size_t index) const; char_type operator[](size_t index) const;
TextStreamBase & operator<<(const char * str); TextStreamBase & operator<<(const char * str);
TextStreamBase & operator<<(const std::string & str); TextStreamBase & operator<<(const std::string & str);
TextStreamBase & operator<<(const wchar_t * str); TextStreamBase & operator<<(const wchar_t * str);
TextStreamBase & operator<<(const std::wstring * str);
TextStreamBase & operator<<(const std::wstring & str); TextStreamBase & operator<<(const std::wstring & str);
TextStreamBase & operator<<(char); TextStreamBase & operator<<(char);
TextStreamBase & operator<<(unsigned char);
TextStreamBase & operator<<(wchar_t); TextStreamBase & operator<<(wchar_t);
TextStreamBase & operator<<(bool);
TextStreamBase & operator<<(short);
TextStreamBase & operator<<(int); TextStreamBase & operator<<(int);
TextStreamBase & operator<<(long); TextStreamBase & operator<<(long);
TextStreamBase & operator<<(long long); TextStreamBase & operator<<(long long);
TextStreamBase & operator<<(unsigned short);
TextStreamBase & operator<<(unsigned int); TextStreamBase & operator<<(unsigned int);
TextStreamBase & operator<<(unsigned long); TextStreamBase & operator<<(unsigned long);
TextStreamBase & operator<<(unsigned long long); TextStreamBase & operator<<(unsigned long long);
TextStreamBase & operator<<(float);
TextStreamBase & operator<<(double); TextStreamBase & operator<<(double);
TextStreamBase & operator<<(long double);
TextStreamBase & operator<<(const void *); // printing a pointer TextStreamBase & operator<<(const void *); // printing a pointer
TextStreamBase & operator<<(const Stream & stream);
TextStreamBase & operator<<(const Space & space); TextStreamBase & operator<<(const Space & space);
TextStreamBase & operator<<(const Date & date); TextStreamBase & operator<<(const Date & date);
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
TextStreamBase & operator<<(const TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg);
// min width for integer output // min width for integer output
// if the output value has less digits then first zeroes are added // if the output value has less digits then first zeroes are added
// (0 turn off) // (0 turn off)
TextStreamBase & int_min_width(size_t min_width); TextStreamBase & int_min_width(size_t min_width);
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size> TextStreamBase & write(const char * buf, size_t len);
TextStreamBase & operator<<(const TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg); TextStreamBase & write(const wchar_t * buf, size_t len);
template<typename in_buffer_type>
TextStreamBase & write(const in_buffer_type * buf, size_t len);
// write double value in a specified format
// format is the same as in the snprintf function, e.g. write("%f", 10.0)
TextStreamBase & write(const char * format, double val);
TextStreamBase & write(const wchar_t * format, double val);
TextStreamBase & fill_up_if_needed(wchar_t fill_up_char, size_t existing_length); TextStreamBase & fill_up_if_needed(wchar_t fill_up_char, size_t existing_length);
@ -136,6 +152,13 @@ public:
int radix; int radix;
size_t min_width_for_integers; size_t min_width_for_integers;
buffer_type buffer; buffer_type buffer;
protected:
void put_stream(const Stream & stream);
}; };
@ -150,6 +173,32 @@ TextStreamBase<char_type, stack_size, heap_block_size>::TextStreamBase()
} }
template<typename char_type, size_t stack_size, size_t heap_block_size>
bool TextStreamBase<char_type, stack_size, heap_block_size>::is_char_stream() const
{
if constexpr (sizeof(char_type) == sizeof(char) )
{
return true;
}
return false;
}
template<typename char_type, size_t stack_size, size_t heap_block_size>
bool TextStreamBase<char_type, stack_size, heap_block_size>::is_wchar_stream() const
{
if constexpr (sizeof(char_type) == sizeof(wchar_t) )
{
return true;
}
return false;
}
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
void TextStreamBase<char_type, stack_size, heap_block_size>::clear() void TextStreamBase<char_type, stack_size, heap_block_size>::clear()
{ {
@ -215,7 +264,7 @@ TextStreamBase<char_type, stack_size, heap_block_size>::end() const
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
void TextStreamBase<char_type, stack_size, heap_block_size>::to_string(std::string & str, bool clear_string) const void TextStreamBase<char_type, stack_size, heap_block_size>::to_str(std::string & str, bool clear_string) const
{ {
if( clear_string ) if( clear_string )
str.clear(); str.clear();
@ -223,16 +272,24 @@ void TextStreamBase<char_type, stack_size, heap_block_size>::to_string(std::stri
if( str.capacity() < str.size() + size() ) if( str.capacity() < str.size() + size() )
str.reserve(str.size() + size()); str.reserve(str.size() + size());
const_iterator i = begin();
for( ; i != end() ; ++i) if constexpr (sizeof(char_type) == sizeof(char) )
str += static_cast<char>(*i); {
const_iterator i = begin();
for( ; i != end() ; ++i)
str += *i;
}
else
{
wide_stream_to_utf8(*this, str);
}
} }
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
void TextStreamBase<char_type, stack_size, heap_block_size>::to_string(std::wstring & str, bool clear_string) const void TextStreamBase<char_type, stack_size, heap_block_size>::to_str(std::wstring & str, bool clear_string) const
{ {
if( clear_string ) if( clear_string )
str.clear(); str.clear();
@ -240,14 +297,64 @@ void TextStreamBase<char_type, stack_size, heap_block_size>::to_string(std::wstr
if( str.capacity() < str.size() + size() ) if( str.capacity() < str.size() + size() )
str.reserve(str.size() + size()); str.reserve(str.size() + size());
const_iterator i = begin(); if constexpr (sizeof(char_type) == sizeof(wchar_t) )
{
const_iterator i = begin();
for( ; i != end() ; ++i) for( ; i != end() ; ++i)
str += static_cast<wchar_t>(*i); str += *i;
}
else
{
// IMPROVE ME don't use a temporary object
std::string utf8;
to_str(utf8);
utf8_to_wide(utf8, str, false);
}
} }
template<typename char_type, size_t stack_size, size_t heap_block_size>
std::string TextStreamBase<char_type, stack_size, heap_block_size>::to_str() const
{
std::string str;
to_str(str, false);
return str;
}
template<typename char_type, size_t stack_size, size_t heap_block_size>
std::wstring TextStreamBase<char_type, stack_size, heap_block_size>::to_wstr() const
{
std::wstring str;
to_str(str, false);
return str;
}
template<typename char_type, size_t stack_size, size_t heap_block_size>
char TextStreamBase<char_type, stack_size, heap_block_size>::get_char(size_t index) const
{
return static_cast<char>(buffer[index]);
}
template<typename char_type, size_t stack_size, size_t heap_block_size>
wchar_t TextStreamBase<char_type, stack_size, heap_block_size>::get_wchar(size_t index) const
{
return static_cast<wchar_t>(buffer[index]);
}
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
char_type & TextStreamBase<char_type, stack_size, heap_block_size>::operator[](size_t index) char_type & TextStreamBase<char_type, stack_size, heap_block_size>::operator[](size_t index)
@ -267,8 +374,15 @@ template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const char * str) TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const char * str)
{ {
for( ; *str ; ++str) if constexpr ( sizeof(char_type) == sizeof(char) )
buffer.append(static_cast<char_type>(*str)); {
for( ; *str ; ++str)
buffer.append(*str);
}
else
{
utf8_to_wide(str, *this, false);
}
return *this; return *this;
} }
@ -278,10 +392,7 @@ template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const std::string & str) TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const std::string & str)
{ {
if( sizeof(char_type) == sizeof(char) ) operator<<(str.c_str());
buffer.append(str.c_str(), str.size());
else
operator<<(str.c_str());
return *this; return *this;
} }
@ -292,8 +403,15 @@ template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const wchar_t * str) TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const wchar_t * str)
{ {
for( ; *str ; ++str) if constexpr (sizeof(char_type) == sizeof(wchar_t) )
buffer.append(static_cast<char_type>(*str)); {
for( ; *str ; ++str)
buffer.append(*str);
}
else
{
wide_to_utf8(str, *this);
}
return *this; return *this;
} }
@ -304,10 +422,7 @@ template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const std::wstring & str) TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const std::wstring & str)
{ {
if( sizeof(char_type) == sizeof(wchar_t) ) operator<<(str.c_str());
buffer.append(str.c_str(), str.size());
else
operator<<(str.c_str());
return *this; return *this;
} }
@ -318,6 +433,22 @@ template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(char v) TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(char v)
{ {
// IMPROVEME
// if char_type == 1 then if v <= 127 then put that char but if (unsigned)v > 127 put replacement character
// if char_type > 1 then simply put that character
buffer.append(static_cast<char_type>(v));
return *this;
}
template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(unsigned char v)
{
// IMPROVEME
// if char_type == 1 then if v <= 127 then put that char but if v > 127 put replacement character
// if char_type > 1 then simply put that character
buffer.append(static_cast<char_type>(v)); buffer.append(static_cast<char_type>(v));
return *this; return *this;
@ -328,12 +459,32 @@ template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(wchar_t v) TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(wchar_t v)
{ {
// IMPROVEME add utf8/wide conversion, if v is from surrogate pair we can skip it
buffer.append(static_cast<char_type>(v)); buffer.append(static_cast<char_type>(v));
return *this; return *this;
} }
template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(bool v)
{
char c = v ? '1' : '0';
buffer.append(static_cast<char_type>(c));
return *this;
}
template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(short v)
{
return operator<<(static_cast<long long>(v));
}
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(int v) TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(int v)
@ -368,6 +519,14 @@ return *this;
} }
template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(unsigned short v)
{
return operator<<(static_cast<unsigned long long>(v));
}
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(unsigned int v) TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(unsigned int v)
@ -402,13 +561,31 @@ return *this;
} }
template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(float v)
{
return operator<<(static_cast<double>(v));
}
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(double v) TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(double v)
{ {
char buf[100]; char buf[100];
snprintf(buf, sizeof(buf)/sizeof(char), "%f", v); snprintf(buf, sizeof(buf)/sizeof(char), "%g", v);
return operator<<(buf);
}
template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(long double v)
{
char buf[100];
snprintf(buf, sizeof(buf)/sizeof(char), "%Lg", v);
return operator<<(buf); return operator<<(buf);
} }
@ -433,12 +610,20 @@ return *this;
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
template<typename in_buffer_type>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::write(const in_buffer_type * buf, size_t len) TextStreamBase<char_type, stack_size, heap_block_size>::write(const char * str, size_t len)
{ {
buffer.append(buf, len); if constexpr ( sizeof(char_type) == sizeof(char) )
{
for(size_t i=0 ; i < len ; ++i)
buffer.append(str[i]);
}
else
{
utf8_to_wide(str, *this, false);
}
return *this; return *this;
} }
@ -446,23 +631,73 @@ return *this;
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::write(const char * format, double val) TextStreamBase<char_type, stack_size, heap_block_size>::write(const wchar_t * str, size_t len)
{ {
char buf[100]; if constexpr (sizeof(char_type) == sizeof(wchar_t) )
{
for(size_t i=0 ; i < len ; ++i)
buffer.append(str[i]);
}
else
{
wide_to_utf8(str, *this);
}
snprintf(buf, sizeof(buf)/sizeof(char), format, val); return *this;
return operator<<(buf);
} }
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::write(const wchar_t * format, double val) TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const Stream & stream)
{ {
wchar_t buf[100]; put_stream(stream);
return *this;
}
swprintf(buf, sizeof(buf)/sizeof(wchar_t), format, val);
return operator<<(buf);
template<typename char_type, size_t stack_size, size_t heap_block_size>
void TextStreamBase<char_type, stack_size, heap_block_size>::put_stream(const Stream & stream)
{
if( sizeof(char_type) == sizeof(char) && stream.is_char_stream() )
{
// from utf8 to utf8
for(size_t i=0 ; i < stream.size() ; ++i)
{
char c = stream.get_char(i);
operator<<(c);
}
}
else
if( sizeof(char_type) == sizeof(wchar_t) && stream.is_char_stream() )
{
// from utf8 to wide
utf8_to_wide(stream, *this, false);
}
else
if( sizeof(char_type) == sizeof(char) && stream.is_wchar_stream() )
{
// from wide to utf8
wide_stream_to_utf8(stream, *this, false);
}
else
if( sizeof(char_type) == sizeof(wchar_t) && stream.is_wchar_stream() )
{
// from wide to wide
for(size_t i=0 ; i < stream.size() ; ++i)
{
wchar_t c = stream.get_wchar(i);
operator<<(c);
}
}
else
{
operator<<("such conversion is not implemented");
}
} }
@ -488,20 +723,28 @@ return *this;
} }
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size> template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<( TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(
const TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg) const TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg)
{ {
buffer.append(arg.buffer); /*
* in the future we can have a faster implementation
* which uses iterators instead of get_char() and get_wchar() methods
*
*/
put_stream(arg);
return *this; return *this;
} }
template<typename char_type, size_t stack_size, size_t heap_block_size> template<typename char_type, size_t stack_size, size_t heap_block_size>
TextStreamBase<char_type, stack_size, heap_block_size> & TextStreamBase<char_type, stack_size, heap_block_size> &
TextStreamBase<char_type, stack_size, heap_block_size>::int_min_width(size_t min_width) TextStreamBase<char_type, stack_size, heap_block_size>::int_min_width(size_t min_width)

View File

@ -35,6 +35,7 @@
* THE POSSIBILITY OF SUCH DAMAGE. * THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <fstream>
#include "utf8.h" #include "utf8.h"
#include "utf8_private.h" #include "utf8_private.h"
@ -290,6 +291,46 @@ return len;
} }
// new function, need to be tested a little more especially when sizeof(wchar_t) is 2
size_t utf8_to_int(const Stream & utf8, size_t stream_index, int & res, bool & correct)
{
size_t i, len;
unsigned char uz;
res = 0;
correct = false;
len = 0;
if( stream_index < utf8.size() )
{
uz = utf8.get_char(stream_index);
if( !private_namespace::utf8_to_int_first_octet(uz, len, res) )
return 1;
if( stream_index + len < utf8.size() + 1 )
{
for(i=1 ; i<len ; ++i)
{
uz = utf8.get_char(stream_index + i);
if( !private_namespace::utf8_to_int_add_next_octet(uz, res) )
return i;
}
if( utf8_check_range(res, len) )
correct = true;
}
else
{
len = utf8.size() - stream_index;
}
}
return len;
}
/* /*

View File

@ -39,7 +39,7 @@
#define headerfile_picotools_utf8_utf8 #define headerfile_picotools_utf8_utf8
#include <string> #include <string>
#include "textstream/textstream.h" #include "textstream/stream.h"
namespace pt namespace pt
@ -60,6 +60,8 @@ namespace pt
/*! /*!
returns true if 'c' is a correct unicode character returns true if 'c' is a correct unicode character
RENAMEME to is_correct_unicode_char
*/ */
bool utf8_check_range(int c); bool utf8_check_range(int c);
@ -121,6 +123,15 @@ size_t utf8_to_int(const char * utf8, size_t utf8_len, int & res, bool & correct
size_t utf8_to_int(const char * utf8, int & res, bool & correct); size_t utf8_to_int(const char * utf8, int & res, bool & correct);
size_t utf8_to_int(const std::string & utf8, int & res, bool & correct); size_t utf8_to_int(const std::string & utf8, int & res, bool & correct);
size_t utf8_to_int(std::istream & utf8, int & res, bool & correct); size_t utf8_to_int(std::istream & utf8, int & res, bool & correct);
size_t utf8_to_int(const Stream & utf8, size_t stream_index, int & res, bool & correct);
/*!
converting one character from int to wide stream
*/
template<typename StreamType>
void int_to_wide(int c, StreamType & res);
/*! /*!
@ -143,6 +154,8 @@ bool utf8_to_wide(const std::string & utf8, StreamType & res, bool clear = true,
template<typename StreamType> template<typename StreamType>
bool utf8_to_wide(std::istream & utf8, StreamType & res, bool clear = true, int mode = 1); // need to be tested bool utf8_to_wide(std::istream & utf8, StreamType & res, bool clear = true, int mode = 1); // need to be tested
template<typename StreamType>
bool utf8_to_wide(const Stream & stream, StreamType & res, bool clear = true, int mode = 1);
/* /*
@ -196,8 +209,11 @@ bool wide_to_utf8(const std::wstring & wide_string, char * utf8, s
template<typename StreamType> template<typename StreamType>
void wide_stream_to_utf8(StreamType & buffer, std::string & utf8, bool clear = true, int mode = 1); // not tested void wide_stream_to_utf8(StreamType & buffer, std::string & utf8, bool clear = true, int mode = 1); // not tested
template<typename StreamType>
bool wide_stream_to_utf8(const Stream & stream, StreamType & utf8, bool clear = true, int mode = 1);
template<typename StreamTypeIn, typename StreamTypeOut> template<typename StreamTypeIn, typename StreamTypeOut>
void wide_stream_to_utf8(StreamTypeIn & buffer, StreamTypeOut & utf8, int mode = 1); // not tested void wide_stream_to_utf8(StreamTypeIn & buffer, StreamTypeOut & utf8, int mode = 1); // not tested, IMPROVE ME add clear parameter, mode parameter is not used

View File

@ -38,7 +38,7 @@
#ifndef headerfile_picotools_utf8_utf8_private #ifndef headerfile_picotools_utf8_utf8_private
#define headerfile_picotools_utf8_utf8_private #define headerfile_picotools_utf8_utf8_private
#include "textstream/textstream.h" #include <string>
namespace pt namespace pt
@ -166,35 +166,17 @@ return !was_error;
template<typename StreamType>
void int_to_wide(int c, StreamType & res)
{
if( sizeof(wchar_t)==2 && c>0xffff )
{
// UTF16 surrogate pairs
c -= 0x10000;
res << static_cast<wchar_t>(((c >> 10) & 0x3FF) + 0xD800);
res << static_cast<wchar_t>((c & 0x3FF) + 0xDC00);
}
else
{
res << static_cast<wchar_t>(c);
}
}
// not tested
// FIX ME it is not using surrogate pairs from input stream // FIX ME it is not using surrogate pairs from input stream
// and mode parameter // and is not using mode parameter
template<typename char_type, size_t stack_size, size_t heap_block_size, typename function_type> template<typename StreamType, typename function_type>
void wide_to_utf8_generic(TextStreamBase<char_type, stack_size, heap_block_size> & buffer, int mode, function_type write_function) void wide_to_utf8_generic(StreamType & buffer, int mode, function_type write_function)
{ {
char utf8_buffer[256]; char utf8_buffer[256];
std::size_t buffer_len = sizeof(utf8_buffer) / sizeof(char); std::size_t buffer_len = sizeof(utf8_buffer) / sizeof(char);
std::size_t utf8_sequence_max_length = 10; std::size_t utf8_sequence_max_length = 10;
std::size_t index = 0; std::size_t index = 0;
typename TextStreamBase<char_type, stack_size, heap_block_size>::const_iterator i = buffer.begin(); typename StreamType::const_iterator i = buffer.begin();
while( i != buffer.end() ) while( i != buffer.end() )
{ {

View File

@ -47,6 +47,24 @@ namespace pt
{ {
template<typename StreamType>
void int_to_wide(int c, StreamType & res)
{
if( sizeof(wchar_t)==2 && c>0xffff )
{
// UTF16 surrogate pairs
c -= 0x10000;
res << static_cast<wchar_t>(((c >> 10) & 0x3FF) + 0xD800);
res << static_cast<wchar_t>((c & 0x3FF) + 0xDC00);
}
else
{
res << static_cast<wchar_t>(c);
}
}
/*! /*!
converting UTF-8 string to a TextStreamBase<wchar_t,...> stream converting UTF-8 string to a TextStreamBase<wchar_t,...> stream
(need to be tested) (need to be tested)
@ -59,7 +77,7 @@ bool utf8_to_wide(const char * utf8, size_t utf8_len, StreamType & res, bool cle
res.clear(); res.clear();
bool status = private_namespace::utf8_to_wide_generic(utf8, utf8_len, mode, [&res](int c) { bool status = private_namespace::utf8_to_wide_generic(utf8, utf8_len, mode, [&res](int c) {
private_namespace::int_to_wide(c, res); int_to_wide(c, res);
}); });
return status; return status;
@ -110,7 +128,7 @@ bool correct, was_error = false;
} }
else else
{ {
private_namespace::int_to_wide(z, res); int_to_wide(z, res);
} }
} }
@ -118,6 +136,59 @@ return !was_error;
} }
/*
this function converts a UTF-8 stream into wide stream
input:
stream - a UTF-8 stream for converting
mode - what to do with errors when converting
0: skip an invalid character
1: put U+FFFD "replacement character" istead of the invalid character (default)
output:
res - a wide stream for the output sequence
this function returns false if there were some errors when converting
*/
template<typename StreamType>
bool utf8_to_wide(const Stream & stream, StreamType & res, bool clear, int mode)
{
size_t len;
bool correct;
int z;
size_t index = 0;
bool was_error = false;
if( clear )
res.clear();
// CHECKME test me when sizeof(wchar_t) is 2
do
{
len = utf8_to_int(stream, index, z, correct);
if( len > 0 )
{
if( !correct )
{
if( mode == 1 )
res << 0xFFFD; // U+FFFD "replacement character"
was_error = true;
}
else
{
int_to_wide(z, res);
}
index += len;
}
}
while( len > 0 );
return !was_error;
}
@ -250,6 +321,59 @@ void wide_stream_to_utf8(StreamType & buffer, std::string & utf8, bool clear, in
} }
template<typename StreamType>
bool wide_stream_to_utf8(const Stream & stream, StreamType & utf8, bool clear, int mode)
{
bool was_error = false;
if( clear )
utf8.clear();
for(size_t i=0 ; i < stream.size() ; ++i)
{
int c = static_cast<int>(stream.get_wchar(i));
bool is_correct = false;
if( utf8_check_range(c) )
{
// CHECKME test me when sizeof(wchar_t) == 2
if( is_first_surrogate_char(c) )
{
if( i + 1 < stream.size() )
{
wchar_t c1 = static_cast<wchar_t>(c);
wchar_t c2 = stream.get_wchar(++i);
if( surrogate_pair_to_int(c1, c2, c) )
{
is_correct = true;
}
}
}
else
{
is_correct = true;
}
}
if( is_correct )
{
int_to_utf8(c, utf8);
}
else
{
was_error = true;
if( mode == 1 )
int_to_utf8(0xFFFD, utf8); // U+FFFD "replacement character"
}
}
return !was_error;
}
// not tested // not tested
template<typename StreamTypeIn, typename StreamTypeOut> template<typename StreamTypeIn, typename StreamTypeOut>
void wide_stream_to_utf8(StreamTypeIn & buffer, StreamTypeOut & utf8, int mode) void wide_stream_to_utf8(StreamTypeIn & buffer, StreamTypeOut & utf8, int mode)

View File

@ -3,23 +3,30 @@
./main.o: convert.h mainoptionsparser.h csvparser.h ./main.o: convert.h mainoptionsparser.h csvparser.h
./convert.o: convert.h test.h ../src/convert/convert.h ./convert.o: convert.h test.h ../src/convert/convert.h
./convert.o: ../src/convert/inttostr.h ../src/convert/patternreplacer.h ./convert.o: ../src/convert/inttostr.h ../src/convert/patternreplacer.h
./convert.o: ../src/textstream/textstream.h ../src/space/space.h ./convert.o: ../src/textstream/textstream.h ../src/textstream/stream.h
./convert.o: ../src/textstream/types.h ../src/convert/inttostr.h ./convert.o: ../src/space/space.h ../src/textstream/types.h
./convert.o: ../src/date/date.h ../src/membuffer/membuffer.h ./convert.o: ../src/convert/inttostr.h ../src/utf8/utf8.h
./convert.o: ../src/textstream/types.h ../src/convert/strtoint.h ./convert.o: ../src/textstream/stream.h ../src/utf8/utf8_templates.h
./convert.o: ../src/convert/text.h ../src/convert/misc.h ./convert.o: ../src/utf8/utf8_private.h ../src/date/date.h
./convert.o: ../src/membuffer/membuffer.h ../src/textstream/types.h
./convert.o: ../src/convert/strtoint.h ../src/convert/text.h
./convert.o: ../src/convert/misc.h ../src/convert/double.h
./test.o: test.h ./test.o: test.h
./mainoptionsparser.o: mainoptionsparser.h test.h ./mainoptionsparser.o: mainoptionsparser.h test.h
./mainoptionsparser.o: ../src/mainoptions/mainoptionsparser.h ./mainoptionsparser.o: ../src/mainoptions/mainoptionsparser.h
./mainoptionsparser.o: ../src/space/space.h ../src/textstream/types.h ./mainoptionsparser.o: ../src/space/space.h ../src/textstream/types.h
./mainoptionsparser.o: ../src/convert/inttostr.h ../src/utf8/utf8.h ./mainoptionsparser.o: ../src/convert/inttostr.h ../src/utf8/utf8.h
./mainoptionsparser.o: ../src/textstream/textstream.h ../src/date/date.h ./mainoptionsparser.o: ../src/textstream/stream.h
./mainoptionsparser.o: ../src/membuffer/membuffer.h ../src/textstream/types.h
./mainoptionsparser.o: ../src/utf8/utf8_templates.h ./mainoptionsparser.o: ../src/utf8/utf8_templates.h
./mainoptionsparser.o: ../src/utf8/utf8_private.h ../src/convert/convert.h ./mainoptionsparser.o: ../src/utf8/utf8_private.h ../src/convert/convert.h
./mainoptionsparser.o: ../src/convert/inttostr.h ./mainoptionsparser.o: ../src/convert/inttostr.h
./mainoptionsparser.o: ../src/convert/patternreplacer.h ./mainoptionsparser.o: ../src/convert/patternreplacer.h
./mainoptionsparser.o: ../src/textstream/textstream.h
./mainoptionsparser.o: ../src/textstream/stream.h ../src/date/date.h
./mainoptionsparser.o: ../src/membuffer/membuffer.h ../src/textstream/types.h
./mainoptionsparser.o: ../src/convert/strtoint.h ../src/convert/text.h ./mainoptionsparser.o: ../src/convert/strtoint.h ../src/convert/text.h
./mainoptionsparser.o: ../src/convert/misc.h ./mainoptionsparser.o: ../src/convert/misc.h ../src/convert/double.h
./csvparser.o: csvparser.h ../src/csv/csvparser.h ../src/space/space.h ./csvparser.o: csvparser.h ../src/csv/csvparser.h ../src/space/space.h
./csvparser.o: ../src/textstream/types.h ../src/convert/inttostr.h test.h ./csvparser.o: ../src/textstream/types.h ../src/convert/inttostr.h
./csvparser.o: ../src/utf8/utf8.h ../src/textstream/stream.h
./csvparser.o: ../src/utf8/utf8_templates.h ../src/utf8/utf8_private.h test.h