#ifndef _KVI_WSTRING_H_
#define _KVI_WSTRING_H_
//=============================================================================
//
//   File : kvi_wstring.h
//   Creation date : Wed 04 Dec 2002 03:33:21 by Szymon Stefanek
//
//   This file is part of the KVirc irc client distribution
//   Copyright (C) 2002 Szymon Stefanek (pragma at kvirc dot net)
//
//   This program is FREE software. You can redistribute it and/or
//   modify it under the terms of the GNU General Public License
//   as published by the Free Software Foundation; either version 2
//   of the License, or (at your opinion) any later version.
//
//   This program is distributed in the HOPE that it will be USEFUL,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//   See the GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program. If not, write to the Free Software Foundation,
//   Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
//=============================================================================

#include "kvi_wstring_config.h"
#include "kvi_wstring_wchar.h"
#include "kvi_wstring_wslen.h"
#include "kvi_wstring_functions.h"

#include "kvi_textencoding.h"

#ifdef WSTRINGCONFIG_USE_KVISTR
	#include "kvi_string.h"
#endif // WSTRINGCONFIG_USE_KVISTR

#ifdef WSTRINGCONFIG_USE_QT
	#include <qstring.h>
#endif // WSTRINGCONFIG_USE_QT

// UCS-2 stringie :)

class _WSTRING_API KviWStr
{
protected:
	//======================================================================================================
	// data
	//======================================================================================================

	kvi_wchar_t          * m_ptr; // pointer to allocated data , never null
	kvi_wslen_t            m_len; // length of the string = ((allocated buffer / 2) - 1)

public:
	//======================================================================================================
	// enums (mostly tags)
	//======================================================================================================

	// this is a tag used in the attach constructors
	enum KviWStrAttachTag { Attach };
	enum KviWStrDecodeTag { Decode };
	// this is a tag used in the conversion constructors

	//======================================================================================================
	// data access
	//======================================================================================================

	_WSTRING_INLINE kvi_wchar_t * ptr() const { return m_ptr; };
	_WSTRING_INLINE kvi_wslen_t len() const { return m_len; };
	// this is an useful alias
	_WSTRING_INLINE kvi_wslen_t length() const { return m_len; };

	_WSTRING_INLINE bool hasData() const { return m_len; };
	_WSTRING_INLINE bool isEmpty() const { return !m_len; };

	//======================================================================================================
	// buffer manipulations
	//======================================================================================================

	// forces the length of this string to be len
	// (len does NOT include the trailing null : it is automatically added)
	void setLen(kvi_wslen_t len);
	// do we need this alias ?
	//void setLength(kvi_wslen_t len){ setLen(len); };

	//======================================================================================================
	// buffer attach and detach
	//======================================================================================================

	// releases the data pointer and sets this string to be empty
	// the pointer must be freed later with KviWStr::bufferFree()
	void bufferDetach();
	// attacches this string to the externally allocated buffer str
	// the buffer must be allocated with KviWStr::bufferAlloc() or KviWStr::bufferRealloc()
	// the pointer becomes property of this string object
	// str must not be NULL and MUST be NULL terminated
	// the length of the string is calculated
	void bufferAttach(kvi_wchar_t * str);
	// attacches this string to the externally allocated buffer str
	// the buffer must be allocated with KviWStr::bufferAlloc() or KviWStr::bufferRealloc() and must be
	// at least ((len+1) * sizeof(kvi_wchar_t)) bytes long
	// the pointer becomes property of this string object
	// str must not be NULL and MUST be NULL terminated
	// This constructor trusts you that the string is exactly len wide characters long
	void bufferAttach(kvi_wchar_t * str,kvi_wslen_t len);


	//======================================================================================================
	// local memory allocator
	//======================================================================================================
	// you can use this allocator to create a string buffer and later
	// attachBuffer() (or use the attach constructor)

	// allocates a buffer with space for nChars wide characters
	// or in bytes: sizeof(kvi_wchar_t) * nChars
	static kvi_wchar_t * bufferAlloc(kvi_wslen_t nChars);
	// reallocates the buffer (must be allocated with bufferAlloc() !)
	static kvi_wchar_t * bufferRealloc(kvi_wchar_t * str,kvi_wslen_t nChars);
	// frees the buffer above
	static void bufferFree(kvi_wchar_t * str);

	//======================================================================================================
	// conversions
	//======================================================================================================

#ifdef WSTRINGCONFIG_USE_QT
	QString qstring() const;
#endif // WSTRINGCONFIG_USE_QT

	//======================================================================================================
	// prepend
	//======================================================================================================

