StringUtils Source

/*
StringUtil - Created by Mathias Svensson (C) Copyright 2010 ( http://result42.com/projects/StringUtil )

History


v1.0 2009-05-02 First Version
v1.1 2010-11-20 Added GetSubString(...)

All rights reserved.

Copyright / Usage Details:

You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise)
as long as this header is kept intact.

*/

#ifndef __STRINGUTILS_H_
#define __STRINGUTILS_H_
#pragma once

#include <vector>
#include <string>

#ifndef STL_STD
#define STL_STD std::
#endif

#ifndef STL_VECTOR
#define STL_VECTOR STL_STD vector
#endif

#ifndef STL_string
#define STL_string STL_STD string
#endif

#ifndef STL_wstring
#define STL_wstring STL_STD wstring
#endif

#ifndef ZSTLDEF_H_
#ifdef _UNICODE
typedef STL_wstring STLString;
#else
typedef STL_string STLString;
#endif
#endif

template<class T, class chartype = _TCHAR>
class StringUtil
{
public:

static void ReplaceSubstrings(T& str, const T& findStr, const T& replaceWith)
{
T::size_type pos = 0;
while((pos = str.find(findStr, pos)) != T::npos)
{
str.replace(pos, findStr.length(), replaceWith);
pos += replaceWith.length();
}
}

static void ReplaceSubstring(T& str, const T& findStr, const T& replaceWith)
{
T::size_type pos = str.find(findStr, 0);
if(pos != T::npos)
str.replace(pos, findStr.length(), replaceWith);
}

static bool SplitString(const T& input, TCHAR delimiter , T& part1, T& part2 )
{
T::size_type pos = input.find_first_of(delimiter);
if( pos == T::npos )
return false;

part1 = input.substr( 0 , pos );
part2 = input.substr( pos+1 );
return true;
}

static int SplitString(const T& input, const T& delimiter, STL_VECTOR<T>& results)
{
size_t iPos = 0;
size_t newPos = (size_t)-1; size_t sizeS2 = delimiter.size();
size_t isize = input.size();

STL_VECTOR<unsigned int> positions;

newPos = input.find(delimiter, 0);

if( newPos < 0 )
{
return 0;
}

if(newPos == T::npos)
{
if(input.empty())
return 0;

// only 1 item
results.push_back(input);
return 1;
}

int numFound = 0;

while( newPos > iPos || newPos == 0) // newPos can be 0 if there is a delimiter at first position'
{
numFound++;
positions.push_back((unsigned int)newPos);
iPos = newPos;
newPos = input.find(delimiter, iPos+sizeS2+1);
}

for( DWORD i=0; i < positions.size(); i++ )
{
T s;
if( i == 0 )
{
s = input.substr(i, positions[i]);
}
else
{
size_t offset = positions[i-1] + sizeS2;

if( offset < isize )
{
if( i == positions.size() )
{
s = input.substr(offset);
}
else if( i > 0 )
{
s = input.substr( positions[i-1] + sizeS2, positions[i] - positions[i-1] - sizeS2 );
}
}
}
if( s.size() > 0 )
{
results.push_back(s);
}
}
return numFound;
}


static T& ToLower(T& str)
{
STL_STD transform(str.begin(), str.end(), str.begin(), tolower);
return str;
}

static T& ToUpper(T& str)
{
STL_STD transform(str.begin(), str.end(), str.begin(), toupper);
return str;
}

static void TrimLeft(T& str, const chartype* whitespace)
{
T::size_type pos = str.find_first_not_of(whitespace);
if(pos != T::npos)
{
str.erase(0, pos);
}
}
static void TrimRight(T& str, const chartype* whitespace)
{
T::size_type pos = str.find_last_not_of(whitespace);
if(pos != T::npos)
{
str.erase(pos + 1);
}
else
str.erase(str.begin(), str.end());
}

static void Trim(T& str, const chartype* whitespace)
{
T::size_type pos = str.find_last_not_of(whitespace);
if(pos != T::npos)
{
str.erase(pos + 1);
pos = str.find_first_not_of(whitespace);
if(pos != T::npos)
{
str.erase(0, pos);
}
}
else
{
str.erase(str.begin(), str.end());
}
}
static T Format(const chartype* strFormat, ... )
{
chartype str[2048];
if( strFormat == NULL )
return ReturnEmpty(strFormat);

va_list vaList;
va_start( vaList , strFormat );

int nRetVal = h_snprintf(str, 2048, strFormat, vaList);

va_end( vaList );

if( nRetVal == -1 )
return ReturnEmpty(strFormat);

return str;
}

// remove
static bool FormatString( T& string, const chartype* strFormat, ... )
{
chartype str[2048];
if( strFormat == NULL )
return false;

va_list vaList;
va_start( vaList , strFormat );

int nRetVal = h_snprintf(str, 2048, strFormat, vaList);

va_end( vaList );

if( nRetVal == -1 )
return false;

string = str;
return true;
}

static T& PathAppend(T& str, const T& strNewPart)
{
AddTrailingSlash(str).append(strNewPart);
return str;
}

// will check if only \ already exists
static T& AddTrailingSlash(T& str)
{
if( str.length() > 0 && str[ str.length() -1 ] != '\\' )
str.append( _T("\\") );

return str;
}

// will check if both \ and / exists before
static T& AddTrailingSlash2(T& str)
{
if( str.length() > 0 && str[ str.length() -1 ] != '\\' && str[str.size()-1] != '/')
str.append( _T("\\") );

return str;
}

static T& RemoveTrailingSlash(T& str, chartype ch = '\\')
{
if( str[ str.length() -1 ] == ch )
str.erase(str.length() -1);

return str;
}

static T& ReplaceFileExtension(T& filename, const T& newExtension)
{
T::size_type pos = filename.find_last_of('.');
if(pos == T::npos)
return filename;

// makesure that the '.' is AFTER the last \\ .
T::size_type pos2 = filename.find_last_of('\\');
if(pos2 != T::npos)
{
if(pos2 > pos)
return filename;
}

filename.erase(pos);
filename += newExtension;
return filename;
}

static bool StripBasePath(T& path, const T& basePath)
{
if(h_csnicmp(path.c_str(), basePath.c_str(), basePath.length()) == 0)
{
path = path.substr(basePath.length());
return true;
}
return false;
}

//
// Remove everything after a specified character.
//
// T s = "Part on Part Two";
// StringUtils::RemoveAfterFirst(s, '-');
// s == "Part one ";
//
static T& RemoveAfterFirst(T& str, const chartype ch = '\\')
{
T::size_type pos = str.find_first_of(ch);
if(pos != T::npos)
{
str = str.substr(0,pos);
}
return str;
}
static T& RemoveBeforeFirst(T& str, const chartype ch = '\\')
{
T::size_type pos = str.find_first_of(ch);
if(pos != T::npos)
{
str = str.substr(pos+1);
}
return str;
}

static bool GetLine(T& str, const chartype** ppData)
{
const chartype* pData = *ppData;

if( *pData == '\0' )
return false;

// find End of line / End of data
while( *pData != '\n' && *pData != '\r' && *pData != '\0' )
pData++;

INT_PTR nCharLen = (pData - *ppData);

chartype strTmp[1024];
ASSERT(nCharLen < 1024);

nCharLen = min(nCharLen, _countof(strTmp));
CopyMemory(strTmp, *ppData, nCharLen*sizeof(chartype));
strTmp[nCharLen] = '\0';
str = strTmp;

// pData is pointing at the \n or \r or \0.
if(*pData != '\0')
{
if(*pData == '\r' && *(pData+1) == '\n')
pData += 2;
else if(*pData == '\n')
pData++;
}

*ppData = pData;
return true;
}

// Get a substring that is located between a begin and end tag.
//
// Example
// std::string str = "My name is : #{TAG.NAME}";
// std::string txt = StringUtilsA::GetSubString(str, "#{", "}");
// txt == "TAG.NAME"
//
static T GetSubString(const T& str, const chartype* beginPart, const chartype* endPart)
{
T emptyResult;
T::size_type posBegin = str.find_first_of(beginPart);
if(posBegin == T::npos)
return emptyResult;

// we need posBegin to point at the position after the beginPart.
posBegin += h_cslen(beginPart);

T::size_type posEnd = str.find_first_of(endPart, posBegin+1);
if(posEnd == T::npos)
return emptyResult;

return str.substr(posBegin, posEnd-posBegin);
}

//////////////////////////////////////////////////////////////////////////
// Helpers functions
//////////////////////////////////////////////////////////////////////////
// helper to be able to get the strnicmp or wcsnicmp.
static int h_csnicmp(const char* sz1, const char* sz2, size_t len)
{
return strnicmp(sz1, sz2, len);
}

static int h_csnicmp(const wchar_t* sz1, const wchar_t* sz2, size_t len)
{
return _wcsnicmp(sz1, sz2, len);
}

// helper to be able to get the correct version of strlen or wcslen
static size_t h_cslen(const char* sz)
{
return strlen(sz);
}

static size_t h_cslen(const wchar_t* sz)
{
return wcslen(sz);
}

// helper to be able to get the correct version of _vsnprintf or _vsnwprintf
static int h_snprintf(char* sz, size_t len, const char* szFormat, va_list vaList)
{
return _vsnprintf( sz, len , szFormat , vaList );
}

static int h_snprintf(wchar_t* sz, size_t len,const wchar_t* szFormat, va_list vaList)
{
return _vsnwprintf( sz, len , szFormat , vaList );
}

// helper to be able to get a empty string of correct type
static T ReturnEmpty(const char*)
{
return "";
}
static T ReturnEmpty(const wchar_t*)
{
return L"";
}
//////////////////////////////////////////////////////////////////////////

};

typedef StringUtil<STLString> StringUtils;
typedef StringUtil<std::string, char> StringUtilsA;
typedef StringUtil<std::wstring, wchar_t> StringUtilsW;


#endif

 

( Try Multi Commander, A file manager for professionals )

Copyright (c) 2015 - Mathias Svensson