- added some converting methods: esc_to_json(...), esc_to_xml(...), esc_to_csv() (convert/misc.h)
- BaseParser: added possibility to read from TextStream and WTextStream - HTMLParser: added filter(const WTextStream & in, Stream & out, ...) method - added utf8_stream.h with one method: template<typename StreamIteratorType> size_t utf8_to_int( StreamIteratorType & iterator_in, StreamIteratorType & iterator_end, int & res, bool & correct)
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
|
||||
#include "baseparser.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
#include "utf8/utf8_stream.h"
|
||||
|
||||
|
||||
namespace pt
|
||||
@@ -45,19 +45,27 @@ namespace pt
|
||||
|
||||
BaseParser::BaseParser()
|
||||
{
|
||||
clear();
|
||||
clear_input_flags();
|
||||
}
|
||||
|
||||
|
||||
void BaseParser::clear()
|
||||
void BaseParser::clear_input_flags()
|
||||
{
|
||||
line = 0;
|
||||
reading_from_file = false;
|
||||
pchar_ascii = nullptr;
|
||||
pchar_unicode = nullptr;
|
||||
reading_from_wchar_string = false;
|
||||
wtext_stream_iterator = nullptr;
|
||||
wtext_stream_iterator_end = nullptr;
|
||||
text_stream_iterator = nullptr;
|
||||
text_stream_iterator_end = nullptr;
|
||||
lastc = -1;
|
||||
input_as_utf8 = true;
|
||||
|
||||
if( file.is_open() )
|
||||
file.close();
|
||||
|
||||
file.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +140,6 @@ bool correct;
|
||||
++line;
|
||||
|
||||
return lastc;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +157,67 @@ return lastc;
|
||||
}
|
||||
|
||||
|
||||
int BaseParser::read_char_from_wtext_stream()
|
||||
{
|
||||
if( (*wtext_stream_iterator) != (*wtext_stream_iterator_end) )
|
||||
{
|
||||
lastc = *(*wtext_stream_iterator);
|
||||
++(*wtext_stream_iterator);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastc = -1;
|
||||
}
|
||||
|
||||
if( lastc == '\n' )
|
||||
++line;
|
||||
|
||||
return lastc;
|
||||
}
|
||||
|
||||
|
||||
int BaseParser::read_char_from_utf8_text_stream()
|
||||
{
|
||||
int c;
|
||||
bool correct;
|
||||
|
||||
lastc = -1;
|
||||
|
||||
do
|
||||
{
|
||||
utf8_to_int(*text_stream_iterator, *text_stream_iterator_end, c, correct);
|
||||
}
|
||||
while( !correct && (*text_stream_iterator) != (*text_stream_iterator_end) );
|
||||
|
||||
if( correct )
|
||||
lastc = c;
|
||||
|
||||
if( lastc == '\n' )
|
||||
++line;
|
||||
|
||||
return lastc;
|
||||
}
|
||||
|
||||
|
||||
int BaseParser::read_char_from_ascii_text_stream()
|
||||
{
|
||||
if( (*text_stream_iterator) != (*text_stream_iterator_end) )
|
||||
{
|
||||
lastc = *(*text_stream_iterator);
|
||||
++(*text_stream_iterator);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastc = -1;
|
||||
}
|
||||
|
||||
if( lastc == '\n' )
|
||||
++line;
|
||||
|
||||
return lastc;
|
||||
}
|
||||
|
||||
|
||||
int BaseParser::read_char_no_escape()
|
||||
{
|
||||
if( reading_from_file )
|
||||
@@ -161,17 +229,33 @@ int BaseParser::read_char_no_escape()
|
||||
}
|
||||
else
|
||||
{
|
||||
if( reading_from_wchar_string )
|
||||
{
|
||||
return read_char_from_wchar_string();
|
||||
}
|
||||
else
|
||||
if( pchar_ascii )
|
||||
{
|
||||
if( input_as_utf8 )
|
||||
return read_char_from_utf8_string();
|
||||
else
|
||||
return read_char_from_ascii_string();
|
||||
}
|
||||
else if( pchar_unicode )
|
||||
{
|
||||
return read_char_from_wchar_string();
|
||||
}
|
||||
else if( wtext_stream_iterator && wtext_stream_iterator_end )
|
||||
{
|
||||
return read_char_from_wtext_stream();
|
||||
}
|
||||
else if( text_stream_iterator && text_stream_iterator_end )
|
||||
{
|
||||
if( input_as_utf8 )
|
||||
return read_char_from_utf8_text_stream();
|
||||
else
|
||||
return read_char_from_ascii_text_stream();
|
||||
}
|
||||
else
|
||||
{
|
||||
lastc = -1;
|
||||
return lastc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -40,6 +40,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include "textstream/textstream.h"
|
||||
|
||||
|
||||
namespace pt
|
||||
@@ -51,15 +52,18 @@ protected:
|
||||
|
||||
BaseParser();
|
||||
|
||||
void clear();
|
||||
virtual void clear_input_flags();
|
||||
|
||||
int read_utf8_char();
|
||||
int read_ascii_char();
|
||||
int read_char_from_wchar_string();
|
||||
int read_char_from_utf8_string();
|
||||
int read_char_from_ascii_string();
|
||||
int read_char_no_escape();
|
||||
int read_char();
|
||||
virtual int read_utf8_char();
|
||||
virtual int read_ascii_char();
|
||||
virtual int read_char_from_wchar_string();
|
||||
virtual int read_char_from_utf8_string();
|
||||
virtual int read_char_from_ascii_string();
|
||||
virtual int read_char_from_wtext_stream();
|
||||
virtual int read_char_from_utf8_text_stream();
|
||||
virtual int read_char_from_ascii_text_stream();
|
||||
virtual int read_char_no_escape();
|
||||
virtual int read_char();
|
||||
|
||||
|
||||
|
||||
@@ -75,6 +79,7 @@ protected:
|
||||
*/
|
||||
bool reading_from_file;
|
||||
|
||||
|
||||
/*
|
||||
pointers to the current character
|
||||
if ParseString() is in used
|
||||
@@ -84,9 +89,20 @@ protected:
|
||||
|
||||
|
||||
/*
|
||||
true if ParseString(wchar_t *) or ParseString(std::wstring&) was called
|
||||
*/
|
||||
bool reading_from_wchar_string;
|
||||
pointers to WTextStream iterators
|
||||
if set then both of them should be set
|
||||
*/
|
||||
WTextStream::const_iterator * wtext_stream_iterator;
|
||||
WTextStream::const_iterator * wtext_stream_iterator_end;
|
||||
|
||||
|
||||
/*
|
||||
pointers to TextStream iterators
|
||||
if set then both of them should be set
|
||||
*/
|
||||
TextStream::const_iterator * text_stream_iterator;
|
||||
TextStream::const_iterator * text_stream_iterator_end;
|
||||
|
||||
|
||||
/*
|
||||
last read char
|
||||
@@ -112,7 +128,6 @@ protected:
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017, Tomasz Sowa
|
||||
* Copyright (c) 2017-2021, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -36,6 +36,8 @@
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "inttostr.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
||||
namespace pt
|
||||
@@ -49,6 +51,287 @@ void SetOverflow(bool * was_overflow, bool val)
|
||||
}
|
||||
|
||||
|
||||
void esc_to_json(char val, Stream & out)
|
||||
{
|
||||
if( (unsigned char)val < 32 )
|
||||
{
|
||||
char buf[10];
|
||||
size_t len;
|
||||
Toa((unsigned char)val, buf, sizeof(buf)/sizeof(char), 16, &len);
|
||||
|
||||
out << "\\u";
|
||||
|
||||
if( len < 4 )
|
||||
{
|
||||
for(size_t i=0 ; i < (4-len) ; ++i)
|
||||
{
|
||||
out << '0';
|
||||
}
|
||||
}
|
||||
|
||||
out << buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
// CHECKME
|
||||
// \r \n \t are <32 and will be serialized os \u.... above
|
||||
|
||||
switch( val )
|
||||
{
|
||||
case 0: out << '\\'; out << '0'; break; // may to skip this character is better?
|
||||
case '\r': out << '\\'; out << 'r'; break;
|
||||
case '\n': out << '\\'; out << 'n'; break;
|
||||
case '\t': out << '\\'; out << 't'; break;
|
||||
case 0x08: out << '\\'; out << 'b'; break;
|
||||
case 0x0c: out << '\\'; out << 'f'; break;
|
||||
case '\\': out << '\\'; out << '\\'; break;
|
||||
case '"': out << '\\'; out << '\"'; break;
|
||||
default:
|
||||
out << val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_json(wchar_t val, Stream & out)
|
||||
{
|
||||
char utf8_buf[10];
|
||||
std::size_t utf8_buf_len = sizeof(utf8_buf) / sizeof(char);
|
||||
|
||||
size_t len = int_to_utf8(static_cast<int>(val), utf8_buf, utf8_buf_len);
|
||||
|
||||
for(size_t a = 0 ; a < len ; ++a)
|
||||
{
|
||||
esc_to_json(utf8_buf[a], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_json(const char * c, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; c[i] != 0 ; ++i)
|
||||
{
|
||||
esc_to_json(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_json(const char * c, std::size_t len, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; i < len ; ++i)
|
||||
{
|
||||
esc_to_json(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_json(const wchar_t * c, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; c[i] != 0 ; ++i)
|
||||
{
|
||||
esc_to_json(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_json(const wchar_t * c, size_t len, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; i < len ; ++i)
|
||||
{
|
||||
esc_to_json(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_json(const std::string & in, Stream & out)
|
||||
{
|
||||
esc_to_json(in.c_str(), in.size(), out);
|
||||
}
|
||||
|
||||
|
||||
void esc_to_json(const std::wstring & in, Stream & out)
|
||||
{
|
||||
esc_to_json(in.c_str(), in.size(), out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void esc_to_xml(char val, Stream & out)
|
||||
{
|
||||
switch(val)
|
||||
{
|
||||
case '<':
|
||||
out << "<";
|
||||
break;
|
||||
|
||||
case '>':
|
||||
out << ">";
|
||||
break;
|
||||
|
||||
case '&':
|
||||
out << "&";
|
||||
break;
|
||||
|
||||
case '"':
|
||||
out << """;
|
||||
break;
|
||||
|
||||
default:
|
||||
out << val;
|
||||
break;
|
||||
|
||||
// what about zero (null) character?
|
||||
}
|
||||
}
|
||||
|
||||
void esc_to_xml(wchar_t val, Stream & out)
|
||||
{
|
||||
char utf8_buf[10];
|
||||
std::size_t utf8_buf_len = sizeof(utf8_buf) / sizeof(char);
|
||||
|
||||
size_t len = int_to_utf8(static_cast<int>(val), utf8_buf, utf8_buf_len);
|
||||
|
||||
for(size_t a = 0 ; a < len ; ++a)
|
||||
{
|
||||
esc_to_xml(utf8_buf[a], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_xml(const char * c, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; c[i] != 0 ; ++i)
|
||||
{
|
||||
esc_to_xml(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_xml(const char * c, std::size_t len, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; i < len ; ++i)
|
||||
{
|
||||
esc_to_xml(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_xml(const wchar_t * c, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; c[i] != 0 ; ++i)
|
||||
{
|
||||
esc_to_xml(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_xml(const wchar_t * c, size_t len, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; i < len ; ++i)
|
||||
{
|
||||
esc_to_xml(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_xml(const std::string & in, Stream & out)
|
||||
{
|
||||
esc_to_xml(in.c_str(), in.size(), out);
|
||||
}
|
||||
|
||||
|
||||
void esc_to_xml(const std::wstring & in, Stream & out)
|
||||
{
|
||||
esc_to_xml(in.c_str(), in.size(), out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void esc_to_csv(char c, pt::Stream & out)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '"':
|
||||
out << "\"\"";
|
||||
break;
|
||||
|
||||
default:
|
||||
out << c;
|
||||
break;
|
||||
|
||||
// what about zero (null) character?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_csv(wchar_t val, Stream & out)
|
||||
{
|
||||
char utf8_buf[10];
|
||||
std::size_t utf8_buf_len = sizeof(utf8_buf) / sizeof(char);
|
||||
|
||||
size_t len = int_to_utf8(static_cast<int>(val), utf8_buf, utf8_buf_len);
|
||||
|
||||
for(size_t a = 0 ; a < len ; ++a)
|
||||
{
|
||||
esc_to_csv(utf8_buf[a], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void esc_to_csv(const char * c, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; c[i] != 0 ; ++i)
|
||||
{
|
||||
esc_to_csv(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_csv(const char * c, std::size_t len, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; i < len ; ++i)
|
||||
{
|
||||
esc_to_csv(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_csv(const wchar_t * c, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; c[i] != 0 ; ++i)
|
||||
{
|
||||
esc_to_csv(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_csv(const wchar_t * c, size_t len, pt::Stream & out)
|
||||
{
|
||||
for(size_t i = 0 ; i < len ; ++i)
|
||||
{
|
||||
esc_to_csv(c[i], out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void esc_to_csv(const std::string & in, Stream & out)
|
||||
{
|
||||
esc_to_csv(in.c_str(), in.size(), out);
|
||||
}
|
||||
|
||||
|
||||
void esc_to_csv(const std::wstring & in, Stream & out)
|
||||
{
|
||||
esc_to_csv(in.c_str(), in.size(), out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017, Tomasz Sowa
|
||||
* Copyright (c) 2017-2021, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -40,6 +40,9 @@
|
||||
|
||||
#include <limits>
|
||||
#include "text.h"
|
||||
#include "textstream/stream.h"
|
||||
#include "textstream/types.h"
|
||||
#include "utf8/utf8_stream.h"
|
||||
|
||||
|
||||
namespace pt
|
||||
@@ -47,6 +50,138 @@ namespace pt
|
||||
|
||||
void SetOverflow(bool * was_overflow, bool val);
|
||||
|
||||
void esc_to_json(char val, Stream & out);
|
||||
void esc_to_json(wchar_t val, Stream & out);
|
||||
void esc_to_json(const char * c, pt::Stream & out);
|
||||
void esc_to_json(const char * c, std::size_t len, Stream & out);
|
||||
void esc_to_json(const wchar_t * c, Stream & out);
|
||||
void esc_to_json(const wchar_t * c, size_t len, pt::Stream & out);
|
||||
void esc_to_json(const std::string & in, Stream & out);
|
||||
void esc_to_json(const std::wstring & in, Stream & out);
|
||||
|
||||
void esc_to_xml(char c, pt::Stream & out);
|
||||
void esc_to_xml(wchar_t c, pt::Stream & out);
|
||||
void esc_to_xml(const char * c, pt::Stream & out);
|
||||
void esc_to_xml(const char * c, std::size_t len, pt::Stream & out);
|
||||
void esc_to_xml(const wchar_t * c, pt::Stream & out);
|
||||
void esc_to_xml(const wchar_t * c, size_t len, pt::Stream & out);
|
||||
void esc_to_xml(const std::string & in, Stream & out);
|
||||
void esc_to_xml(const std::wstring & in, Stream & out);
|
||||
|
||||
void esc_to_csv(char c, pt::Stream & out);
|
||||
void esc_to_csv(wchar_t val, Stream & out);
|
||||
void esc_to_csv(const char * c, std::size_t len, Stream & out);
|
||||
void esc_to_csv(const char * c, pt::Stream & out);
|
||||
void esc_to_csv(const char * c, std::size_t len, pt::Stream & out);
|
||||
void esc_to_csv(const wchar_t * c, pt::Stream & out);
|
||||
void esc_to_csv(const wchar_t * c, size_t len, pt::Stream & out);
|
||||
void esc_to_csv(const std::string & in, Stream & out);
|
||||
|
||||
|
||||
|
||||
template<typename StreamType>
|
||||
void esc_to_json(const StreamType & in, Stream & out)
|
||||
{
|
||||
char utf8_buf[10];
|
||||
std::size_t utf8_buf_len = sizeof(utf8_buf) / sizeof(char);
|
||||
typename StreamType::const_iterator i = in.begin();
|
||||
typename StreamType::const_iterator end = in.end();
|
||||
int res;
|
||||
bool correct;
|
||||
|
||||
for( ; i != end ; ++i)
|
||||
{
|
||||
if( in.is_wchar_stream() && out.is_char_stream() )
|
||||
{
|
||||
std::size_t len = int_to_utf8(static_cast<int>(*i), utf8_buf, utf8_buf_len);
|
||||
esc_to_json(utf8_buf, len, out);
|
||||
}
|
||||
else
|
||||
if( in.is_char_stream() && out.is_wchar_stream() )
|
||||
{
|
||||
utf8_to_int(i, end, res, correct);
|
||||
|
||||
if( correct )
|
||||
esc_to_json(static_cast<wchar_t>(res), out); // IMPROVEME no surrogate pair used here (if sizeof(wchar_t) == 2)
|
||||
|
||||
// put replacement char if not correct?
|
||||
}
|
||||
else
|
||||
{
|
||||
esc_to_json(static_cast<wchar_t>(*i), out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename StreamType>
|
||||
void esc_to_xml(const StreamType & in, Stream & out)
|
||||
{
|
||||
char utf8_buf[10];
|
||||
std::size_t utf8_buf_len = sizeof(utf8_buf) / sizeof(char);
|
||||
typename StreamType::const_iterator i = in.begin();
|
||||
typename StreamType::const_iterator end = in.end();
|
||||
int res;
|
||||
bool correct;
|
||||
|
||||
for( ; i != end ; ++i)
|
||||
{
|
||||
if( in.is_wchar_stream() && out.is_char_stream() )
|
||||
{
|
||||
std::size_t len = int_to_utf8(static_cast<int>(*i), utf8_buf, utf8_buf_len);
|
||||
esc_to_xml(utf8_buf, len, out);
|
||||
}
|
||||
else
|
||||
if( in.is_char_stream() && out.is_wchar_stream() )
|
||||
{
|
||||
utf8_to_int(i, end, res, correct);
|
||||
|
||||
if( correct )
|
||||
esc_to_xml(static_cast<wchar_t>(res), out); // IMPROVEME no surrogate pair used here (if sizeof(wchar_t) == 2)
|
||||
|
||||
// put replacement char if not correct?
|
||||
}
|
||||
else
|
||||
{
|
||||
esc_to_xml(static_cast<wchar_t>(*i), out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename StreamType>
|
||||
void esc_to_csv(const StreamType & in, Stream & out)
|
||||
{
|
||||
char utf8_buf[10];
|
||||
std::size_t utf8_buf_len = sizeof(utf8_buf) / sizeof(char);
|
||||
typename StreamType::const_iterator i = in.begin();
|
||||
typename StreamType::const_iterator end = in.end();
|
||||
int res;
|
||||
bool correct;
|
||||
|
||||
for( ; i != end ; ++i)
|
||||
{
|
||||
if( in.is_wchar_stream() && out.is_char_stream() )
|
||||
{
|
||||
std::size_t len = int_to_utf8(static_cast<int>(*i), utf8_buf, utf8_buf_len);
|
||||
esc_to_csv(utf8_buf, len, out);
|
||||
}
|
||||
else
|
||||
if( in.is_char_stream() && out.is_wchar_stream() )
|
||||
{
|
||||
utf8_to_int(i, end, res, correct);
|
||||
|
||||
if( correct )
|
||||
esc_to_csv(static_cast<wchar_t>(res), out); // IMPROVEME no surrogate pair used here (if sizeof(wchar_t) == 2)
|
||||
|
||||
// put replacement char if not correct?
|
||||
}
|
||||
else
|
||||
{
|
||||
esc_to_csv(static_cast<wchar_t>(*i), out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user