Merge branch 'api2021'
This commit is contained in:
commit
6c41e0a803
|
@ -3,41 +3,42 @@
|
|||
./convert/inttostr.o: ./convert/inttostr.h
|
||||
./convert/misc.o: ./convert/misc.h ./convert/text.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
|
||||
./log/filelog.o: ./log/filelog.h textstream/textstream.h space/space.h
|
||||
./log/filelog.o: textstream/types.h convert/inttostr.h date/date.h
|
||||
./log/filelog.o: membuffer/membuffer.h textstream/types.h utf8/utf8.h
|
||||
./log/filelog.o: utf8/utf8_templates.h utf8/utf8_private.h
|
||||
./log/log.o: ./log/log.h textstream/textstream.h space/space.h
|
||||
./log/log.o: textstream/types.h convert/inttostr.h date/date.h
|
||||
./log/log.o: membuffer/membuffer.h textstream/types.h ./log/filelog.h
|
||||
./log/log.o: utf8/utf8.h utf8/utf8_templates.h utf8/utf8_private.h
|
||||
./log/filelog.o: ./log/filelog.h textstream/textstream.h textstream/stream.h
|
||||
./log/filelog.o: space/space.h textstream/types.h convert/inttostr.h
|
||||
./log/filelog.o: utf8/utf8.h textstream/stream.h utf8/utf8_templates.h
|
||||
./log/filelog.o: utf8/utf8_private.h date/date.h membuffer/membuffer.h
|
||||
./log/filelog.o: textstream/types.h
|
||||
./log/log.o: ./log/log.h textstream/textstream.h textstream/stream.h
|
||||
./log/log.o: space/space.h textstream/types.h convert/inttostr.h utf8/utf8.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: utf8/utf8.h textstream/textstream.h space/space.h
|
||||
./space/space.o: date/date.h membuffer/membuffer.h textstream/types.h
|
||||
./space/space.o: utf8/utf8_templates.h utf8/utf8_private.h convert/convert.h
|
||||
./space/space.o: ./convert/inttostr.h convert/patternreplacer.h
|
||||
./space/space.o: convert/strtoint.h ./convert/text.h ./convert/misc.h
|
||||
./space/space.o: utf8/utf8.h textstream/stream.h utf8/utf8_templates.h
|
||||
./space/space.o: utf8/utf8_private.h convert/convert.h ./convert/inttostr.h
|
||||
./space/space.o: convert/patternreplacer.h textstream/textstream.h
|
||||
./space/space.o: textstream/stream.h space/space.h date/date.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: textstream/types.h convert/inttostr.h utf8/utf8.h
|
||||
./space/spaceparser.o: textstream/textstream.h space/space.h date/date.h
|
||||
./space/spaceparser.o: membuffer/membuffer.h textstream/types.h
|
||||
./space/spaceparser.o: utf8/utf8_templates.h utf8/utf8_private.h
|
||||
./space/spaceparser.o: convert/strtoint.h ./convert/text.h ./convert/misc.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
|
||||
./space/spaceparser.o: textstream/stream.h utf8/utf8_templates.h
|
||||
./space/spaceparser.o: utf8/utf8_private.h convert/strtoint.h
|
||||
./space/spaceparser.o: ./convert/text.h ./convert/misc.h
|
||||
./utf8/utf8.o: ./utf8/utf8.h textstream/stream.h utf8/utf8_templates.h
|
||||
./utf8/utf8.o: utf8/utf8_private.h
|
||||
./utf8/utf8_private.o: utf8/utf8_private.h textstream/textstream.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
|
||||
./utf8/utf8_private.o: utf8/utf8_private.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: date/date.h membuffer/membuffer.h textstream/types.h
|
||||
./csv/csvparser.o: convert/inttostr.h utf8/utf8.h textstream/stream.h
|
||||
./csv/csvparser.o: utf8/utf8_templates.h utf8/utf8_private.h
|
||||
./mainoptions/mainoptionsparser.o: ./mainoptions/mainoptionsparser.h
|
||||
./mainoptions/mainoptionsparser.o: space/space.h textstream/types.h
|
||||
./mainoptions/mainoptionsparser.o: convert/inttostr.h utf8/utf8.h
|
||||
./mainoptions/mainoptionsparser.o: textstream/textstream.h date/date.h
|
||||
./mainoptions/mainoptionsparser.o: membuffer/membuffer.h textstream/types.h
|
||||
./mainoptions/mainoptionsparser.o: utf8/utf8_templates.h utf8/utf8_private.h
|
||||
./mainoptions/mainoptionsparser.o: textstream/stream.h utf8/utf8_templates.h
|
||||
./mainoptions/mainoptionsparser.o: utf8/utf8_private.h
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012-2018, Tomasz Sowa
|
||||
* Copyright (c) 2012-2021, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -43,5 +43,6 @@
|
|||
#include "patternreplacer.h"
|
||||
#include "strtoint.h"
|
||||
#include "text.h"
|
||||
#include "double.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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();;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2021, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -86,7 +86,7 @@ private:
|
|||
params.clear();
|
||||
AddParams(types...);
|
||||
ReplacePattern(pattern);
|
||||
buffer.to_string(output_string);
|
||||
buffer.to_str(output_string);
|
||||
|
||||
params.clear();
|
||||
buffer.clear();
|
||||
|
@ -104,7 +104,7 @@ private:
|
|||
{
|
||||
buffer.clear();
|
||||
buffer << type;
|
||||
buffer.to_string(temp_str);
|
||||
buffer.to_str(temp_str);
|
||||
params.push_back(temp_str);
|
||||
temp_str.clear();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012-2018, Tomasz Sowa
|
||||
* Copyright (c) 2012-2021, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -251,12 +251,21 @@ public:
|
|||
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
|
||||
ISO 8601 format
|
||||
*/
|
||||
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)
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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>
|
||||
void Date::SerializeYearMonthDay(Stream & out) const
|
||||
void Date::SerializeYearMonthDay(Stream & out, bool roman_month) const
|
||||
{
|
||||
SerializeInt(out, year, 4);
|
||||
out << '-';
|
||||
|
||||
if( roman_month )
|
||||
SerializeMonthAsRoman(out, month);
|
||||
else
|
||||
SerializeInt(out, month);
|
||||
|
||||
out << '-';
|
||||
SerializeInt(out, day);
|
||||
}
|
||||
|
@ -571,9 +599,13 @@ void Date::SerializeHourMinSec(Stream & out) const
|
|||
|
||||
|
||||
template<class Stream>
|
||||
void Date::SerializeMonthDay(Stream & out) const
|
||||
void Date::SerializeMonthDay(Stream & out, bool roman_month) const
|
||||
{
|
||||
if( roman_month )
|
||||
SerializeMonthAsRoman(out, month);
|
||||
else
|
||||
SerializeInt(out, month);
|
||||
|
||||
out << '-';
|
||||
SerializeInt(out, day);
|
||||
}
|
||||
|
@ -589,17 +621,22 @@ void Date::SerializeHourMin(Stream & out) const
|
|||
|
||||
|
||||
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 << ' ';
|
||||
|
||||
if( with_seconds )
|
||||
SerializeHourMinSec(out);
|
||||
else
|
||||
SerializeHourMin(out);
|
||||
}
|
||||
|
||||
|
||||
template<class Stream>
|
||||
void Date::SerializeISO(Stream & out) const
|
||||
{
|
||||
SerializeYearMonthDay(out);
|
||||
SerializeYearMonthDay(out, false);
|
||||
out << 'T';
|
||||
SerializeHourMinSec(out);
|
||||
out << 'Z';
|
||||
|
|
427
src/log/log.cpp
427
src/log/log.cpp
|
@ -41,7 +41,7 @@
|
|||
#include "date/date.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
#ifdef PT_HAS_MORM
|
||||
#ifdef PT_HAS_MORM_LIBRARY
|
||||
#include "morm.h"
|
||||
#endif
|
||||
|
||||
|
@ -54,89 +54,156 @@ Log::Log()
|
|||
{
|
||||
buffer = nullptr;
|
||||
file_log = nullptr;
|
||||
|
||||
current_level = 4;
|
||||
max_buffer_length = 2 * 1024 * 1024; // 2MB
|
||||
max_buffer_length = 2 * 1024 * 1024;
|
||||
}
|
||||
|
||||
|
||||
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::SetFileLog(FileLog * file_log)
|
||||
{
|
||||
this->file_log = file_log;
|
||||
}
|
||||
|
||||
|
||||
FileLog * Log::GetFileLog()
|
||||
{
|
||||
return file_log;
|
||||
}
|
||||
|
||||
|
||||
Log & Log::IntMinWidth(size_t min_width)
|
||||
void Log::clear()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
@ -146,34 +213,18 @@ Log & Log::operator<<(const char * 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
if( buffer && file_log && s && current_level <= file_log->get_log_level() )
|
||||
if( can_put_log() )
|
||||
{
|
||||
(*buffer) << s;
|
||||
}
|
||||
|
@ -182,10 +233,9 @@ Log & Log::operator<<(const wchar_t * 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;
|
||||
}
|
||||
|
@ -194,49 +244,55 @@ Log & Log::operator<<(const std::wstring & s)
|
|||
}
|
||||
|
||||
|
||||
|
||||
Log & Log::operator<<(const std::wstring * s)
|
||||
Log & Log::operator<<(char val)
|
||||
{
|
||||
if( buffer && file_log && s && current_level <= file_log->get_log_level() )
|
||||
if( can_put_log() )
|
||||
{
|
||||
(*buffer) << *s;
|
||||
(*buffer) << val;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Log & Log::operator<<(unsigned char val)
|
||||
{
|
||||
if( can_put_log() )
|
||||
{
|
||||
(*buffer) << val;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Log & Log::operator<<(int s)
|
||||
Log & Log::operator<<(wchar_t val)
|
||||
{
|
||||
if( buffer && file_log && current_level <= file_log->get_log_level() )
|
||||
{
|
||||
(*buffer) << s;
|
||||
(*buffer) << val;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Log & Log::operator<<(long s)
|
||||
Log & Log::operator<<(bool val)
|
||||
{
|
||||
if( buffer && file_log && current_level <= file_log->get_log_level() )
|
||||
if( can_put_log() )
|
||||
{
|
||||
(*buffer) << s;
|
||||
(*buffer) << val;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -244,39 +300,95 @@ Log & Log::operator<<(long long s)
|
|||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -289,10 +401,20 @@ Log & Log::operator<<(double s)
|
|||
}
|
||||
|
||||
|
||||
|
||||
Log & Log::operator<<(const Space & s)
|
||||
Log & Log::operator<<(long double val)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
if( buffer && file_log && current_level <= file_log->get_log_level() )
|
||||
if( can_put_log() )
|
||||
{
|
||||
(*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)
|
||||
{
|
||||
operator<<(model.to_string());
|
||||
|
@ -322,13 +465,35 @@ Log & Log::operator<<(morm::Model & model)
|
|||
#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)
|
||||
{
|
||||
switch(m)
|
||||
{
|
||||
case lend:
|
||||
case logend:
|
||||
if( buffer && file_log && current_level <= file_log->get_log_level() )
|
||||
if( can_put_log() )
|
||||
{
|
||||
(*buffer) << '\n';
|
||||
|
||||
|
@ -337,27 +502,22 @@ Log & Log::operator<<(Manipulators m)
|
|||
}
|
||||
break;
|
||||
|
||||
case lsave:
|
||||
case logsave:
|
||||
save_log_and_clear();
|
||||
break;
|
||||
|
||||
case l1:
|
||||
case log1:
|
||||
current_level = 1;
|
||||
break;
|
||||
|
||||
case l2:
|
||||
case log2:
|
||||
current_level = 2;
|
||||
break;
|
||||
|
||||
case l3:
|
||||
case log3:
|
||||
current_level = 3;
|
||||
break;
|
||||
|
||||
case l4:
|
||||
case log4:
|
||||
current_level = 4;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
char Log::get_hex_digit(unsigned char c)
|
||||
{
|
||||
if( c < 10 )
|
||||
|
@ -393,7 +598,6 @@ return c - 10 + 'A';
|
|||
}
|
||||
|
||||
|
||||
|
||||
void Log::to_hex(char * buf, unsigned char c)
|
||||
{
|
||||
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;
|
||||
char buf[3];
|
||||
|
||||
if( buffer && file_log && blob && current_level <= file_log->get_log_level() )
|
||||
if( can_put_log() )
|
||||
{
|
||||
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()
|
||||
{
|
||||
save_log();
|
||||
|
@ -483,7 +686,3 @@ void Log::save_log()
|
|||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
148
src/log/log.h
148
src/log/log.h
|
@ -45,22 +45,16 @@
|
|||
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
class Model;
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace pt
|
||||
{
|
||||
|
||||
|
||||
class Log
|
||||
class Log : public Stream
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
/*
|
||||
log1 - the first level
|
||||
log2
|
||||
|
@ -76,81 +70,91 @@ public:
|
|||
log3,
|
||||
log4,
|
||||
|
||||
l1,
|
||||
l2,
|
||||
l3,
|
||||
l4,
|
||||
|
||||
logend,
|
||||
lend,
|
||||
|
||||
logsave,
|
||||
lsave,
|
||||
};
|
||||
|
||||
|
||||
|
||||
Log();
|
||||
virtual ~Log();
|
||||
~Log();
|
||||
|
||||
virtual void SetLogBuffer(WTextStream * buffer);
|
||||
virtual WTextStream * GetLogBuffer();
|
||||
bool is_char_stream() const;
|
||||
bool is_wchar_stream() const;
|
||||
|
||||
void SetFileLog(FileLog * file_log);
|
||||
FileLog * GetFileLog();
|
||||
void clear();
|
||||
bool empty() const;
|
||||
size_t size() const;
|
||||
void reserve(size_t len);
|
||||
size_t capacity() const;
|
||||
|
||||
void SetMaxBufferLength(size_t max_buffer_length);
|
||||
size_t GetMaxBufferLength();
|
||||
void to_str(std::string & str, bool clear_string = true) const;
|
||||
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);
|
||||
virtual Log & operator<<(const std::string * s);
|
||||
virtual Log & operator<<(const std::string & s);
|
||||
Log & operator<<(const char * s);
|
||||
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);
|
||||
virtual Log & operator<<(const std::wstring * s);
|
||||
virtual Log & operator<<(const std::wstring & s);
|
||||
Log & operator<<(char val);
|
||||
Log & operator<<(unsigned char val);
|
||||
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);
|
||||
virtual Log & operator<<(wchar_t s);
|
||||
Log & operator<<(const Stream & stream);
|
||||
Log & operator<<(const Space & space);
|
||||
Log & operator<<(const Date & date);
|
||||
|
||||
virtual Log & operator<<(int s);
|
||||
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
|
||||
#ifdef PT_HAS_MORM_LIBRARY
|
||||
virtual Log & operator<<(morm::Model & model);
|
||||
#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 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 & LogString(const std::wstring & value, size_t max_size);
|
||||
virtual Log & int_min_width(size_t min_width);
|
||||
|
||||
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>
|
||||
Log & operator<<(const TextStreamBase<char_type, stack_size, heap_block_size> & buf);
|
||||
|
||||
|
||||
|
||||
virtual Log & LogBinary(const char * blob, size_t blob_len);
|
||||
virtual Log & LogBinary(const std::string & blob);
|
||||
virtual Log & put_binary_blob(const char * blob, size_t blob_len);
|
||||
virtual Log & put_binary_blob(const std::string & blob);
|
||||
|
||||
|
||||
|
||||
|
@ -176,6 +180,7 @@ protected:
|
|||
template<class StringType>
|
||||
Log & log_string_generic(const StringType & value, size_t max_size);
|
||||
|
||||
virtual bool can_put_log();
|
||||
virtual void save_log();
|
||||
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>
|
||||
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;
|
||||
|
||||
if( buffer && file_log && current_level <= file_log->get_log_level() )
|
||||
if( can_put_log() )
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
Space * option_table = space->get_object_field(option);
|
||||
Space * option_table = space->get_space(option);
|
||||
|
||||
if( !option_table )
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,9 +44,10 @@
|
|||
#include <map>
|
||||
#include <cstdio>
|
||||
#include <cwchar>
|
||||
#include <errno.h>
|
||||
#include "textstream/types.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::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
|
||||
{
|
||||
no_escape,
|
||||
|
@ -152,6 +150,7 @@ public:
|
|||
type_long,
|
||||
type_float,
|
||||
type_double,
|
||||
type_long_double,
|
||||
type_string,
|
||||
type_wstring,
|
||||
type_object,
|
||||
|
@ -164,6 +163,7 @@ public:
|
|||
long long value_long;
|
||||
float value_float;
|
||||
double value_double;
|
||||
long double value_long_double;
|
||||
std::string value_string;
|
||||
std::wstring value_wstring;
|
||||
ObjectType value_object;
|
||||
|
@ -201,6 +201,7 @@ public:
|
|||
Space(unsigned long long val);
|
||||
Space(float val);
|
||||
Space(double val);
|
||||
Space(long double val);
|
||||
Space(const char * str);
|
||||
Space(const wchar_t * str);
|
||||
Space(const std::string & str);
|
||||
|
@ -234,6 +235,7 @@ public:
|
|||
void set(unsigned long long val);
|
||||
void set(float val);
|
||||
void set(double val);
|
||||
void set(long double val);
|
||||
void set(const char * str);
|
||||
void set(const wchar_t * str);
|
||||
void set(const std::string & str);
|
||||
|
@ -255,6 +257,7 @@ public:
|
|||
Space & add(unsigned long long val);
|
||||
Space & add(float val);
|
||||
Space & add(double val);
|
||||
Space & add(long double val);
|
||||
Space & add(const char * val);
|
||||
Space & add(const wchar_t * 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, float 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 wchar_t * 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, float 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 wchar_t * 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)
|
||||
{
|
||||
std::wstring temp;
|
||||
str.to_string(temp);
|
||||
str.to_str(temp);
|
||||
|
||||
return add(field, temp);
|
||||
}
|
||||
|
@ -322,7 +327,7 @@ public:
|
|||
Space & add_stream(const std::wstring & field, StreamType & str)
|
||||
{
|
||||
std::wstring temp;
|
||||
str.to_string(temp);
|
||||
str.to_str(temp);
|
||||
|
||||
return add(field, temp);
|
||||
}
|
||||
|
@ -335,6 +340,7 @@ public:
|
|||
bool is_long_long() const;
|
||||
bool is_float() const;
|
||||
bool is_double() const;
|
||||
bool is_long_double() const;
|
||||
bool is_numeric() const;
|
||||
bool is_str() const;
|
||||
bool is_wstr() const;
|
||||
|
@ -355,6 +361,9 @@ public:
|
|||
unsigned long to_ulong() const;
|
||||
unsigned long long to_ullong() 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::wstring to_wstr() const;
|
||||
|
||||
|
@ -418,6 +427,7 @@ public:
|
|||
long long * get_long_long();
|
||||
float * get_float();
|
||||
double * get_double();
|
||||
long double * get_long_double();
|
||||
std::string * get_str();
|
||||
std::wstring * get_wstr();
|
||||
ObjectType * get_object();
|
||||
|
@ -443,17 +453,21 @@ public:
|
|||
// size_t argument will be only for tables, wchar_t* or std::wstring for objects?
|
||||
|
||||
// getters from object
|
||||
Space * get_object_field(const wchar_t * field); // may a better name?
|
||||
const Space * get_object_field(const wchar_t * field) const; // may a better name?
|
||||
Space * get_object_field(const std::wstring & field);
|
||||
const Space * get_object_field(const std::wstring & field) const; // may a better name?
|
||||
Space * get_space(const wchar_t * field);
|
||||
const Space * get_space(const wchar_t * field) const;
|
||||
Space * get_space(const std::wstring & field);
|
||||
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);
|
||||
long long * get_llong(const wchar_t * field);
|
||||
long long * get_long_long(const wchar_t * field);
|
||||
float * get_float(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::wstring * get_wstr(const wchar_t * field);
|
||||
ObjectType * get_object(const wchar_t * field);
|
||||
|
@ -466,6 +480,7 @@ public:
|
|||
const long long * get_long_long() const;
|
||||
const float * get_float() const;
|
||||
const double * get_double() const;
|
||||
const long double * get_long_double() const;
|
||||
const std::string * get_str() const;
|
||||
const std::wstring * get_wstr() const;
|
||||
const ObjectType * get_object() const;
|
||||
|
@ -480,6 +495,7 @@ public:
|
|||
const long long * get_long_long(const wchar_t * field) const;
|
||||
const float * get_float(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::wstring * get_wstr(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
|
||||
Space * get_object_field_nc(const wchar_t * field);
|
||||
Space * get_object_field_nc(const std::wstring & field);
|
||||
const Space * get_object_field_nc(const wchar_t * field) const;
|
||||
const Space * get_object_field_nc(const std::wstring & field) const;
|
||||
Space * get_space_nc(const wchar_t * field);
|
||||
Space * get_space_nc(const std::wstring & field);
|
||||
const Space * get_space_nc(const wchar_t * 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 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::wstring serialize_to_space_wstr(bool pretty_print = false) const;
|
||||
|
@ -510,7 +549,7 @@ public:
|
|||
{
|
||||
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>
|
||||
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)
|
||||
{
|
||||
|
@ -547,6 +593,10 @@ public:
|
|||
serialize_json_double(str);
|
||||
break;
|
||||
|
||||
case type_long_double:
|
||||
serialize_json_long_double(str);
|
||||
break;
|
||||
|
||||
case type_string:
|
||||
serialize_json_string(str);
|
||||
break;
|
||||
|
@ -556,11 +606,11 @@ public:
|
|||
break;
|
||||
|
||||
case type_object:
|
||||
serialize_json_object(str);
|
||||
serialize_json_object(str, pretty_print, level + 1);
|
||||
break;
|
||||
|
||||
case type_table:
|
||||
serialize_json_table(str);
|
||||
serialize_json_table(str, pretty_print, level + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -580,39 +630,7 @@ public:
|
|||
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:
|
||||
|
@ -634,9 +652,16 @@ protected:
|
|||
Space & add_generic(const wchar_t * field, const ArgType & val)
|
||||
{
|
||||
initialize_value_object_if_needed();
|
||||
|
||||
auto insert_res = value.value_object.insert(std::make_pair(field, nullptr));
|
||||
|
||||
if( insert_res.second )
|
||||
{
|
||||
insert_res.first->second = new Space(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
insert_res.first->second->set(val);
|
||||
}
|
||||
|
||||
return *(insert_res.first->second);
|
||||
}
|
||||
|
@ -733,7 +758,7 @@ protected:
|
|||
if( clear_list )
|
||||
output_list.clear();
|
||||
|
||||
const Space * space = get_object_field(field);
|
||||
const Space * space = get_space(field);
|
||||
|
||||
if( space )
|
||||
{
|
||||
|
@ -751,7 +776,7 @@ protected:
|
|||
if( clear_list )
|
||||
output_list.clear();
|
||||
|
||||
const Space * space = get_object_field(field);
|
||||
const Space * space = get_space(field);
|
||||
|
||||
if( space )
|
||||
{
|
||||
|
@ -948,7 +973,7 @@ protected:
|
|||
wchar_t buffer[100];
|
||||
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 )
|
||||
buffer[0] = 0;
|
||||
|
@ -962,7 +987,21 @@ protected:
|
|||
wchar_t buffer[100];
|
||||
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 )
|
||||
buffer[0] = 0;
|
||||
|
@ -992,19 +1031,26 @@ protected:
|
|||
if( !is_main_object )
|
||||
{
|
||||
str << '{';
|
||||
print_if(pretty_print && (!value.value_object.empty() || !child_spaces_empty()), str, '\n');
|
||||
}
|
||||
|
||||
bool is_first = true;
|
||||
|
||||
for(auto & map_item : value.value_object)
|
||||
{
|
||||
if( !is_first )
|
||||
print_if(pretty_print, str, '\n', ',');
|
||||
if( is_first )
|
||||
{
|
||||
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);
|
||||
|
||||
print_level(pretty_print, level, str);
|
||||
print_if(quote_field, str, '"');
|
||||
serialize_string_buffer(map_item.first.c_str(), str, Escape::escape_space);
|
||||
print_if(quote_field, str, '"');
|
||||
|
@ -1013,87 +1059,52 @@ protected:
|
|||
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;
|
||||
}
|
||||
|
||||
print_if(!is_first && pretty_print, str, '\n');
|
||||
serialize_child_spaces(str, pretty_print, level);
|
||||
|
||||
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 << '}';
|
||||
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>
|
||||
void serialize_space_table(StreamType & str, bool pretty_print, int level) const
|
||||
{
|
||||
bool multivalue_table = false;
|
||||
bool is_first = true;
|
||||
|
||||
if( value.value_table.size() > 1 )
|
||||
{
|
||||
multivalue_table = true;
|
||||
}
|
||||
|
||||
str << '(';
|
||||
print_if(pretty_print && multivalue_table, str, '\n');
|
||||
|
||||
for(Space * space : value.value_table)
|
||||
{
|
||||
if( !is_first )
|
||||
print_if(pretty_print, str, '\n', ',');
|
||||
if( is_first )
|
||||
{
|
||||
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 + 1, false);
|
||||
space->serialize_to_space_stream(str, pretty_print, level, false);
|
||||
is_first = false;
|
||||
}
|
||||
|
||||
print_if(pretty_print && multivalue_table, str, '\n');
|
||||
print_level(pretty_print && multivalue_table, level - 1, str);
|
||||
print_if(pretty_print && !is_first, str, '\n');
|
||||
print_level(pretty_print && !is_first, level - 1, str);
|
||||
str << ')';
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
template<typename StreamType>
|
||||
|
@ -1132,7 +1143,7 @@ protected:
|
|||
wchar_t buffer[100];
|
||||
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 )
|
||||
buffer[0] = 0;
|
||||
|
@ -1146,7 +1157,21 @@ protected:
|
|||
wchar_t buffer[100];
|
||||
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 )
|
||||
buffer[0] = 0;
|
||||
|
@ -1171,53 +1196,70 @@ protected:
|
|||
}
|
||||
|
||||
template<typename StreamType>
|
||||
void serialize_json_object(StreamType & str) const
|
||||
void serialize_json_object(StreamType & str, bool pretty_print, int level) const
|
||||
{
|
||||
str << '{';
|
||||
|
||||
bool is_first = true;
|
||||
|
||||
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 << ',';
|
||||
print_if(pretty_print, str, '\n');
|
||||
print_level(pretty_print, level, str);
|
||||
}
|
||||
|
||||
str << '"';
|
||||
serialize_string_buffer(map_item.first.c_str(), str, Escape::escape_json);
|
||||
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;
|
||||
}
|
||||
|
||||
print_if(pretty_print && !is_first, str, '\n');
|
||||
print_level(pretty_print && !is_first, level - 1, str);
|
||||
str << '}';
|
||||
}
|
||||
|
||||
template<typename StreamType>
|
||||
void serialize_json_table(StreamType & str) const
|
||||
void serialize_json_table(StreamType & str, bool pretty_print, int level) const
|
||||
{
|
||||
str << '[';
|
||||
|
||||
bool is_first = true;
|
||||
|
||||
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 << ',';
|
||||
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;
|
||||
}
|
||||
|
||||
print_if(pretty_print && !is_first, str, '\n');
|
||||
print_level(pretty_print && !is_first, level - 1, str);
|
||||
str << ']';
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
template<typename StreamType>
|
||||
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);
|
||||
break;
|
||||
|
||||
case type_long_double:
|
||||
serialize_space_long_double(str);
|
||||
break;
|
||||
|
||||
case type_string:
|
||||
serialize_space_string(str);
|
||||
break;
|
||||
|
@ -1253,11 +1299,11 @@ protected:
|
|||
break;
|
||||
|
||||
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;
|
||||
|
||||
case type_table:
|
||||
serialize_space_table(str, pretty_print, level);
|
||||
serialize_space_table(str, pretty_print, level + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1303,17 +1349,7 @@ protected:
|
|||
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_value_object(const Value & value_from);
|
||||
|
@ -1328,6 +1364,7 @@ protected:
|
|||
void initialize_value_long_if_needed();
|
||||
void initialize_value_float_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(std::string && str);
|
||||
void initialize_value_wstring_if_needed();
|
||||
|
@ -1336,16 +1373,12 @@ protected:
|
|||
void initialize_value_object_if_needed(ObjectType && obj);
|
||||
void initialize_value_table_if_needed();
|
||||
void initialize_value_table_if_needed(TableType && tab);
|
||||
void initialize_child_spaces_if_needed();
|
||||
|
||||
void remove_value();
|
||||
void remove_value_string();
|
||||
void remove_value_wstring();
|
||||
void remove_value_object();
|
||||
void remove_value_table();
|
||||
|
||||
const Space * find_child_space_const(const wchar_t * name) const;
|
||||
const Space * find_child_space_const(size_t table_index) const;
|
||||
void remove_value_object(bool only_clear = false);
|
||||
void remove_value_table(bool only_clear = false);
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -499,7 +499,7 @@ void SpaceParser::parse_key_value_pairs(Space * 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();
|
||||
|
||||
if( lastc == space_end )
|
||||
|
@ -530,12 +530,6 @@ void SpaceParser::parse_key_value_pairs(Space * space)
|
|||
parse(&new_space, true, false);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -39,16 +39,18 @@
|
|||
#define headerfile_picotools_textstream_textstream
|
||||
|
||||
#include <string>
|
||||
#include "stream.h"
|
||||
#include "space/space.h"
|
||||
#include "date/date.h"
|
||||
#include "convert/inttostr.h"
|
||||
#include "membuffer/membuffer.h"
|
||||
#include "types.h"
|
||||
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
// for snprintf
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
namespace pt
|
||||
{
|
||||
|
||||
|
@ -58,10 +60,9 @@ namespace pt
|
|||
similar to std::ostringstream
|
||||
|
||||
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>
|
||||
class TextStreamBase
|
||||
class TextStreamBase : public Stream
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -74,6 +75,9 @@ public:
|
|||
typedef typename buffer_type::const_iterator const_iterator;
|
||||
|
||||
|
||||
bool is_char_stream() const;
|
||||
bool is_wchar_stream() const;
|
||||
|
||||
void clear();
|
||||
bool empty() const;
|
||||
size_t size() const;
|
||||
|
@ -86,47 +90,59 @@ public:
|
|||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
void to_string(std::string & str, bool clear_string = true) const;
|
||||
void to_string(std::wstring & str, bool clear_string = true) const;
|
||||
// IMPROVE ME
|
||||
// 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) const;
|
||||
|
||||
TextStreamBase & operator<<(const char * str);
|
||||
TextStreamBase & operator<<(const std::string & str);
|
||||
|
||||
TextStreamBase & operator<<(const wchar_t * str);
|
||||
TextStreamBase & operator<<(const std::wstring * str);
|
||||
TextStreamBase & operator<<(const std::wstring & str);
|
||||
|
||||
TextStreamBase & operator<<(char);
|
||||
TextStreamBase & operator<<(unsigned char);
|
||||
TextStreamBase & operator<<(wchar_t);
|
||||
TextStreamBase & operator<<(bool);
|
||||
TextStreamBase & operator<<(short);
|
||||
TextStreamBase & operator<<(int);
|
||||
TextStreamBase & operator<<(long);
|
||||
TextStreamBase & operator<<(long long);
|
||||
TextStreamBase & operator<<(unsigned short);
|
||||
TextStreamBase & operator<<(unsigned int);
|
||||
TextStreamBase & operator<<(unsigned long);
|
||||
TextStreamBase & operator<<(unsigned long long);
|
||||
TextStreamBase & operator<<(float);
|
||||
TextStreamBase & operator<<(double);
|
||||
TextStreamBase & operator<<(long double);
|
||||
TextStreamBase & operator<<(const void *); // printing a pointer
|
||||
|
||||
TextStreamBase & operator<<(const Stream & stream);
|
||||
TextStreamBase & operator<<(const Space & space);
|
||||
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
|
||||
// if the output value has less digits then first zeroes are added
|
||||
// (0 turn off)
|
||||
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 & operator<<(const TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg);
|
||||
|
||||
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 & write(const char * buf, size_t len);
|
||||
TextStreamBase & write(const wchar_t * buf, size_t len);
|
||||
|
||||
TextStreamBase & fill_up_if_needed(wchar_t fill_up_char, size_t existing_length);
|
||||
|
||||
|
@ -136,6 +152,13 @@ public:
|
|||
int radix;
|
||||
size_t min_width_for_integers;
|
||||
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>
|
||||
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>
|
||||
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 )
|
||||
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() )
|
||||
str.reserve(str.size() + size());
|
||||
|
||||
|
||||
if constexpr (sizeof(char_type) == sizeof(char) )
|
||||
{
|
||||
const_iterator i = begin();
|
||||
|
||||
for( ; i != end() ; ++i)
|
||||
str += static_cast<char>(*i);
|
||||
str += *i;
|
||||
}
|
||||
else
|
||||
{
|
||||
wide_stream_to_utf8(*this, str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 )
|
||||
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() )
|
||||
str.reserve(str.size() + size());
|
||||
|
||||
if constexpr (sizeof(char_type) == sizeof(wchar_t) )
|
||||
{
|
||||
const_iterator i = begin();
|
||||
|
||||
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>
|
||||
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>::operator<<(const char * str)
|
||||
{
|
||||
if constexpr ( sizeof(char_type) == sizeof(char) )
|
||||
{
|
||||
for( ; *str ; ++str)
|
||||
buffer.append(static_cast<char_type>(*str));
|
||||
buffer.append(*str);
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8_to_wide(str, *this, false);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -278,9 +392,6 @@ 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<<(const std::string & str)
|
||||
{
|
||||
if( sizeof(char_type) == sizeof(char) )
|
||||
buffer.append(str.c_str(), str.size());
|
||||
else
|
||||
operator<<(str.c_str());
|
||||
|
||||
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>::operator<<(const wchar_t * str)
|
||||
{
|
||||
if constexpr (sizeof(char_type) == sizeof(wchar_t) )
|
||||
{
|
||||
for( ; *str ; ++str)
|
||||
buffer.append(static_cast<char_type>(*str));
|
||||
buffer.append(*str);
|
||||
}
|
||||
else
|
||||
{
|
||||
wide_to_utf8(str, *this);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -304,9 +422,6 @@ 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<<(const std::wstring & str)
|
||||
{
|
||||
if( sizeof(char_type) == sizeof(wchar_t) )
|
||||
buffer.append(str.c_str(), str.size());
|
||||
else
|
||||
operator<<(str.c_str());
|
||||
|
||||
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>::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));
|
||||
|
||||
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>::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));
|
||||
|
||||
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>
|
||||
TextStreamBase<char_type, stack_size, heap_block_size> &
|
||||
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>
|
||||
TextStreamBase<char_type, stack_size, heap_block_size> &
|
||||
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>
|
||||
TextStreamBase<char_type, stack_size, heap_block_size> &
|
||||
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(double v)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -433,12 +610,20 @@ return *this;
|
|||
|
||||
|
||||
|
||||
|
||||
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>::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;
|
||||
}
|
||||
|
@ -446,23 +631,73 @@ 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>::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 operator<<(buf);
|
||||
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>::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 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>::operator<<(
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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>::int_min_width(size_t min_width)
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include "utf8.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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#define headerfile_picotools_utf8_utf8
|
||||
|
||||
#include <string>
|
||||
#include "textstream/textstream.h"
|
||||
#include "textstream/stream.h"
|
||||
|
||||
|
||||
namespace pt
|
||||
|
@ -60,6 +60,8 @@ namespace pt
|
|||
|
||||
/*!
|
||||
returns true if 'c' is a correct unicode character
|
||||
|
||||
RENAMEME to is_correct_unicode_char
|
||||
*/
|
||||
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 std::string & 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>
|
||||
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>
|
||||
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>
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#ifndef headerfile_picotools_utf8_utf8_private
|
||||
#define headerfile_picotools_utf8_utf8_private
|
||||
|
||||
#include "textstream/textstream.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
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
|
||||
// and mode parameter
|
||||
template<typename char_type, size_t stack_size, size_t heap_block_size, typename function_type>
|
||||
void wide_to_utf8_generic(TextStreamBase<char_type, stack_size, heap_block_size> & buffer, int mode, function_type write_function)
|
||||
// and is not using mode parameter
|
||||
template<typename StreamType, typename function_type>
|
||||
void wide_to_utf8_generic(StreamType & buffer, int mode, function_type write_function)
|
||||
{
|
||||
char utf8_buffer[256];
|
||||
std::size_t buffer_len = sizeof(utf8_buffer) / sizeof(char);
|
||||
std::size_t utf8_sequence_max_length = 10;
|
||||
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() )
|
||||
{
|
||||
|
|
|
@ -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
|
||||
(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();
|
||||
|
||||
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;
|
||||
|
@ -110,7 +128,7 @@ bool correct, was_error = false;
|
|||
}
|
||||
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
|
||||
template<typename StreamTypeIn, typename StreamTypeOut>
|
||||
void wide_stream_to_utf8(StreamTypeIn & buffer, StreamTypeOut & utf8, int mode)
|
||||
|
|
|
@ -3,23 +3,30 @@
|
|||
./main.o: convert.h mainoptionsparser.h csvparser.h
|
||||
./convert.o: convert.h test.h ../src/convert/convert.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/types.h ../src/convert/inttostr.h
|
||||
./convert.o: ../src/date/date.h ../src/membuffer/membuffer.h
|
||||
./convert.o: ../src/textstream/types.h ../src/convert/strtoint.h
|
||||
./convert.o: ../src/convert/text.h ../src/convert/misc.h
|
||||
./convert.o: ../src/textstream/textstream.h ../src/textstream/stream.h
|
||||
./convert.o: ../src/space/space.h ../src/textstream/types.h
|
||||
./convert.o: ../src/convert/inttostr.h ../src/utf8/utf8.h
|
||||
./convert.o: ../src/textstream/stream.h ../src/utf8/utf8_templates.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
|
||||
./mainoptionsparser.o: mainoptionsparser.h test.h
|
||||
./mainoptionsparser.o: ../src/mainoptions/mainoptionsparser.h
|
||||
./mainoptionsparser.o: ../src/space/space.h ../src/textstream/types.h
|
||||
./mainoptionsparser.o: ../src/convert/inttostr.h ../src/utf8/utf8.h
|
||||
./mainoptionsparser.o: ../src/textstream/textstream.h ../src/date/date.h
|
||||
./mainoptionsparser.o: ../src/membuffer/membuffer.h ../src/textstream/types.h
|
||||
./mainoptionsparser.o: ../src/textstream/stream.h
|
||||
./mainoptionsparser.o: ../src/utf8/utf8_templates.h
|
||||
./mainoptionsparser.o: ../src/utf8/utf8_private.h ../src/convert/convert.h
|
||||
./mainoptionsparser.o: ../src/convert/inttostr.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/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: ../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
|
||||
|
|
Loading…
Reference in New Issue