See what's going on with flipcode!




This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  Unicode String Class
  Submitted by



Having recently discovered the immense benefits of using unicode, I decided to make a string class based on the unicode standard. Why not use std::string you say, well i did but I needed a bit more functionality. Easy conversion to ascii to be more specific.

There's also a few other functions, like basic search and substring functions and also string->double, string->long and double->string.

This code is windows specific, but it's only a few functions like WideCharToMultiByte, MultiByteToWideChar, _setmbcp and _getmbcp. If anyone knows how to do these conversion in a platform idependent way, I would love to know.

The code may lack some comments, but frankly, I don't think it needs a lot of comments.

This code is free for anyone to use as they please, and you are free to email me about anything.

Cheers
John Juul Jensen

Currently browsing [uastring.zip] (3,538 bytes) - [UAString.cpp] - (11,413 bytes)

#include "wchar.h"
#include "windows.h"
#include <mbctype.h>

#include "UAString.h"

//#include "PointsAndVectors.h" //#include "Color.h"

/************************************************************************/ /* Constructors / Destructor */ /************************************************************************/

#define CONSTRUCTOR_ALL \ uStringLength = 0; \ uStringBufferSize = 0; \ uString = NULL; \ aStringLength = 0; \ aString = NULL; \ codepage = CP_ACP; \

CUAString::CUAString() { CONSTRUCTOR_ALL; }

CUAString::CUAString( const CUAString& _in) { CONSTRUCTOR_ALL; *this = _in; }

CUAString::CUAString( const wchar_t* _in) { CONSTRUCTOR_ALL; *this = _in; }

CUAString::CUAString( const char* _in) { CONSTRUCTOR_ALL; *this = _in; }

CUAString::CUAString( const double _in) { CONSTRUCTOR_ALL; *this = _in; }

CUAString::~CUAString() { Clear(); }

/************************************************************************/ /* */ /* Operators */ /* */ /************************************************************************/

/************************************************************************/ /* = Operators */ /************************************************************************/ const CUAString& CUAString::operator=( const CUAString& _in) { if ( _in.uStringLength) { AllocateString( _in.uStringLength); AppendString( _in.uString, _in.uStringLength); }

codepage = _in.Codepage; return *this; }

const CUAString& CUAString::operator=( const wchar_t* _in) { if ( _in) { int inLength = wcslen( _in); if ( inLength) { AllocateString( inLength + 1); AppendString( _in, inLength); } else { DeAllocateString(); } }

return *this; }

const CUAString& CUAString::operator=( const char* _in) { if ( _in) { int inLength = strlen( _in); int cp = codepage; if ( !codepage) { cp = CP_ACP; } int convertedInLength = MultiByteToWideChar( cp, 0, _in, inLength, NULL, 0); if ( convertedInLength) { AllocateString( convertedInLength + 1); uStringLength = MultiByteToWideChar( cp, 0, _in, inLength, uString, uStringBufferSize); uString[ uStringLength] = 0; } else { DeAllocateString(); } } return *this; }

const CUAString& CUAString::operator=( const double _in) { DeAllocateString(); AppendDouble( _in); return *this; }

/************************************************************************/ /* += Operators */ /************************************************************************/

const CUAString& CUAString::operator+=( const CUAString& _in) { AppendString( _in.uString, _in.uStringLength); return *this; }

const CUAString& CUAString::operator+=( const wchar_t* _in) { int inLength = wcslen( _in); AppendString( _in, inLength); return *this; }

const CUAString& CUAString::operator+=( const char* _in) { CUAString tempString( _in); *this += tempString; return *this; }

const CUAString& CUAString::operator+=( const double _in) { AppendDouble( _in); return *this; }

/************************************************************************/ /* + Operators */ /************************************************************************/ #define OPERATOR_PLUS( type1, type2) \ CUAString operator+( const type1 string1, const type2 string2) \ { \ CUAString ret = string1; \ ret += string2; \ return ret; \ } \

OPERATOR_PLUS( CUAString&, CUAString&); OPERATOR_PLUS( CUAString&, wchar_t*); OPERATOR_PLUS( wchar_t*, CUAString&); OPERATOR_PLUS( CUAString&, char*); OPERATOR_PLUS( char*, CUAString&); OPERATOR_PLUS( CUAString&, double); OPERATOR_PLUS( double, CUAString&);

/************************************************************************/ /* Comaprison operators */ /************************************************************************/

bool CUAString::operator==( const CUAString& _in) { return !wcscmp( uString, _in.uString); }

bool CUAString::operator==( const wchar_t* _in) { return !wcscmp( uString, _in); }