	// this treats str as Latin1
	// str can be NULL here
	void prepend(const char * str);
	// this treats str as Latin1
	// str can't be NULL here
	void prepend(const char * str,kvi_wslen_t len);
	
	void prepend(const KviWStr &str);

	void prepend(kvi_wchar_t c);

	//======================================================================================================
	// append
	//======================================================================================================

#ifdef WSTRINGCONFIG_USE_QT
	void append(const QString &str,int startIdx,int len);
#endif // WSTRINGCONFIG_USE_QT

	void append(kvi_wchar_t c);
	// str can be null here
	void append(kvi_wchar_t * str);
	// str CAN'T be null here
	void append(kvi_wchar_t * str,kvi_wslen_t len);

	//======================================================================================================
	// strip stuff
	//======================================================================================================

	// strips left and right white space
	void stripWhiteSpace();

	//======================================================================================================
	// fiddle with encodings
	//======================================================================================================

	// 
	static const char * encodingName(unsigned int e)
		{ return kvi_textEncodingName(e); };
	// better understandable name
	static const char * encodingNameAlias(unsigned int e)
		{ return kvi_textEncodingNameAlias(e); };
	static unsigned int encodingFromName(const char * name)
		{ return kvi_textEncodingFromName(name); };

	static unsigned int encodingForLocale()
		{ return kvi_textEncodingForLocale(); };

	static unsigned int numberOfEncodings()
		{ return KVI_TEXT_ENCODING_COUNT; };

	static bool isValidEncoding(unsigned int enc)
		{ return (enc < KVI_TEXT_ENCODING_COUNT); };

	//======================================================================================================
	// conversions
	//======================================================================================================

protected:
	void internalDecode(kvi_wchar_t * map,const char * str,unsigned int len);
	void internalEncode(unsigned char ** map,KviStr &szBuffer);
public:

	// this is the faster conversion method
	// str must not be null and must be at least len characters long
	void decodeLatin1(const char * str,kvi_wslen_t len);
	// str can be null, but if not null then it must be NULL terminated
	void decodeLatin1(const char * str);
#ifdef WSTRINGCONFIG_USE_KVISTR
	// just like the above
	void decodeLatin1(const KviStr &str)
		{ decodeLatin1(str.ptr(),str.len()); };
	void encodeLatin1(KviStr &szBuffer);
#endif // WSTRINGCONFIG_USE_KVISTR

	// converts the string str from utf8
	// str must not be null and must be at least len characters long
	void decodeUtf8(const char * str,kvi_wslen_t len);
	// str can be null but if not null then it must be NULL terminated
	void decodeUtf8(const char * str);
#ifdef WSTRINGCONFIG_USE_KVISTR
	// just like the above
	void decodeUtf8(const KviStr &str)
		{ decodeUtf8(str.ptr(),str.len()); };
	void encodeUtf8(KviStr &szBuffer);
#endif // WSTRINGCONFIG_USE_KVISTR


	// converts the string str from latin2 (ISO-8859-2)
	// str must not be null and must be at least len characters long
	void decodeLatin2(const char * str,kvi_wslen_t len);
	// str can be null but if not null then it must be NULL terminated
	void decodeLatin2(const char * str);
#ifdef WSTRINGCONFIG_USE_KVISTR
	// just like the above
	void decodeLatin2(const KviStr &str)
		{ decodeLatin2(str.ptr(),str.len()); };
	void encodeLatin2(KviStr &szBuffer);
#endif // WSTRINGCONFIG_USE_KVISTR


	void decodeLatin15(const char * str,kvi_wslen_t len);
#ifdef WSTRINGCONFIG_USE_KVISTR
	void decodeLatin15(const KviStr &str)
		{ decodeLatin2(str.ptr(),str.len()); };
	void encodeLatin15(KviStr &szBuffer);
#endif // WSTRINGCONFIG_USE_KVISTR

	// str can NOT be null and must be at least len characters long
	void decode(const char * str,kvi_wslen_t len,unsigned int encoding);
	// str can be null but if not null then it must be NULL terminated
	void decode(const char * str,unsigned int encoding);
#ifdef WSTRINGCONFIG_USE_KVISTR
	// just like the above
	void decode(const KviStr &str,unsigned int encoding)
		{ decode(str.ptr(),str.len(),encoding); };

	void encode(KviStr &szBuffer,unsigned int encoding);

#endif // WSTRINGCONFIG_USE_KVISTR


	//======================================================================================================
	// assignment operators
	//======================================================================================================


	void operator = (const KviWStr &str);

	void operator = (const KviStr &str);
	// str CAN be null here
	void operator = (const kvi_wchar_t *str);
	// this is decoded from Latin1 , str can be null
	void operator = (const char * str);

