793 lines
22 KiB
C++
793 lines
22 KiB
C++
//
|
|
// File: nsl.h
|
|
//
|
|
// Contents: wrapper of iconv unicode library and some other utility
|
|
//
|
|
// Functions: nsl::split
|
|
// nsl::replace
|
|
// nsl::toupper
|
|
// nsl::tolower
|
|
// nsl::wildcmp
|
|
// nsl::sprintf_str
|
|
// nsl::format
|
|
// nsl::itos<>
|
|
// nsl::itos
|
|
// nsl::itosw
|
|
// nsl::insert_comma<>
|
|
// nsl::insert_comma
|
|
// nsl::insert_commaw
|
|
//
|
|
// nsl::path::get_path_separator
|
|
// nsl::path::get_file_name
|
|
// nsl::path::get_directory_name
|
|
// nsl::path::get_extension
|
|
// nsl::path::trim_extension
|
|
// nsl::path::get_file_name_without_extension
|
|
// nsl::path::normalize
|
|
// nsl::path::join
|
|
//
|
|
// Author: Kang, KiHyun ( testors@nflavor.com )
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <cstdarg>
|
|
#include <locale>
|
|
#include <vector>
|
|
|
|
#include "safe_function.h"
|
|
|
|
namespace nl
|
|
{
|
|
namespace str
|
|
{
|
|
template< typename _Elem >
|
|
inline void sprintf_str( std::basic_string< _Elem > & str, const _Elem* fmt, ... )
|
|
{
|
|
_Elem buf[128];
|
|
va_list args;
|
|
va_start( args, fmt );
|
|
|
|
_Elem* p = buf;
|
|
size_t buf_len = sizeof(buf)/sizeof(_Elem);
|
|
|
|
while ( -1 == s_vsprintf( p, buf_len, fmt, args ) )
|
|
{
|
|
if ( p != buf ) delete [] p;
|
|
|
|
buf_len *= 2;
|
|
|
|
p = new _Elem[ buf_len ];
|
|
}
|
|
|
|
str = p;
|
|
|
|
if ( p != buf ) delete [] p;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > format( const _Elem* fmt, ... )
|
|
{
|
|
_Elem buf[128];
|
|
va_list args;
|
|
va_start( args, fmt );
|
|
|
|
_Elem* p = buf;
|
|
size_t buf_len = sizeof(buf)/sizeof(_Elem);
|
|
|
|
while ( -1 == s_vsprintf( p, buf_len, fmt, args ) )
|
|
{
|
|
if ( p != buf ) delete [] p;
|
|
|
|
buf_len *= 2;
|
|
|
|
p = new _Elem[ buf_len ];
|
|
}
|
|
|
|
std::basic_string< _Elem > strTemp = p;
|
|
|
|
if ( p != buf ) delete [] p;
|
|
|
|
return strTemp;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > itos( int n ) { assert( 0 ); return ""; }
|
|
template<> inline std::basic_string< char > itos< char >( int n ) { return nl::str::format( "%d", n ); }
|
|
template<> inline std::basic_string< wchar_t > itos< wchar_t >( int n ) { return nl::str::format( L"%d", n ); }
|
|
inline std::string itos( int n ) { return nl::str::format( "%d", n ); }
|
|
inline std::wstring itosw( int n ) { return nl::str::format( L"%d", n ); }
|
|
|
|
template< typename _Elem >
|
|
inline size_t replace( std::basic_string< _Elem >& str, const _Elem* from, size_t from_len, const _Elem* to, size_t to_len, size_t max_cnt = 0xffffffff )
|
|
{
|
|
size_t cnt = 0;
|
|
size_t nPos = 0;
|
|
|
|
while ( true )
|
|
{
|
|
if ( cnt >= max_cnt ) break;
|
|
|
|
nPos = str.find( from, nPos );
|
|
if ( nPos == std::string::npos ) break;
|
|
|
|
str.replace( nPos, from_len, to );
|
|
nPos += to_len;
|
|
|
|
cnt++;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline size_t replace( std::basic_string< _Elem >& str, const _Elem* from, const _Elem* to, size_t max_cnt = 0xffffffff )
|
|
{
|
|
size_t from_len = 0;
|
|
size_t to_len = 0;
|
|
|
|
const _Elem* p;
|
|
|
|
p = from;
|
|
while ( *++p ) ;
|
|
from_len = p - from;
|
|
|
|
p = to;
|
|
while ( *++p ) ;
|
|
to_len = p - to;
|
|
|
|
return replace( str, from, from_len, to, to_len, max_cnt );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline size_t strlen( const _Elem* str )
|
|
{
|
|
size_t len = 0;
|
|
while ( *str )
|
|
{
|
|
++len;
|
|
++str;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
template< typename _Elem, typename _INTEGER >
|
|
inline std::basic_string< _Elem > itoa( _INTEGER in )
|
|
{
|
|
_INTEGER n = in;
|
|
if ( n < 0 ) n = 0 - n;
|
|
|
|
std::basic_string< _Elem > str;
|
|
|
|
do
|
|
{
|
|
str.insert( 0, 1, (_Elem)( '0' + ( n % 10 ) ) );
|
|
n /= 10;
|
|
} while ( n );
|
|
|
|
if ( in < 0 ) str.insert( 0, 1, '-' );
|
|
|
|
return str;
|
|
}
|
|
|
|
template< typename _Elem, typename _INTEGER >
|
|
inline _INTEGER atoi( const _Elem* str )
|
|
{
|
|
bool bIsMinus = false;
|
|
|
|
if ( str[0] == '-' )
|
|
{
|
|
bIsMinus = true;
|
|
++str;
|
|
}
|
|
|
|
if ( str[0] == '+' ) ++str;
|
|
|
|
size_t len = strlen( str );
|
|
if ( len <= 0 ) return static_cast< _INTEGER >( 0 );
|
|
|
|
const _Elem* back = ( str + len - 1 );
|
|
_INTEGER nResult = static_cast< _INTEGER >( 0 );
|
|
_INTEGER nCur = static_cast< _INTEGER >( 1 );
|
|
|
|
while ( back >= str )
|
|
{
|
|
if ( *back > '9' || *back < '0' ) break;
|
|
nResult = static_cast< _INTEGER >( nResult + ( *back - '0' ) * nCur );
|
|
nCur = static_cast< _INTEGER >( nCur * 10 );
|
|
--back;
|
|
}
|
|
|
|
//bIsMinus 체크
|
|
return bIsMinus ? 0-nResult:nResult;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline size_t replace( std::basic_string< _Elem >& str, const std::basic_string< _Elem >& from, const std::basic_string< _Elem >& to, size_t max_cnt = 0xffffffff )
|
|
{
|
|
return replace( str, from.c_str(), from.size(), to.c_str(), to.size(), max_cnt );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline void toupper( std::basic_string< _Elem >& str )
|
|
{
|
|
for ( std::basic_string< _Elem >::iterator it = str.begin(); it != str.end(); ++it )
|
|
{
|
|
if ( *it >= 'a' && *it <= 'z' ) *it = *it - ('a' - 'A');
|
|
}
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline void tolower( std::basic_string< _Elem >& str )
|
|
{
|
|
for ( std::basic_string< _Elem >::iterator it = str.begin(); it != str.end(); ++it )
|
|
{
|
|
if ( *it >= 'A' && *it <= 'Z' ) *it = *it + ('a' - 'A');
|
|
}
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline bool isEqual( _Elem ch, _Elem pattern, bool ignore_case )
|
|
{
|
|
if ( ignore_case )
|
|
{
|
|
if ( ch >= 'A' && ch <= 'Z' ) ch -= ( 'A' - 'a' );
|
|
if ( pattern >= 'A' && pattern <= 'Z' ) pattern -= ( 'A' - 'a' );
|
|
}
|
|
|
|
return ( pattern == ch || pattern == '?' );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
bool wildcmp( const _Elem* pattern, const _Elem* str, bool ignore_case = false )
|
|
{
|
|
if ( !pattern || pattern[0] == '\0' ) return true;
|
|
|
|
if ( pattern[0] == '*' && pattern[1] == '\0' ) return true;
|
|
|
|
const _Elem* cp = 0,* mp = 0;
|
|
|
|
while ( (*str) && (*pattern != '*') )
|
|
{
|
|
if ( !isEqual( *str, *pattern, ignore_case ) ) return 0;
|
|
|
|
pattern++;
|
|
str++;
|
|
}
|
|
|
|
while ( *str )
|
|
{
|
|
if ( *pattern == '*' )
|
|
{
|
|
if ( !*++pattern ) return 1;
|
|
|
|
mp = pattern;
|
|
cp = str+1;
|
|
}
|
|
else if ( isEqual( *str, *pattern, ignore_case ) )
|
|
{
|
|
pattern++;
|
|
str++;
|
|
}
|
|
else
|
|
{
|
|
pattern = mp;
|
|
str = cp++;
|
|
}
|
|
}
|
|
|
|
while ( *pattern == '*' )
|
|
{
|
|
pattern++;
|
|
}
|
|
|
|
return !*pattern;
|
|
}
|
|
|
|
template< typename _Elem > bool wildcmp( const _Elem* pattern, const std::basic_string<_Elem >& str, bool ignore_case = false ) { return wildcmp( pattern, str.c_str(), ignore_case ); }
|
|
template< typename _Elem > bool wildcmp( const std::basic_string< _Elem >& pattern, const std::basic_string<_Elem >& str, bool ignore_case = false ) { return wildcmp( pattern.c_str(), str.c_str(), ignore_case ); }
|
|
template< typename _Elem > bool wildcmp( const std::basic_string< _Elem >& pattern, const _Elem* str, bool ignore_case = false ) { return wildcmp( pattern.c_str(), str, ignore_case ); }
|
|
|
|
template< typename _Elem >
|
|
inline bool is_delimiter( _Elem _c, const _Elem* delimiter )
|
|
{
|
|
_Elem* c = const_cast< _Elem* >( delimiter );
|
|
while ( *c )
|
|
{
|
|
if ( *c == _c ) return true;
|
|
++c;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template< typename _Elem, typename _Container >
|
|
inline void split_with_string( const _Elem* pszCommand, _Container& vToken, const _Elem* pSeparatorString, bool bAllowBlankString = false )
|
|
{
|
|
if ( !pszCommand ) return;
|
|
|
|
const char *p = pszCommand;
|
|
|
|
std::string strTemp;
|
|
size_t separator_len = strlen( pSeparatorString );
|
|
|
|
while( *p )
|
|
{
|
|
if( strncmp( p, pSeparatorString, separator_len ) == 0 )
|
|
{
|
|
if( bAllowBlankString || !strTemp.empty() )
|
|
{
|
|
vToken.push_back( strTemp );
|
|
}
|
|
p += separator_len;
|
|
strTemp.clear();
|
|
continue;
|
|
}
|
|
|
|
strTemp.append( 1, *p );
|
|
++p;
|
|
}
|
|
|
|
if( bAllowBlankString || !strTemp.empty() )
|
|
{
|
|
vToken.push_back( strTemp );
|
|
}
|
|
}
|
|
|
|
template< typename _Elem, typename _Container >
|
|
inline void split( const _Elem* pszCommand, _Container& vToken, const _Elem* pDelimiterList, bool bProcSpecialCharacter = true, bool bAllowBlankString = false )
|
|
{
|
|
if ( !pszCommand ) return;
|
|
|
|
std::basic_string< _Elem > strTmp;
|
|
|
|
bool bBackSlash = false;
|
|
bool bQuotationMark = false;
|
|
|
|
//_Elem newCmd[512];
|
|
_Elem* pszCmd = const_cast< _Elem* >( pszCommand );
|
|
unsigned len = (unsigned)strlen(pszCmd)+1;
|
|
|
|
for ( unsigned i = 0 ; i < len ; i++ )
|
|
{
|
|
// { 역슬래쉬 처리
|
|
if ( !bBackSlash && pszCmd[i] == '\\' && bProcSpecialCharacter ) {
|
|
bBackSlash = true;
|
|
continue;
|
|
}
|
|
// }
|
|
|
|
if ( !bBackSlash ) {
|
|
if ( ( pszCmd[i] == '\"' && bProcSpecialCharacter ) || // 따옴표가 나왔거나
|
|
( !bQuotationMark && (is_delimiter(pszCmd[i], pDelimiterList) ) ) || // 스페이스로 파싱중일때 스페이스가 나왔거나
|
|
( pszCmd[i] == '\0' ) ) // 문장의 끝일경우
|
|
|
|
|
|
{
|
|
if ( pszCmd[i] == '\"' )
|
|
{
|
|
bQuotationMark ^= true; // 따옴표가 나오면 토글
|
|
if (bQuotationMark) continue;
|
|
}
|
|
|
|
// 구문 저장
|
|
if ( strTmp.size() || bAllowBlankString ) vToken.push_back( strTmp );
|
|
strTmp.erase( strTmp.begin(), strTmp.end() );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
strTmp += pszCmd[i];
|
|
bBackSlash = false;
|
|
}
|
|
}
|
|
|
|
// 2010.04.14 bintitle
|
|
// 기존 split() 함수에서는 공백문자를 무시하므로 추가.
|
|
template< typename _Elem, typename _Container >
|
|
inline void split_Ex( const _Elem* pszCommand, _Container& vToken, const _Elem* pDelimiterList, bool bProcSpecialCharacter = true, bool bAllowBlankString = false )
|
|
{
|
|
if ( !pszCommand ) return;
|
|
|
|
std::basic_string< _Elem > strTmp;
|
|
|
|
bool bBackSlash = false;
|
|
bool bQuotationMark = false;
|
|
|
|
//_Elem newCmd[512];
|
|
_Elem* pszCmd = const_cast< _Elem* >( pszCommand );
|
|
unsigned len = (unsigned)strlen(pszCmd)+1;
|
|
|
|
for ( unsigned i = 0 ; i < len ; i++ )
|
|
{
|
|
// { 역슬래쉬 처리
|
|
if ( !bBackSlash && pszCmd[i] == '\\' && bProcSpecialCharacter ) {
|
|
bBackSlash = true;
|
|
continue;
|
|
}
|
|
// }
|
|
|
|
if ( !bBackSlash ) {
|
|
if ( ( pszCmd[i] == '\"' && bProcSpecialCharacter ) || // 따옴표가 나왔거나
|
|
( !bQuotationMark && (is_delimiter(pszCmd[i], pDelimiterList) ) ) || // 스페이스로 파싱중일때 스페이스가 나왔거나
|
|
( pszCmd[i] == '\0' ) ) // 문장의 끝일경우
|
|
|
|
|
|
{
|
|
if ( pszCmd[i] == '\"' )
|
|
{
|
|
bQuotationMark ^= true; // 따옴표가 나오면 토글
|
|
if (bQuotationMark) continue;
|
|
}
|
|
|
|
// 수정 2010.04.14 bintitle.
|
|
// 기존 코드는 공백 토큰을 무시하고있다.
|
|
// 공백토큰도 vToken 배열에 추가하도록 수정.
|
|
vToken.push_back( strTmp );
|
|
strTmp.erase( strTmp.begin(), strTmp.end() );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
strTmp += pszCmd[i];
|
|
bBackSlash = false;
|
|
}
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::vector< std::basic_string< _Elem > > split( const _Elem* pszCommand, const _Elem* pDelimiterList, bool bProcSpecialCharacter = true, bool bAllowBlankString = false )
|
|
{
|
|
std::vector< std::basic_string< _Elem > > tmp;
|
|
split( pszCommand, tmp, pDelimiterList, bProcSpecialCharacter, bAllowBlankString );
|
|
return tmp;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::vector< std::basic_string< _Elem > > split_Ex( const _Elem* pszCommand, const _Elem* pDelimiterList, bool bProcSpecialCharacter = true, bool bAllowBlankString = false )
|
|
{
|
|
std::vector< std::basic_string< _Elem > > tmp;
|
|
split_Ex( pszCommand, tmp, pDelimiterList, bProcSpecialCharacter, bAllowBlankString );
|
|
return tmp;
|
|
}
|
|
|
|
inline std::string insert_comma( int nValue )
|
|
{
|
|
const int c_nCommaGap = 3;
|
|
|
|
std::string strNum = itos< char >( nValue );
|
|
std::string strCommaNum;
|
|
|
|
int nCount( 0 );
|
|
int nCommaPos = int(strNum.size()) % c_nCommaGap;
|
|
|
|
for ( std::string::iterator it = strNum.begin(); it != strNum.end(); ++it, ++nCount )
|
|
{
|
|
if ( it != strNum.begin() && nCommaPos == (nCount % c_nCommaGap) )
|
|
strCommaNum.push_back( ',' );
|
|
|
|
strCommaNum.push_back( (*it) );
|
|
}
|
|
return strCommaNum;
|
|
}
|
|
|
|
inline std::wstring insert_commaw( int nValue )
|
|
{
|
|
const int c_nCommaGap = 3;
|
|
|
|
std::wstring strNum = itosw( nValue );
|
|
std::wstring strCommaNum;
|
|
|
|
int nCount( 0 );
|
|
int nCommaPos = int(strNum.size()) % c_nCommaGap;
|
|
|
|
for ( std::wstring::iterator it = strNum.begin(); it != strNum.end(); ++it, ++nCount )
|
|
{
|
|
if ( it != strNum.begin() && nCommaPos == (nCount % c_nCommaGap) )
|
|
strCommaNum.push_back( ',' );
|
|
|
|
strCommaNum.push_back( (*it) );
|
|
}
|
|
return strCommaNum;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > insert_comma( int nValue ) { return insert_comma( nValue ); }
|
|
template<> inline std::basic_string< char > insert_comma( int nValue ) { return insert_comma( nValue ); }
|
|
template<> inline std::basic_string< wchar_t > insert_comma( int nValue ) { return insert_commaw( nValue ); }
|
|
|
|
namespace path
|
|
{
|
|
inline char get_path_separator() { return '/'; }
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > get_file_name( const std::basic_string< _Elem >& path, char path_separator = get_path_separator() )
|
|
{
|
|
size_t pos = path.rfind( path_separator );
|
|
if ( pos == path.npos ) return path;
|
|
|
|
std::basic_string< _Elem > file_name( path.begin() + pos + 1, path.end() );
|
|
return file_name;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > get_file_name( const _Elem* path )
|
|
{
|
|
return get_file_name( std::basic_string< _Elem >( path ) );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > get_directory_name( const std::basic_string< _Elem >& path, char path_separator = get_path_separator() )
|
|
{
|
|
size_t pos = path.rfind( path_separator );
|
|
if ( pos == path.npos ) return path;
|
|
|
|
std::basic_string< _Elem > file_name( path.begin(), path.begin() + pos );
|
|
return file_name;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > get_directory_name( const _Elem* path )
|
|
{
|
|
return get_directory_name( std::basic_string< _Elem >( path ) );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > get_extension( const std::basic_string< _Elem >& path, char path_separator = get_path_separator() )
|
|
{
|
|
std::basic_string< _Elem > temp;
|
|
size_t bpos = path.rfind( path_separator );
|
|
if ( bpos == path.npos ) temp = path;
|
|
else temp.assign( path.begin() + bpos, path.end() );
|
|
|
|
size_t pos = temp.rfind( '.' );
|
|
if ( pos == temp.npos ) return "";
|
|
|
|
std::basic_string< _Elem > extension( temp.begin() + pos, temp.end() );
|
|
return extension;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > get_extension( const _Elem* path )
|
|
{
|
|
return get_extension( std::basic_string< _Elem >( path ) );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > trim_extension( const std::basic_string< _Elem >& path )
|
|
{
|
|
std::basic_string< _Elem > extension = get_extension( path );
|
|
|
|
std::basic_string< _Elem > new_path( path.begin(), path.end() - extension.size() );
|
|
return new_path;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > get_file_name_without_extension( const std::basic_string< _Elem >& path )
|
|
{
|
|
return get_file_name( trim_extension( path ) );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline void normalize_( std::basic_string< _Elem >& path, _Elem path_separator = get_path_separator() )
|
|
{
|
|
_Elem sep[2] = { '/', 0 };
|
|
_Elem to[2] = { path_separator, 0 };
|
|
|
|
if ( path_separator == '/' ) sep[0] = '\\';
|
|
|
|
nsl::replace( path, sep, to );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > normalize( const std::basic_string< _Elem >& path )
|
|
{
|
|
std::basic_string< _Elem > tmp = path;
|
|
normalize_( tmp );
|
|
return tmp;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > normalize( const _Elem* path, _Elem path_separator = get_path_separator() )
|
|
{
|
|
std::basic_string< _Elem > tmp = path;
|
|
normalize_( tmp, path_separator );
|
|
return tmp;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > join( const std::basic_string< _Elem >& p1, const std::basic_string< _Elem >& p2 )
|
|
{
|
|
int path_separator = get_path_separator();
|
|
|
|
if ( p1.empty() ) return p2;
|
|
if ( p2.empty() ) return p1;
|
|
|
|
bool bP1 = ( p1[ p1.size() - 1 ] == path_separator );
|
|
bool bP2 = ( p2[ 0 ] == path_separator );
|
|
|
|
std::basic_string< _Elem > temp( p1 );
|
|
|
|
if ( bP1 && bP2 )
|
|
{
|
|
temp.erase( temp.end() - 1, temp.end() );
|
|
temp.insert( temp.end(), p2.begin(), p2.end() );
|
|
return temp;
|
|
}
|
|
|
|
if ( !bP1 && !bP2 ) temp += '/';
|
|
|
|
temp += p2;
|
|
|
|
return normalize( temp );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > join( const _Elem * p1, const _Elem * p2 )
|
|
{
|
|
return join( std::basic_string< _Elem >( p1 ), std::basic_string< _Elem >( p2 ) );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > join( const std::basic_string< _Elem >& p1, const std::basic_string< _Elem >& p2, const std::basic_string< _Elem >& p3 )
|
|
{
|
|
return join( join( p1, p2 ), p3 );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > join( const _Elem * p1, const _Elem * p2, const _Elem * p3 )
|
|
{
|
|
return join( std::basic_string< _Elem >( p1 ), std::basic_string< _Elem >( p2 ), std::basic_string< _Elem >( p3 ) );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > join( const std::basic_string< _Elem >& p1, const std::basic_string< _Elem >& p2, const std::basic_string< _Elem >& p3, const std::basic_string< _Elem >& p4 )
|
|
{
|
|
return join( join( p1, p2, p3 ), p4 );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline std::basic_string< _Elem > join( const _Elem * p1, const _Elem * p2, const _Elem * p3, const _Elem * p4 )
|
|
{
|
|
return join( std::basic_string< _Elem >( p1 ), std::basic_string< _Elem >( p2 ), std::basic_string< _Elem >( p3 ), std::basic_string< _Elem >( p4 ) );
|
|
}
|
|
};
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// pointer out-parameter version. deprecated for inline inefficiency - by Tyburn
|
|
|
|
|
|
namespace nl
|
|
{
|
|
namespace str
|
|
{
|
|
template< typename _Elem >
|
|
inline void sprintf_str( std::basic_string< _Elem > * str, const _Elem* fmt, ... )
|
|
{
|
|
_Elem buf[128];
|
|
va_list args;
|
|
va_start( args, fmt );
|
|
|
|
_Elem* p = buf;
|
|
size_t buf_len = sizeof(buf)/sizeof(_Elem);
|
|
|
|
while ( -1 == s_vsprintf( p, buf_len, fmt, args ) )
|
|
{
|
|
if ( p != buf ) delete [] p;
|
|
|
|
buf_len *= 2;
|
|
|
|
p = new _Elem[ buf_len ];
|
|
}
|
|
|
|
*str = p;
|
|
|
|
if ( p != buf ) delete [] p;
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline size_t replace( std::basic_string< _Elem >* str, const _Elem* from, size_t from_len, const _Elem* to, size_t to_len, size_t max_cnt = 0xffffffff )
|
|
{
|
|
return replace( *str, from, from_len, to, to_len, max_cnt );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline size_t replace( std::basic_string< _Elem >* str, const _Elem* from, const _Elem* to, size_t max_cnt = 0xffffffff )
|
|
{
|
|
return replace( *str, from, to, max_cnt );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline size_t replace( std::basic_string< _Elem >* str, const std::basic_string< _Elem >& from, const std::basic_string< _Elem >& to, size_t max_cnt = 0xffffffff )
|
|
{
|
|
return replace( str, from.c_str(), from.size(), to.c_str(), to.size(), max_cnt );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline void toupper( std::basic_string< _Elem >* str )
|
|
{
|
|
toupper( *str );
|
|
}
|
|
|
|
template< typename _Elem >
|
|
inline void tolower( std::basic_string< _Elem >* str )
|
|
{
|
|
tolower( *str );
|
|
}
|
|
|
|
template< typename _Elem, typename _Container >
|
|
inline void split( const _Elem* pszCommand, _Container* vToken, const _Elem* pDelimiterList, bool bProcSpecialCharacter = true, bool bAllowBlankString = false )
|
|
{
|
|
split( pszCommand, *vToken, pDelimiterList, bProcSpecialCharacter, bAllowBlankString );
|
|
}
|
|
|
|
template< typename _Elem, typename _Container >
|
|
inline void split_with_string( const _Elem* pszCommand, _Container* vToken, const _Elem* pSeparatorString, bool bAllowBlankString = false )
|
|
{
|
|
split_with_string( pszCommand, *vToken, pSeparatorString, bAllowBlankString );
|
|
}
|
|
|
|
namespace path
|
|
{
|
|
template< typename _Elem >
|
|
inline void normalize( std::basic_string< _Elem >* path, char path_separator = get_path_separator() )
|
|
{
|
|
normalize_( *path, path_separator );
|
|
}
|
|
};
|
|
|
|
template< typename _Elem >
|
|
void url_encode( std::basic_string< _Elem > *pString )
|
|
{
|
|
for( size_t i = 0; i < pString->size(); ++i )
|
|
{
|
|
bool bEncode = false;
|
|
|
|
int nChar = (*pString)[i];
|
|
|
|
// ASCII Control characters
|
|
if( ( nChar >= 0x00 && nChar <= 0x1F ) || ( nChar == 0x7F ) ) bEncode = true;
|
|
|
|
// Non-ASCII characters
|
|
else if( nChar >= 0x80 && nChar <= 0xFF ) bEncode = true;
|
|
|
|
// Resserved characters
|
|
else if( ( nChar == 0x24 ) || ( nChar == 0x26 ) ||
|
|
( nChar == 0x2B ) || ( nChar == 0x2C ) ||
|
|
( nChar == 0x2F ) || ( nChar == 0x3A ) ||
|
|
( nChar == 0x3B ) || ( nChar == 0x3D ) ||
|
|
( nChar == 0x3F ) || ( nChar == 0x40 ) ) bEncode = true;
|
|
|
|
// Unsafe characters
|
|
else if( ( nChar == 0x20 ) || ( nChar == 0x22 ) ||
|
|
( nChar == 0x3C ) || ( nChar == 0x3E ) ||
|
|
( nChar == 0x23 ) || ( nChar == 0x25 ) ) bEncode = true;
|
|
|
|
// Misc
|
|
else if( ( nChar == 0x7B ) || ( nChar == 0x7D ) ||
|
|
( nChar == 0x7C ) || ( nChar == 0x5C ) ||
|
|
( nChar == 0x5E ) || ( nChar == 0x7E ) ||
|
|
( nChar == 0x5B ) || ( nChar == 0x5D ) ||
|
|
( nChar == 0x60 ) ) bEncode = true;
|
|
|
|
if( bEncode )
|
|
{
|
|
(*pString)[i++] = '%';
|
|
int nHigh = nChar / 16;
|
|
int nLow = nChar % 16;
|
|
nHigh = nHigh > 9 ? 'A' + nHigh - 10 : '0' + nHigh;
|
|
nLow = nLow > 9 ? 'A' + nLow - 10 : '0' + nLow;
|
|
pString->insert( i++, 1, nHigh );
|
|
pString->insert( i, 1, nLow );
|
|
}
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
namespace nsl { using namespace nl::str; };
|