2016-01-28 14:52:40 +01:00
|
|
|
|
/** @file
|
|
|
|
|
|
*
|
|
|
|
|
|
* @par History
|
2016-02-19 19:26:35 +01:00
|
|
|
|
* - 2009/09/12 MuadDib: Disabled 4244 in this file due to it being on a string iter. Makes no
|
|
|
|
|
|
* sense.
|
2018-04-03 04:13:03 +02:00
|
|
|
|
* - 2014/06/10 Nando: Removed pragma that disabled 4244. (tolower()/toupper() used ints because -1
|
2016-02-19 19:26:35 +01:00
|
|
|
|
* is a valid output).
|
2016-01-28 14:52:40 +01:00
|
|
|
|
*/
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "strutil.h"
|
|
|
|
|
|
|
2018-01-29 21:55:48 +01:00
|
|
|
|
#include <boost/algorithm/string/case_conv.hpp>
|
2023-02-08 21:13:48 +01:00
|
|
|
|
#include <boost/algorithm/string/trim.hpp>
|
2019-01-12 11:46:30 +01:00
|
|
|
|
#include <utf8/utf8.h>
|
2018-01-29 21:55:48 +01:00
|
|
|
|
|
|
|
|
|
|
#include "logfacility.h"
|
2016-02-11 22:54:43 +01:00
|
|
|
|
#include "stlutil.h"
|
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
|
namespace Pol
|
|
|
|
|
|
{
|
|
|
|
|
|
namespace Clib
|
|
|
|
|
|
{
|
|
|
|
|
|
void splitnamevalue( const std::string& istr, std::string& propname, std::string& propvalue )
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string::size_type start = istr.find_first_not_of( " \t\r\n" );
|
|
|
|
|
|
if ( start != std::string::npos )
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string::size_type delimpos = istr.find_first_of( " \t\r\n=", start + 1 );
|
|
|
|
|
|
if ( delimpos != std::string::npos )
|
2016-02-11 22:54:43 +01:00
|
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
|
std::string::size_type valuestart = istr.find_first_not_of( " \t\r\n", delimpos + 1 );
|
|
|
|
|
|
std::string::size_type valueend = istr.find_last_not_of( " \t\r\n" );
|
|
|
|
|
|
propname = istr.substr( start, delimpos - start );
|
|
|
|
|
|
if ( valuestart != std::string::npos && valueend != std::string::npos )
|
|
|
|
|
|
{
|
|
|
|
|
|
propvalue = istr.substr( valuestart, valueend - valuestart + 1 );
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
propvalue = "";
|
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
|
else
|
2016-02-11 22:54:43 +01:00
|
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
|
propname = istr.substr( start, std::string::npos );
|
|
|
|
|
|
propvalue = "";
|
2016-02-11 22:54:43 +01:00
|
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
propname = "";
|
|
|
|
|
|
propvalue = "";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
|
void decodequotedstring( std::string& str )
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string tmp;
|
|
|
|
|
|
tmp.swap( str );
|
|
|
|
|
|
const char* s = tmp.c_str();
|
|
|
|
|
|
str.reserve( tmp.size() );
|
|
|
|
|
|
++s;
|
|
|
|
|
|
while ( *s )
|
|
|
|
|
|
{
|
|
|
|
|
|
char ch = *s++;
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
|
switch ( ch )
|
|
|
|
|
|
{
|
|
|
|
|
|
case '\\':
|
|
|
|
|
|
ch = *s++;
|
|
|
|
|
|
switch ( ch )
|
|
|
|
|
|
{
|
|
|
|
|
|
case '\0':
|
|
|
|
|
|
return;
|
|
|
|
|
|
case 'n': // newline
|
|
|
|
|
|
str += "\n";
|
|
|
|
|
|
break;
|
|
|
|
|
|
default: // slash, quote, etc
|
|
|
|
|
|
str += ch;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case '\"':
|
|
|
|
|
|
return;
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
|
default:
|
|
|
|
|
|
str += ch;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void encodequotedstring( std::string& str )
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string tmp;
|
|
|
|
|
|
tmp.swap( str );
|
|
|
|
|
|
const char* s = tmp.c_str();
|
|
|
|
|
|
str.reserve( tmp.size() + 2 );
|
|
|
|
|
|
str += "\"";
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
|
while ( *s )
|
|
|
|
|
|
{
|
|
|
|
|
|
char ch = *s++;
|
|
|
|
|
|
switch ( ch )
|
|
|
|
|
|
{
|
|
|
|
|
|
case '\\':
|
|
|
|
|
|
str += "\\\\";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case '\"':
|
|
|
|
|
|
str += "\\\"";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case '\n':
|
|
|
|
|
|
str += "\\n";
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
str += ch;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
|
str += "\"";
|
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
|
std::string getencodedquotedstring( const std::string& in )
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string tmp = in;
|
|
|
|
|
|
encodequotedstring( tmp );
|
|
|
|
|
|
return tmp;
|
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
|
// If we have boost, I think we should use it...
|
2019-01-12 11:46:30 +01:00
|
|
|
|
void mklowerASCII( std::string& str )
|
2016-02-19 19:26:35 +01:00
|
|
|
|
{
|
|
|
|
|
|
boost::to_lower( str );
|
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
2019-01-12 11:46:30 +01:00
|
|
|
|
void mkupperASCII( std::string& str )
|
2016-02-19 19:26:35 +01:00
|
|
|
|
{
|
|
|
|
|
|
boost::to_upper( str );
|
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
2019-01-12 11:46:30 +01:00
|
|
|
|
std::string strlowerASCII( const std::string& str )
|
2016-02-19 19:26:35 +01:00
|
|
|
|
{
|
|
|
|
|
|
return boost::to_lower_copy( str );
|
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
2019-01-12 11:46:30 +01:00
|
|
|
|
std::string strupperASCII( const std::string& str )
|
2016-02-19 19:26:35 +01:00
|
|
|
|
{
|
|
|
|
|
|
return boost::to_upper_copy( str );
|
|
|
|
|
|
}
|
2019-01-12 11:46:30 +01:00
|
|
|
|
|
2023-02-08 21:13:48 +01:00
|
|
|
|
std::string strtrim( const std::string& str )
|
|
|
|
|
|
{
|
|
|
|
|
|
return boost::trim_copy( str );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-12 11:46:30 +01:00
|
|
|
|
bool isValidUnicode( const std::string& str )
|
|
|
|
|
|
{
|
|
|
|
|
|
return utf8::find_invalid( str.begin(), str.end() ) == str.end();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void sanitizeUnicodeWithIso( std::string* str )
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( isValidUnicode( *str ) )
|
|
|
|
|
|
return;
|
|
|
|
|
|
// assume iso8859
|
|
|
|
|
|
std::string utf8( "" );
|
|
|
|
|
|
utf8.reserve( 2 * str->size() + 1 );
|
|
|
|
|
|
|
|
|
|
|
|
for ( const auto& s : *str )
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( !( s & 0x80 ) )
|
|
|
|
|
|
{
|
|
|
|
|
|
utf8.push_back( s );
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
utf8.push_back( 0xc2 | ( (unsigned char)( s ) >> 6 ) );
|
|
|
|
|
|
utf8.push_back( 0xbf & s );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
*str = utf8;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void sanitizeUnicode( std::string* str )
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( !isValidUnicode( *str ) )
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string new_s;
|
|
|
|
|
|
utf8::replace_invalid( str->begin(), str->end(), std::back_inserter( new_s ) );
|
|
|
|
|
|
*str = new_s;
|
|
|
|
|
|
}
|
2019-08-16 19:02:53 +02:00
|
|
|
|
catch ( utf8::exception& )
|
2019-01-12 11:46:30 +01:00
|
|
|
|
{
|
|
|
|
|
|
*str = "Invalid unicode";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
auto begin = str->begin();
|
|
|
|
|
|
auto end = str->end();
|
2021-08-23 07:58:42 +02:00
|
|
|
|
auto invalid_chr = []( u32 c )
|
|
|
|
|
|
{
|
2020-01-04 12:35:04 +01:00
|
|
|
|
return ( c >= 0x1u && c < 0x9u ) /*0x9 \t 0x10 \n*/ ||
|
2020-08-29 13:46:11 +02:00
|
|
|
|
( c >= 0x11u && c < 0x13u ) /*0x13 \r*/ || ( c >= 0x14u && c < 0x20u ) || c == 0x7Fu ||
|
|
|
|
|
|
( c >= 0x80u && c <= 0x9Fu );
|
2020-01-04 12:35:04 +01:00
|
|
|
|
};
|
2019-01-12 11:46:30 +01:00
|
|
|
|
while ( begin != end )
|
|
|
|
|
|
{
|
|
|
|
|
|
auto c = utf8::unchecked::next( begin );
|
2020-01-04 12:35:04 +01:00
|
|
|
|
if ( invalid_chr( c ) )
|
2019-01-12 11:46:30 +01:00
|
|
|
|
{
|
|
|
|
|
|
// control character found build new string skipping them
|
|
|
|
|
|
std::string new_s;
|
|
|
|
|
|
begin = str->begin();
|
|
|
|
|
|
while ( begin != end )
|
|
|
|
|
|
{
|
|
|
|
|
|
c = utf8::unchecked::next( begin );
|
2020-01-04 12:35:04 +01:00
|
|
|
|
if ( invalid_chr( c ) )
|
2019-01-12 11:46:30 +01:00
|
|
|
|
continue;
|
|
|
|
|
|
utf8::unchecked::append( c, std::back_inserter( new_s ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
*str = new_s;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-08-18 19:09:15 +02:00
|
|
|
|
|
|
|
|
|
|
void remove_bom( std::string* strbuf )
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( strbuf->size() >= 3 )
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( utf8::starts_with_bom( strbuf->cbegin(), strbuf->cend() ) )
|
|
|
|
|
|
strbuf->erase( 0, 3 );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-11-02 23:00:36 +02:00
|
|
|
|
uint8_t unicodeToCp1252( uint32_t codepoint )
|
|
|
|
|
|
{
|
|
|
|
|
|
if ( codepoint >= 0x80 && codepoint <= 0x9f )
|
|
|
|
|
|
return '?';
|
|
|
|
|
|
else if ( codepoint <= 0xff )
|
|
|
|
|
|
return (char)codepoint;
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
switch ( codepoint )
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0x20AC: return 128; break; //€
|
|
|
|
|
|
case 0x201A: return 130; break; //‚
|
|
|
|
|
|
case 0x0192: return 131; break; //ƒ
|
|
|
|
|
|
case 0x201E: return 132; break; //„
|
|
|
|
|
|
case 0x2026: return 133; break; //…
|
|
|
|
|
|
case 0x2020: return 134; break; //†
|
|
|
|
|
|
case 0x2021: return 135; break; //‡
|
|
|
|
|
|
case 0x02C6: return 136; break; //ˆ
|
|
|
|
|
|
case 0x2030: return 137; break; //‰
|
|
|
|
|
|
case 0x0160: return 138; break; //Š
|
|
|
|
|
|
case 0x2039: return 139; break; //‹
|
|
|
|
|
|
case 0x0152: return 140; break; //Œ
|
|
|
|
|
|
case 0x017D: return 142; break; //Ž
|
|
|
|
|
|
case 0x2018: return 145; break; //‘
|
|
|
|
|
|
case 0x2019: return 146; break; //’
|
|
|
|
|
|
case 0x201C: return 147; break; //“
|
|
|
|
|
|
case 0x201D: return 148; break; //”
|
|
|
|
|
|
case 0x2022: return 149; break; //•
|
|
|
|
|
|
case 0x2013: return 150; break; //–
|
|
|
|
|
|
case 0x2014: return 151; break; //—
|
|
|
|
|
|
case 0x02DC: return 152; break; //˜
|
|
|
|
|
|
case 0x2122: return 153; break; //™
|
|
|
|
|
|
case 0x0161: return 154; break; //š
|
|
|
|
|
|
case 0x203A: return 155; break; //›
|
|
|
|
|
|
case 0x0153: return 156; break; //œ
|
|
|
|
|
|
case 0x017E: return 158; break; //ž
|
|
|
|
|
|
case 0x0178: return 159; break; //Ÿ
|
|
|
|
|
|
default: return '?'; break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t cp1252ToUnicode( uint8_t codepoint )
|
|
|
|
|
|
{
|
|
|
|
|
|
switch ( codepoint )
|
|
|
|
|
|
{
|
|
|
|
|
|
case 128: return 0x20AC; break; //€
|
|
|
|
|
|
case 130: return 0x201A; break; //‚
|
|
|
|
|
|
case 131: return 0x0192; break; //ƒ
|
|
|
|
|
|
case 132: return 0x201E; break; //„
|
|
|
|
|
|
case 133: return 0x2026; break; //…
|
|
|
|
|
|
case 134: return 0x2020; break; //†
|
|
|
|
|
|
case 135: return 0x2021; break; //‡
|
|
|
|
|
|
case 136: return 0x02C6; break; //ˆ
|
|
|
|
|
|
case 137: return 0x2030; break; //‰
|
|
|
|
|
|
case 138: return 0x0160; break; //Š
|
|
|
|
|
|
case 139: return 0x2039; break; //‹
|
|
|
|
|
|
case 140: return 0x0152; break; //Œ
|
|
|
|
|
|
case 142: return 0x017D; break; //Ž
|
|
|
|
|
|
case 145: return 0x2018; break; //‘
|
|
|
|
|
|
case 146: return 0x2019; break; //’
|
|
|
|
|
|
case 147: return 0x201C; break; //“
|
|
|
|
|
|
case 148: return 0x201D; break; //”
|
|
|
|
|
|
case 149: return 0x2022; break; //•
|
|
|
|
|
|
case 150: return 0x2013; break; //–
|
|
|
|
|
|
case 151: return 0x2014; break; //—
|
|
|
|
|
|
case 152: return 0x02DC; break; //˜
|
|
|
|
|
|
case 153: return 0x2122; break; //™
|
|
|
|
|
|
case 154: return 0x0161; break; //š
|
|
|
|
|
|
case 155: return 0x203A; break; //›
|
|
|
|
|
|
case 156: return 0x0153; break; //œ
|
|
|
|
|
|
case 158: return 0x017E; break; //ž
|
|
|
|
|
|
case 159: return 0x0178; break; //Ÿ
|
|
|
|
|
|
default: return codepoint; break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string strUtf8ToCp1252( const std::string &utf8string )
|
|
|
|
|
|
{
|
|
|
|
|
|
auto itr = utf8string.begin();
|
|
|
|
|
|
auto end = utf8string.end();
|
|
|
|
|
|
std::string outstring;
|
|
|
|
|
|
while( itr != end )
|
|
|
|
|
|
{
|
|
|
|
|
|
auto c = unicodeToCp1252( utf8::unchecked::next( itr ) );
|
|
|
|
|
|
outstring.push_back( c );
|
|
|
|
|
|
}
|
|
|
|
|
|
return outstring;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string strCp1252ToUtf8( const std::string &cp1252string )
|
|
|
|
|
|
{
|
|
|
|
|
|
auto itr = cp1252string.begin();
|
|
|
|
|
|
auto end = cp1252string.end();
|
|
|
|
|
|
std::string outstring;
|
|
|
|
|
|
auto inserter = std::back_inserter(outstring);
|
|
|
|
|
|
while( itr != end )
|
|
|
|
|
|
{
|
|
|
|
|
|
utf8::unchecked::append(cp1252ToUnicode(*itr++), inserter);
|
|
|
|
|
|
}
|
|
|
|
|
|
return outstring;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-10-24 21:42:36 +02:00
|
|
|
|
} // namespace Clib
|
|
|
|
|
|
} // namespace Pol
|