	//======================================================================================================
	// complex assignments
	//======================================================================================================

#ifdef WSTRINGCONFIG_USE_QT
	void setStr(const QString &str,int startIdx,int len);
#endif // WSTRINGCONFIG_USE_QT

	//======================================================================================================
	// sprintf , yeah
	//======================================================================================================

	void sprintf(const kvi_wchar_t * fmt,...);
	void sprintf(const char * fmt,...);

	//======================================================================================================
	// constructors
	//======================================================================================================

	// plain constructor , 1 wchar allocated
	KviWStr();

	// copy constructor
	KviWStr(const KviWStr &str);

	// deep copy of str which must be NULL terminated
	// str can be NULL : in this case an empty string is created (1 wchar)
	KviWStr(const kvi_wchar_t * str);

	// deep copy of first len characters of str
	// str MUST be at least len characters long and can't be NULL
	KviWStr(const kvi_wchar_t * str,kvi_wslen_t len);

	// deep copy of the string begin up to the character end (not included)
	// begin and end must point to the same string buffer
	KviWStr(const kvi_wchar_t * begin,const kvi_wchar_t * end);

	// attacches this string to the externally allocated buffer str
	// the buffer must be allocated with KviWStr::bufferAlloc() or KviWStr::bufferRealloc()
	// the pointer becomes property of this string object
	// str must not be NULL and MUST be NULL terminated
	// the length of the string is calculated
	// tag must be KviWStr::Attach
	KviWStr(KviWStrAttachTag tag,kvi_wchar_t * str)
		{ m_ptr = str; m_len = kvi_wstrlen(str); };

	// attacches this string to the externally allocated buffer str
	// the buffer must be allocated with KviWStr::bufferAlloc() or KviWStr::bufferRealloc() and must be
	// at least ((len+1) * sizeof(kvi_wchar_t)) bytes long
	// the pointer becomes property of this string object
	// str must not be NULL and MUST be NULL terminated
	// This constructor trusts you that the string is exactly len wide characters long
	// tag must be KviWStr::Attach
	KviWStr(kvi_wchar_t * str,kvi_wslen_t len)
		{ m_ptr = str; m_len = len; };

	// conversion constructor
	// str is decoded from encoding e
	// str can't be NULL and must be at least len characters long
	KviWStr(KviWStrDecodeTag tag,const char * str,kvi_wslen_t len,unsigned int e)
		{ m_ptr = 0; decode(str,len,e); };

	// conversion constructor
	// decodes str from Latin1
	// str can't be NULL and must be at least len characters long
	// this is mostly useful for constructing hardcoded strings
	// like KviWStr("beginning of a message",22);
	// this is just like the above constructor had a default parameter.. just faster
	KviWStr(const char * str,kvi_wslen_t len)
		{ m_ptr = 0; decodeLatin1(str,len); };

	// conversion constructor
	// decodes str from the encoding e
	// str can be NULL but if it isn't then it must be NULL terminated
	// tag must be KviWStr::Decode
	KviWStr(KviWStrDecodeTag tag,const char * str,unsigned int e)
		{ m_ptr = 0; decode(str,e); };

	// straight conversion constructor : decodes from Latin1
	// str can be NULL but if it isn't then it must be NULL terminated
	// this is mostly useful for constructing hardcoded strings
	// like KviWStr("beginning of a message");
	// this is just like the above constructor had a default parameter.. just faster
	KviWStr(const char * str)
		{ m_ptr = 0; decodeLatin1(str); };

#ifdef WSTRINGCONFIG_USE_KVISTR

	// conversion constructor
	// decodes str from Latin1
	// tag must be KviWStr::Decode
	KviWStr(KviWStrDecodeTag tag,const KviStr &str,unsigned int e)
		{ m_ptr = 0; decode(str.ptr(),str.len(),e); };

	// conversion constructor
	// decodes str from Latin1
	// this is just like the above constructor had a default parameter.. just faster
	KviWStr(const KviStr &str)
		{ m_ptr = 0; decodeLatin1(str.ptr(),str.len()); };

#endif // WSTRINGCONFIG_USE_KVISTR

#ifdef WSTRINGCONFIG_USE_QT
	// deep copy of the str data
	KviWStr(const QString &str);
#endif // WSTRINGCONFIG_USE_QT

	//======================================================================================================
	// destructor
	//======================================================================================================

	// just plain free()
	~KviWStr();

};