bool CUAString::operator!=( const CUAString& _in) { return wcscmp( uString, _in.uString); }

bool CUAString::operator!=( const wchar_t* _in) { return wcscmp( uString, _in); }

/************************************************************************/ /* Search functions */ /* */ /* If the find functions returns something>Length then no occurences */ /* were found. */ /************************************************************************/

unsigned int CUAString::FindFirstOf( unsigned int startPos, wchar_t* filter) { if ( startPos < uStringLength) { wchar_t* res = wcspbrk( uString + startPos, filter); if ( res){ return res - uString; } } return uStringLength; }

unsigned int CUAString::FindFirstNotOf( unsigned int startPos, wchar_t* filter) { size_t res = uStringLength; if ( startPos < uStringLength) { res = wcsspn( uString + startPos, filter) + startPos; } return res; }

CUAString CUAString::SubString( unsigned int startPos, int length) { CUAString ret;

if ( startPos < uStringLength) { int minLength = min( length, uStringLength - startPos); if ( length < 0) { minLength = uStringLength - startPos; } ret.AppendString( uString + startPos, minLength); }

return ret; }

/************************************************************************/ /* Public Functions */ /************************************************************************/

bool CUAString::Empty() { if ( uStringLength) { return true; } else { return false; } }

void CUAString::MakeLower() { wcslwr( uString); }

void CUAString::MakeUpper() { wcsupr( uString); }

int CUAString::Codepage() { return codepage; }

bool CUAString::Codepage( int _codepage) { codepage = CP_ACP;

int oldCodepage = _getmbcp();

if ( 0 == _setmbcp( _codepage)) { codepage = _codepage; }

_setmbcp( oldCodepage);

if ( codepage) { return true; } else { return false; } }

/************************************************************************/ /* Conversion functions (AsFoo) */ /************************************************************************/

double CUAString::AsDouble( bool extract) { unsigned int endPos, startPos; double number = 0; endPos = 0; startPos = FindFirstOf( endPos, L"+-1234567890."); endPos = FindFirstNotOf( startPos + 1, L"+-1234567890.");

if ( startPos < uStringLength) { number = wcstod( SubString( startPos, endPos - startPos).AsUnicode(), NULL);

if ( extract) { *this = SubString( endPos); } } return number; }

long CUAString::AsLong( bool extract) { unsigned int endPos, startPos; long number = 0; endPos = 0; startPos = FindFirstOf( endPos, L"+-1234567890"); endPos = FindFirstNotOf( startPos + 1, L"+-1234567890"); if ( startPos < uStringLength) { number = wcstol( SubString( startPos, endPos - startPos).AsUnicode(), NULL, 10); if ( extract) { *this = SubString( endPos); } } return number; }

CUAString CUAString::AsToken( wchar_t startChar, wchar_t endChar, bool extract) { CUAString ret; wchar_t startBuf[] = L"["; startBuf[0] = startChar; wchar_t endBuf[] = L"]"; endBuf[0] = endChar; unsigned int endPos, startPos; endPos = 0; startPos = FindFirstOf( endPos, startBuf) + 1; endPos = FindFirstOf( startPos, endBuf); ret = SubString( startPos, endPos - startPos); if ( extract) { *this = SubString( endPos + 1); }

return ret; }

const wchar_t* CUAString::AsUnicode() { return uString; }

const char* CUAString::AsAscii( int _codepage) {

int cp = codepage;

if ( _codepage) { cp = _codepage; }

if ( !aString) {

int convertedLength = WideCharToMultiByte( cp, 0, uString, uStringLength, aString, 0, NULL, NULL); if ( convertedLength) { aStringLength = convertedLength; if ( aString) delete[] aString; aString = new char[aStringLength + 1]; WideCharToMultiByte( cp, 0, uString, uStringLength, aString, aStringLength, NULL, NULL); aString[ aStringLength] = 0; } }

if ( aString) { return aString; }

return ""; }

/************************************************************************/ /* Protected Functions */ /************************************************************************/

void CUAString::Clear() { DeAllocateString(); codepage = CP_ACP; }

void CUAString::DeAllocateString() { uStringLength = 0; uStringBufferSize = 0; if ( uString) delete[] uString; uString = NULL; aStringLength = 0; if ( aString) delete[] aString; aString = NULL; }

void CUAString::AllocateString( unsigned int _size) { DeAllocateString(); if ( _size > 0) { uStringBufferSize = _size; uString = new wchar_t[ uStringBufferSize]; uString[0] = 0; } }