/*


/////////////////////////////////////////////////////////////////////////////////
#include "kvi_settings.h"



#include <stdio.h>
#include <stdarg.h> //for va_list

#include <string.h>
//#include <ctype.h>

#ifdef WSTRING_USE_QT
	#include <qglobal.h>
	#include <qstring.h>
#endif // WSTRING_USE_QT

#ifdef WSTRING_USE_KVISTR
	#include "kvi_string.h"
#endif // WSTRING_USE_KVISTR

#undef __KVI_EXTERN

#ifdef _KVI_STRING_CPP_
	#define __KVI_EXTERN
#else
	#define __KVI_EXTERN extern
#endif

#include "kvi_wchar.h"


//=============================================================================
//
// A simple UNICODE string class.
// -No data sharing.
// -Has ALWAYS NON-NULL DATA.
// WARNING : Handle with care and use at own risk :)
//
//=============================================================================






void KviWStr::clear()
{
	m_len = 0;
	m_ptr = _MY_REALLOC(m_ptr,1);
	*m_ptr = KVI_WCHAR_NULL;
}

class KVILIB_API KviWStr
{
protected:
	//=============================================================================
	// Data members
	//=============================================================================
	kvi_char_t    * m_ptr; // pointer to allocated buffer , do not change this!
	unsigned int    m_len; // string data length not including the terminator
public:
	//=============================================================================
	// Enums
	//=============================================================================
	enum KviEncodingTag { Latin1 , UTF8 };
	enum KviWFormatConstructorTag { Format , Sprintf };

	//=============================================================================
	// Constructors
	//=============================================================================

	// Empty string == "", len = 0, 2 butes allocated
	KviWStr();

	// Deep copy of the NULL TERMINATED string
	// str CAN be NULL (an empty string is created)
	// str MUST NOT point to this string buffer
	KviWStr(const kvi_wchar_t *str);

	// Copy uLen characters from string str 
	// str MUST be at least uLen chars long)
	// str MUST NOT point to this string
	KviWStr(const kvi_wchar_t *str,unsigned int uLen);

	// begin and end are pointers to a SINGLE string.
	// begin MUST BE <= end
	// A string is extracted starting from bg and ending at end (not included).
	KviWStr(const kvi_wchar_t *begin,const kvi_wchar_t *end);

	// Carbon copy :)
	// fast because it has precalculated length
	KviWStr(const KviWStr &str);

	// Conversion constructor
	// KVI_TEXT_ENCODING_ISO88591 : the string is encoded in Latin1 charset: the fastest conversion
	// KviWStr::UTF8 : the string is UTF8 encoded
	KviWStr(const char * str,KviEncodingTag tag);

	// direct latin1 decoding
	KviWStr(const char * str){ from(str,_MY_STRLEN(str)); };

#if WSTRING_USE_QT
	// Compat with QT...
	// Safe even if the QString is null.
	KviWStr(const QString &str);
#endif // WSTRING_USE_QT

#if WSTRING_USE_KVISTR
	// Copy from a KviStr
	KviWStr(const KviStr & str,KviEncodingTag tag);
#endif // WSTRING_USE_KVISTR

	// Fill sonstructor.
	// Creates a string long fillLen characters filled with character c.<br>

	KviWStr(char c,int fillLen = 1);


	// Format constructor.<br>
	// tag is....yes....a dummy number used to resolve ambiguities.<br>
	// It is SAFE: will fail only if we run out of memory,<br>
	// but can handle only %s %d %u and %c.

	KviWStr(KviFormatConstructorTag tag,const char *fmt,...);


	_KVI_INLINE void from(const char * str,KviEncodingTag tag){ from(str,_MY_STRLEN(str),tag); }

	// just free(m_ptr)

	~KviWStr();

public:
	//=============================================================================
	// Basic const interface (read stuff)
	//=============================================================================

	// Internal data buffer
	kvi_wchar_t * ptr() const              { return m_ptr; };
	// Length: fast, cached
	unsigned int len() const               { return m_len; };
	unsigned int length() const            { return m_len; };

	// I hate this operator...but sometimes it is really useful
	operator const kvi_wchar_t * () const  { return m_ptr; };

	bool isEmpty() const            { return (m_len == 0); };
	bool hasData() const            { return (m_len != 0); };

// Memory allocators and deallocators
//	static void * KviWStr::memAllocBytes(unsigned int uCount);
//	static void * KviWStr::memAllocChars(unsigned int uCount);
//	static void KviWStr::memFree(void * ptr);
//	static void KviWSt::memRealloc(void * ptr,unsigned int uCount);


	// this is better than string = "", it does not call strlen
	void clear();

	// forces the length of this string to be iLen (iLen does NOT include the trailing null : it is automatically added)
	void setLength(int iLen);

	// Returns true if there is something "readable" inside the string
	bool hasNonWhiteSpaceData() const;

	// Character at zero-based index : always safe!
	char & at(int idx) const        { return ((idx < m_len) ? m_ptr[idx] : m_ptr[m_len]);        };

	// character checks
	bool lastCharIs(char ch)  const { return (m_len > 0) ? (*(m_ptr + m_len - 1) == ch) : false; };
	bool firstCharIs(char ch) const { return (*m_ptr == ch);                                     };

	// upper and lower case copies
	KviWStr upper() const;
	KviWStr lower() const;

	// left , right & co.
	// all parameters are safety-checked
	KviWStr left(int maxLen) const;
	KviWStr right(int maxLen) const ;
	KviWStr middle(int idx,int maxLen) const;

	KviWStr leftToFirst(char c,bool bIncluded = false) const;
//	KviWStr leftToFirst(const char * str); const;

	//=============================================================================
	// Non-const interface (write stuff)
	//=============================================================================

	// Null terminator is NOT included in len
	KviWStr & setLen(int len);
	// str must not be 0, but len can be anything (it is checked)
	KviWStr & setStr(const char *str,int len = -1);
	// Like the special constructor that gets the same args.
	void extractFromString(const char *begin,const char *end);


	// Safe sprintf. This one will never write past the end of the string
	// It can handle only %s %d %u and %c format flags.
	KviWStr & sprintf(const char *fmt,...);

	// append functions
	void append(const KviWStr &str);
	void append(const QString &str);
	void append(char c);
	void append(const char *str);                                     // str CAN be 0
	void append(const char *str,int len);                             // str CAN NOT be 0, and MUST be at least len chars long
	void append(KviFormatConstructorTag dummy,const char *fmt,...);

	// prepend stuff , same as above
	void prepend(const KviWStr &str);
	void prepend(const char *str);                                    // str CAN be 0
	void prepend(const char *str,int len);                            // str CAN NOT be 0, and MUST be at least len chars long

	// if lastCharIs ch does nothing otherwise appends it
	void ensureLastCharIs(char ch)              { if(!lastCharIs(ch))append(ch);        };

	// Change THIS string to uppercase or lowercase
	void toUpper();
	void toLower();

	// Assignment
	KviWStr & operator=(const KviWStr &str);       // deep copy
	KviWStr & operator=(const char *str);         // str can be NULL here
	KviWStr & operator=(char c);                  // 2 bytes allocated ,m_len = 1
	KviWStr & operator=(const QString &str);

	// Append operators
	KviWStr & operator+=(const KviWStr &str)      { append(str); return (*this);          };
	KviWStr & operator+=(const char *str)        { append(str); return (*this);          };
	KviWStr & operator+=(char c)                 { append(c);   return (*this);          };
	KviWStr & operator+=(const QString &str)     { append(str); return (*this);          };

	// Comparison
	bool equalsCI(const KviWStr &other) const { if(m_len != other.m_len)return false; return kvi_strEqualCI(m_ptr,other.m_ptr); };
	bool equalsCS(const KviWStr &other) const { if(m_len != other.m_len)return false; return kvi_strEqualCS(m_ptr,other.m_ptr); };

	//=============================================================================
	// HEX and Base64 stuff
	//=============================================================================

	// HEX transforms functions
	void bufferToHex(const char *buffer,int len);
	// Allocates the needed buffer and returns the allocated length,
	// returns -1 in case of error (and allocates nothing)
	// The string MUST contain only hex digits, and the digits MUST be in couples. (len % 2) must equal 0!
	// So this will fail also if there are leading or trailing spaces!
	int hexToBuffer(char ** buffer,bool bNullToNewlines = false);
	// BASE64 stuff
	void bufferToBase64(const char * buffer,int len);
	// same as hexToBuffer but obviously transforms base64 notation to binary data (len % 4) must equal 0!
	int base64ToBuffer(char ** buffer,bool bNullToNewlines = false);

	// frees a buffer allocated by hexToBuffer or base64ToBuffer
	static void freeBuffer(char * buffer);

	//=============================================================================
	// Splitters
	//=============================================================================

	// cut
	KviWStr & cutLeft(int len);             // kills the first len characters
	KviWStr & cutRight(int len);            // kills the last len characters
	KviWStr & cut(int idx,int len);
	KviWStr & cutToFirst(char c,bool bIncluded = true); // cuts the left part of the string up to the first character c or does nothing if the char c is not in the string
	KviWStr & cutToLast(char c,bool bIncluded = true);
	KviWStr & cutFromFirst(char c,bool bIncluded = true);
	KviWStr & cutFromLast(char c,bool bIncluded = true);
	KviWStr & cutToFirst(const char *c,bool bIncluded = true); // cuts the left part of the string up to the first character c or does nothing if the char c is not in the string
	KviWStr & cutToLast(const char *c,bool bIncluded = true);
	KviWStr & cutFromFirst(const char *c,bool bIncluded = true);
	KviWStr & cutFromLast(const char *c,bool bIncluded = true);
	// & paste
	KviWStr & insert(int idx,const char *data);
	KviWStr & insert(int idx,char c);
	//Replaces all occurences of char c with the string str
	KviWStr & replaceAll(char c,const char *str);
	//same as above but with a string
	KviWStr & replaceAll(char *toFind,const char *str,bool bCaseS = true);

	KviWStr & transliterate(const char * szToFind,const char * szReplacement);

	// Strips whitespace characters from beginning of this string.
	KviWStr & stripLeftWhiteSpace();
	KviWStr & stripRightWhiteSpace();
	// Stips inital and final WHITESPACE characters (see man isspace),<br>
	// and returns a reference to this string.
	KviWStr & stripWhiteSpace();

	// Strips spaces and tabs only
	KviWStr & stripSpace();
	// Strips all occurences of the character c from the beginning of the string.<br>
	// Note that c can not be '\0' :)
	KviWStr & stripLeft(char c);
	KviWStr & stripRight(char c);

	//=============================================================================
	// Tokenize
	//=============================================================================

	// Extracts (copy to str and remove) a token from this string ,<br>
	// and returns true if there are more tokens to extract<br>
	// Does not strip initial separators!!<br>
	// str can NOT be this string.
	bool getToken(KviWStr &str,char sep);
	// Does not strip initial separators!<br>
	// Can assign also to this string.
	KviWStr getToken(char sep);
	// Extracts a line from the string.<br>
	// Returns false if there was no data to extract
	bool getLine(KviWStr &str);

	// splits this string in a null-terminated array of strings
	// separated by sep.
	KviWStr ** splitToArray(char sep,int max,int * realCount) const;
	static void freeArray(KviWStr ** strings);
	// joins the array to this string
	// if sep is not 0 , it is inserted between the strings
	// if bLastSep is true and sep is non 0 , then sep is also appended at the end
	// of the buffer (after the last string)
	void joinFromArray(KviWStr ** strings,const char * sep = 0,bool bLastSep = false);

	//=============================================================================
	// Utils
	//=============================================================================

	KviWStr & decodeWhiteSpace();
	KviWStr & encodeWhiteSpace();

	//=============================================================================
	// Contains / occurence count
	//=============================================================================

	// Returns true if at least one occurence of str is found
	bool contains(const char *str,bool caseS=true) const;
	// Returns true if at least one occurence of character c is found in this string
	bool contains(char c,bool caseS=true) const;
	// Returns the number of occurences of string str in this string.<br>
	// Overlapped matches are counted.
	int occurences(const char *str,bool caseS=true) const;
	// Returns the number of occurences of character c in this string
	int occurences(char c,bool caseS=true) const;

	//=============================================================================
	// Find
	//=============================================================================

	// Finds the first occurence of the character c in this string,<br>
	// and returns its zero-based index or -1 if c can not be found.<br>
	// c can NOT be '\0' here.
	int findFirstIdx(char c) const;
	// Finds the first occurence of the sub-string str in this string,<br>
	// and returns its zero-based index or -1 if the sub-string can not be found.<br>
	// str can NOT be 0 here.
	int findFirstIdx(const char *str,bool caseS = true) const;
	// Finds the last occurence of the character c in this string,<br>
	// and returns its zero-based index or -1 if the character can not be found.
	int findLastIdx(char c) const;
	// Finds the last occurence of the sub-string str in this string,<br>
	// and returns its zero-based index or -1 if the sub-string can not be found.<br>
	// str can NOT be 0 here.
	int findLastIdx(const char *str,bool caseS = true) const;

	int find(char c,int startIdx) const;
	int find(const char * str,int startIdx,bool caseS = true) const;
	int findRev(const char * str,int startIdx,bool caseS = true) const;


	//=============================================================================
	// Numbers
	//=============================================================================

	// everything in base 10.... no overflow checks here
	long toLong(bool *bOk=0) const;
	unsigned long toULong(bool *bOk=0) const;
	char toChar(bool *bOk=0) const              { return (char)toLong(bOk);             };
	unsigned char toUChar(bool *bOk=0) const    { return (unsigned char)toULong(bOk);   };
	int toInt(bool *bOk=0) const                { return (int)toLong(bOk);              };
	unsigned int toUInt(bool *bOk=0) const      { return (unsigned int)toULong(bOk);    };
	short toShort(bool *bOk=0) const            { return (short)toLong(bOk);            };
	unsigned short toUShort(bool *bOk=0) const  { return (unsigned short)toLong(bOk);   };

	KviWStr & setNum(long num);
	KviWStr & setNum(unsigned long num);

	KviWStr & setNum(int num)                    { return setNum((long)num);             };
	KviWStr & setNum(unsigned int num)           { return setNum((unsigned long)num);    };
	KviWStr & setNum(short num)                  { return setNum((long)num);             };
	KviWStr & setNum(unsigned short num)         { return setNum((unsigned long)num);    };
	KviWStr & setNum(char num)                   { return setNum((long)num);             };
	KviWStr & setNum(unsigned char num)          { return setNum((unsigned long)num);    };

	// Retuns true if the string contains only digits and an optional '-' character
	// at the beginning.<be>
	// Space characters are allowed at the begginning and the end.<br>
	// There is no overflow check!
	bool isNum() const;
	bool isUnsignedNum() const;

	// special functions for multiple bases
	long toLongExt(bool *bOk = 0,int base = 0);
	// unsigned long toULongExt(bool *bOk = 0,int base = 0); //never used

	// returns an empty string...
	// this if often useful!
	static KviWStr & emptyString();

#ifdef COMPILE_ON_WINDOWS
	// On windows we need to override new and delete operators
	// to ensure that always the right new/delete pair is called for an object instance
	// This bug is present in all the classes exported by a module that
	// can be instantiated/destroyed from external modules.
	// (this is a well known bug described in Q122675 of MSDN)
	void       * operator new(size_t tSize);
	void         operator delete(void * p);
#endif
	//=============================================================================
	// Dead interface
	//=============================================================================

	// Transform a pointer to a string with all 0 and 1
	// void pointerToBitString(const void * ptr);
	// Get a pointer from a string all of 0 and 1 : return 0 if invalid
	// void * bitStringToPointer();

	//=============================================================================
	// "External string" helper functions
	//=============================================================================

	// FIXME: Should it be KviWStrExt::contains namespace ?
	static bool ext_contains(register const char * data,const char * item,bool caseS = true);
};



// Include inlined assembly implementations if required
//#ifdef COMPILE_ix86_ASM
//	#include "kvi_strasm.h"
//#else
	// Returns true if the string str1 is equal to str2. case sensitive.
	__KVI_EXTERN KVILIB_API bool kvi_strEqualCS(const char *str1,const char *str2);
	// Returns true if the forst len characters of string str1 are equal to str2.
	// case sensitive.
	// Note that if str1 or str2 are shorter than len characters then are considered as NOT equal!
	__KVI_EXTERN KVILIB_API bool kvi_strEqualCSN(const char *str1,const char *str2,int len);
	// no such tricks in non-asm
	#define kvi_strEqualNoLocaleCI(str1,str2) kvi_strEqualCI(str1,str2)
	#define kvi_strEqualNoLocaleCIN(str1,str2,len) kvi_strEqualCIN(str1,str2,len)
	#define kvi_strLen(str) strlen(str)
//#endif

// Returns true if the string str1 is equal to str2.
// case insensitive.
__KVI_EXTERN KVILIB_API bool kvi_strEqualCI(const char *str1,const char *str2);
// Returns true if the forst len characters of string str1 are equal to str2.
// case insensitive.
// Note that if str1 or str2 are shorter than len characters then are considered as NOT equal!
__KVI_EXTERN KVILIB_API bool kvi_strEqualCIN(const char *str1,const char *str2,int len);
// My own implementations of strcmp and strncasecmp
// Once I wrote it , I KNOW what they do : ALWAYS :)
// Note that greater here means that comes AFTER in the alphabetic order.
__KVI_EXTERN KVILIB_API int kvi_strcmpCI(const char *str1,const char *str2);
//__KVI_EXTERN KVILIB_API int kvi_strcmpCIN(const char *str1,const char *str2,int len);
__KVI_EXTERN KVILIB_API int kvi_strcmpCS(const char *str1,const char *str2);




// FIXME: the functions below should end in the KviWStr namespace ???


// Cool string parsing function.
// It will extract the first found token from the string aux_ptr , and return
// a pointer to the beginning of the next token , or end of the string.
// It skips the initial sep characters!
__KVI_EXTERN KVILIB_API const char * kvi_extractToken(KviWStr &str,const char *aux_ptr,char sep =' ');
// Does not skip the beginning separators!
// Extracts data from the string up to the next separator character or the end of the string.
// and returns a pointer to that separator (or string end).
__KVI_EXTERN KVILIB_API const char * kvi_extractUpTo(KviWStr &str,const char *aux_ptr,char sep=' ');
// Reduced vsnprintf...
// Handles %s,%c,%d,%u  (%% are TWO percents here and not one.)
// Returns -1 if the formatted string exceeded the buffer length.
// Otherwise returns the length of the formatted buffer...(not including '\0')
__KVI_EXTERN KVILIB_API int kvi_vsnprintf(char *buffer,int len,const char *fmt,va_list list);
// Reduced vsnprintf: special version for irc.
// Handles %s,%c,%d,%u  (%% are TWO percents here and not one.)
// Writes up to 510 characters and terminates the string with a CRLF
// Sets bTruncated if the requested format string was too large to fit in 512 bytes
// otherwise sets it to false; The buffer MUST be at least 512 bytes long.
// Always returns the length of the formatted buffer...(max 512 - min 2=CRLF)
__KVI_EXTERN KVILIB_API int kvi_irc_vsnprintf(char *buffer,const char *fmt,va_list list,bool *bTruncated);

// WILDCARD EXPRESSION MATCHING FUNCTIONS

// Returns true if the two regular expressions with wildcards matches
__KVI_EXTERN KVILIB_API bool kvi_matchWildExpr(register const char *m1,register const char *m2);
// Returns true if the two regular expressions with wildcards matches, case sensitive
//__KVI_EXTERN bool kvi_matchWildExprCS(register const char *m1,register const char *m2); // actually unused
// Same as kvi_matchWildExpr but with an additional char that acts as string terminator
// If there is a match this function returns true and puts the pointers where it stopped in r1 and r2
__KVI_EXTERN KVILIB_API bool kvi_matchWildExprWithTerminator(register const char *m1,register const char *m2,char terminator,
			const char ** r1,const char ** r2);

// Returns true if the wildcard expression exp matches the string str
__KVI_EXTERN KVILIB_API bool kvi_matchString(register const char * exp,register const char * str);
__KVI_EXTERN KVILIB_API bool kvi_matchStringWithTerminator(register const char * exp,register const char * str,char terminator,const char ** r1,const char ** r2);

// This function works like a particular case of strncmp.
// It evaluates if str2 is the terminal part of str1.
// example: if str1 is "this is an experiment" and str2 is "xperiment"
// return 0.
// With the index parameter, the match start on str1 from the specified
// index. For example:
// if str1 is "this is an experiment" and str2 is "an" we have return !0
// but "this is an experiment"
//      012345678901234567890
// if we call kvi_strsubRevCS("this is an experiment","an", 9) we got a match.
__KVI_EXTERN KVILIB_API int kvi_strMatchRevCS(const char *str1, const char *str2, int index=-1);

// KviWStr comparison non-member operators
__KVI_EXTERN KVILIB_API inline bool operator==(const KviWStr &left,const KviWStr &right)
{ return (left.m_len == right.m_len) ? kvi_strEqualCS(left.m_ptr,right.m_ptr) : false; }
__KVI_EXTERN KVILIB_API inline bool operator==(const KviWStr &left,const char *right)
{ return kvi_strEqualCS(left.m_ptr,right); }
__KVI_EXTERN KVILIB_API inline bool operator==(const char *left,const KviWStr &right)
{ return kvi_strEqualCS(left,right.m_ptr); }
__KVI_EXTERN KVILIB_API inline bool operator!=(const KviWStr &left,const KviWStr &right)
{ return !kvi_strEqualCS(left.m_ptr,right.m_ptr); }
__KVI_EXTERN KVILIB_API inline bool operator!=(const KviWStr &left,const char *right)
{ return !kvi_strEqualCS(left.m_ptr,right); }
__KVI_EXTERN KVILIB_API inline bool operator!=(const char *left,const KviWStr &right)
{ return !kvi_strEqualCS(left,right.m_ptr); }

__KVI_EXTERN KVILIB_API inline KviWStr operator+(const KviWStr &left,const KviWStr &right)
{ KviWStr ret(left); ret += right; return ret; }
__KVI_EXTERN KVILIB_API inline KviWStr operator+(const KviWStr &left,const char *right)
{ KviWStr ret(left); ret += right; return ret; }
__KVI_EXTERN KVILIB_API inline KviWStr operator+(const char *left,const KviWStr &right)
{ KviWStr ret(left); ret += right; return ret; }
__KVI_EXTERN KVILIB_API inline KviWStr operator+(const KviWStr &left,char right)
{ KviWStr ret(left); ret += right; return ret; }
__KVI_EXTERN KVILIB_API inline KviWStr operator+(char left,const KviWStr &right)
{ KviWStr ret(left); ret += right; return ret; }
*/

#endif //_KVI_WSTRING_H_