void CUAString::ReAllocateString( unsigned int _size) {

if ( _size > 0) { wchar_t* tempStr = new wchar_t[ _size]; int minLength = min( uStringLength + 1, _size); if ( uString) { memcpy( tempStr, uString, minLength * sizeof(wchar_t)); } tempStr[minLength - 1] = 0;

DeAllocateString();

uString = tempStr; uStringLength = minLength - 1; uStringBufferSize = _size; } else { DeAllocateString(); } }

void CUAString::AppendString( const wchar_t* _str, unsigned int _length) { if ( uStringBufferSize < uStringLength + _length + 1) { ReAllocateString( uStringLength + _length + 1); }

memcpy( uString + uStringLength, _str, _length * sizeof(wchar_t)); uStringLength = uStringLength + _length; uString[ uStringLength] = 0; }

void CUAString::AppendDouble( double num) { int dec, sign; CUAString tempString; char* buffer = _fcvt( num, 5, &dec, &sign );

int bufLength = strlen( buffer) - 1; while ( (bufLength > 0) && (buffer[bufLength] == '0')) { buffer[bufLength] = 0; bufLength--; }

if ( buffer[0] != '0') { if ( sign) tempString += L"-"; if ( dec <= 0) { tempString += L"0."; while ( dec < 0) { tempString += L"0"; dec++; } } else if ( bufLength > dec) { char temp = buffer[dec]; buffer[dec] = 0; tempString += buffer; buffer[dec] = temp; buffer += dec; tempString += L"."; } }

tempString += buffer;

*this += tempString; }

Currently browsing [uastring.zip] (3,538 bytes) - [UAString.h] - (3,817 bytes)

/********************************************************************
	created:		2001/03/24
	file name:		D:\grafik\MPREstd\UAString.h
	OS specific:	Yes
	author:			John Juul Jensen

Copyright 2001 [COPYRIGHT NOTICE] contains: CUAString *********************************************************************/


#ifndef __UASTRING_H #define __UASTRING_H

#include "wchar.h"

/******************************************************************** class name: CUAString created: 2001/03/24 author: John Juul Jensen purpose: The CUAString class is a string class based on the unicode standard. All text is kept in unicode internally and this is also the preferred external use. For accurate conversion between ascii and unicode, a codepage can be specified. The class implements the conversion function string->float. A few basic search functions, similar to the ones found in std::string, has also been implemented. All string lengths in this this class are assumed to be excluding the null character. *********************************************************************/ class CUAString { public: // Constructors / Destructor CUAString(); CUAString( const CUAString& _in); CUAString( const wchar_t* _in); CUAString( const char* _in); CUAString( const double _in); ~CUAString();

public: // Operators const CUAString& operator=( const CUAString& _in); const CUAString& operator=( const wchar_t* _in); const CUAString& operator=( const char* _in); const CUAString& operator=( const double _in);

const CUAString& operator+=( const CUAString& _in); const CUAString& operator+=( const wchar_t* _in); const CUAString& operator+=( const char* _in); const CUAString& operator+=( const double _in);

friend CUAString operator+( const CUAString& string1, const CUAString& string2); friend CUAString operator+( const CUAString& string1, const wchar_t* string2); friend CUAString operator+( const wchar_t* string1, const CUAString& string2); friend CUAString operator+( const CUAString& string1, const char* string2); friend CUAString operator+( const char* string1, const CUAString& string2); friend CUAString operator+( const CUAString& string1, const double string2); friend CUAString operator+( const double string1, const CUAString& string2);

bool operator==( const CUAString& _in); bool operator==( const wchar_t* _in); bool operator!=( const CUAString& _in); bool operator!=( const wchar_t* _in);

public: // Search functions unsigned int FindFirstOf( unsigned int startPos, wchar_t* filter); unsigned int FindFirstNotOf( unsigned int startPos, wchar_t* filter); CUAString SubString( unsigned int startPos, int length = -1);

public: // Extract/Conversion routines double AsDouble( bool extract = false); long AsLong( bool extract = false); CUAString AsToken( wchar_t startChar = L'[', wchar_t endChar = L']', bool extract = false); const wchar_t* AsUnicode(); const char* AsAscii( int _codepage = 0);

public: // Misc functions int Codepage(); bool Codepage( int _codepage);

void MakeLower(); void MakeUpper();

bool Empty();

protected: // functions void BuildAscii(); void Clear();

void DeAllocateString(); void AllocateString( unsigned int _size); void ReAllocateString( unsigned int _size); void AppendString( const wchar_t* _str, unsigned int _length); void AppendDouble( double num);

protected: // variables unsigned int codepage;

unsigned int uStringLength; // length excluding terminating null character unsigned int uStringBufferSize; // size of buffer wchar_t* uString;

unsigned int aStringLength; char* aString; // length excluding terminating null character };

#endif

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

 

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.