// utf-8

/*	Copyright  (c)	Günter Woigk   2001-2003
  					mailto:kio@little-bat.de

	This file is free software

 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.  

 Permission to use, copy, modify, distribute, and sell this software and
 its documentation for any purpose is hereby granted without fee, provided
 that the above copyright notice appear in all copies and that both that
 copyright notice and this permission notice appear in supporting
 documentation, and that the name of the copyright holder not be used
 in advertising or publicity pertaining to distribution of the software
 without specific, written prior permission. The copyright holder makes no
 representations about the suitability of this software for any purpose.
 It is provided "as is" without express or implied warranty.

 THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 PERFORMANCE OF THIS SOFTWARE.


 ---------------------------------------------------------------------------
	
			class String

			this is a variant of the char-based (UTF-8) class String.
			+ supports UTF-8, UCS-1 (ISO Latin-1), UCS-2 and UCS-4 characters
			+ lots of conversions
			+ indexable characters (which is not possible with UTF-8 Strings)
			- slower than char-based (UTF-8) Strings

---------------------------------------------------------------------------
*/


#ifndef _string_h_
#define _string_h_

#include "kio.h"


/* ********************************************************************************
						MISC. TYPE DEFINITIONS
******************************************************************************** */

typedef unsigned char		UCS1Char;			// == uchar
typedef	UCS1Char const		cUCS1Char;			// == uchar const
typedef UCS1Char *			UCS1CharPtr;		// == uptr
typedef UCS1Char const *	cUCS1CharPtr;		// == cuptr

typedef unsigned short		UCS2Char;
typedef	UCS2Char const		cUCS2Char;
typedef UCS2Char *			UCS2CharPtr;
typedef UCS2Char const *	cUCS2CharPtr;

typedef unsigned long		UCS4Char;
typedef	UCS4Char const		cUCS4Char;
typedef UCS4Char *			UCS4CharPtr;
typedef UCS4Char const *	cUCS4CharPtr;

typedef char const *		UTF8Char;
typedef char const *		cUTF8Char;
typedef char *				UTF8CharPtr;
typedef char const *		cUTF8CharPtr;

typedef	char *				UTF8Str;			// c-style string
typedef char const *		cUTF8Str;			// c-style string literals in utf-8 encoded source files



/* ********************************************************************************
					class String
******************************************************************************** */

enum CharSize { /*utf8=0,*/ ucs1=1, ucs2=2, ucs4=4 };


class String
{
	ptr			text;
	long		count;
	CharSize	csz;

	ptr			data;			// address for delete[]
	String*		next;			// next string sharing same data
	String*		prev;			// prev string sharing same data

	void 		_init_from_utf8	( cptr p, cptr e );
	void		_init 			( );
	void 		_init 			( cString& q );
	void 		_init 			( CharSize csz, long n );
	void 		_kill			( );
	long		_compare	  	( cString& q ) const;
	void		_resize			( long newlen );
	UCS1Char*	Ucs1			( )									{ return (UCS1Char*)text; }
	UCS2Char*	Ucs2			( )									{ return (UCS2Char*)text; }
	UCS4Char*	Ucs4			( )									{ return (UCS4Char*)text; }
	cUCS1Char*	Ucs1			( )	const							{ return (cUCS1Char*)text; }
	cUCS2Char*	Ucs2			( )	const							{ return (cUCS2Char*)text; }
	cUCS4Char*	Ucs4			( ) const							{ return (cUCS4Char*)text; }

public:
				~String			( );
				String			( );

				String			( UCS4Char c );

				String   		( cUCS1Char* p, long n );
				String   		( cUCS2Char* p, long n );
				String   		( cUCS4Char* p, long n );
				String   		( cUTF8CharPtr p, long n );

				String   		( long n, CharSize sz );			// uncleared
				String   		( long n, UCS4Char c );				// cleared

				String   		( cUTF8Str s );						// string from c-string
				String   		( cString& q );						// copy creator
				String   		( cString& q, long a, long e );		// substring

	void		Truncate		( long newlen );
	void		Resize			( long newlen, UCS4Char padding=' ' );

	long		Len				( ) const							{ return count; }
	CharSize	Csz				( ) const							{ return csz; }
	UCS4Char	operator[]  	( long i ) const;

	UCS1Char*	UCS1Text		( )									{ XXXTRAP(csz!=ucs1); return Ucs1(); }
	UCS2Char*	UCS2Text		( )									{ XXXTRAP(csz!=ucs2); return Ucs2(); }
	UCS4Char*	UCS4Text		( )									{ XXXTRAP(csz!=ucs4); return Ucs4(); }
	ptr			Text			( )									{ return text; }
	cUCS1Char*	UCS1Text		( ) const							{ XXXTRAP(csz!=ucs1); return Ucs1(); }
	cUCS2Char*	UCS2Text		( ) const							{ XXXTRAP(csz!=ucs2); return Ucs2(); }
	cUCS4Char*	UCS4Text		( ) const							{ XXXTRAP(csz!=ucs4); return Ucs4(); }
	cptr		Text			( ) const							{ return text; }

	bool		IsWritable  	( ) const							{ return next==this; }
	bool		NotWritable  	( ) const							{ return next!=this; }
	void		MakeWritable	( );

	String		SubString   	( long a, long e ) const	{ return String(*this,a,e); }
	String		MidString   	( long a, long n ) const	{ return String(*this,a,a+n); }
	String		MidString		( long a ) const			{ return String(*this,a,Len()); }
	String		LeftString  	( long n ) const			{ return String(*this,0,n); }
	String		RightString 	( long n ) const			{ return String(*this,Len()-n,Len()); }

	String&		operator=   	( cString& q );

	String		operator+   	( cString& q ) const;		// concatenate strings
	String&		operator+=  	( cString& q )				{ return *this = *this + q; }

	String		operator*   	( long n ) const;			// repeat string contents n times
	String&		operator*=  	( long n )					{ return *this = *this * n; }

	bool		operator==  	( cString& q ) const		{ return count==q.count && _compare(q)==0; }
	bool		operator!=  	( cString& q ) const		{ return count!=q.count || _compare(q)!=0; }
	bool		operator<   	( cString& q ) const		{ return _compare(q)<0; }
	bool		operator>   	( cString& q ) const		{ return _compare(q)>0; }
	bool		operator>=  	( cString& q ) const		{ return _compare(q)>=0; }
	bool		operator<=  	( cString& q ) const		{ return _compare(q)<=0; }

	str			CString			( ) const;
	double		NumVal			( ) const;

	long		Find			( UCS4Char c, long startidx= 0 ) const;
	long		RFind			( UCS4Char c, long startidx= 0x7fffffff ) const;
	long		Find			( cString& s, long startidx= 0 ) const;
	long		RFind			( cString& s, long startidx= 0x7fffffff ) const;
	long		Find			( cUTF8Str s, long startidx= 0 ) const;
	long		RFind			( cUTF8Str s, long startidx= 0x7fffffff ) const;

	void		Replace     	( UCS4Char o, UCS4Char n );
	void		Swap			( UCS4Char o, UCS4Char n );

	String		ToUpper  		( )	const;
	String		ToLower  		( )	const;
	String		ToHtml			( ) const;
	String		FromHtml		( ) const;
	String		ToEscaped		( bool addquotes=no ) const;
	String		FromEscaped		( bool rmvquotes=no ) const;
	String		ToQuoted		( ) const					{ return ToEscaped(yes); }
	String		FromQuoted		( ) const					{ return FromEscaped(yes); }

friend  class   Var;
friend	void	TestStringClass	( );

static	void	PurgeCaches		( );
};



extern void		TestStringClass	( );

extern cString	emptyString;
extern String	CharString	( UCS4Char c );
extern String	SpaceString	( long n, UCS4Char c=' ' );

extern String  	NumString	( double n );
extern String  	NumString	( long n );
extern String  	NumString	( ulong n );
inline String  	NumString	( int n )						{ return NumString((long)n); }
inline String  	NumString	( uint n )						{ return NumString((ulong)n); }
extern String  	HexString	( ulong n, int digits=0 );

inline String	SubString	( cString& s, long a, long e )	{ return s.SubString(a,e); }
inline String	MidString	( cString& s, long a, long n )	{ return s.MidString(a,n); }
inline String	MidString	( cString& s, long a )			{ return s.MidString(a); }
inline String	LeftString	( cString& s, long n )			{ return s.LeftString(n); }
inline String	RightString	( cString& s, long n )			{ return s.RightString(n); }

inline String	ToUpper		( cString& s )					{ return s.ToUpper(); }
inline String	ToLower		( cString& s )					{ return s.ToLower(); }
inline String	ToHtml		( cString& s )					{ return s.ToHtml(); }
inline String	FromHtml	( cString& s )					{ return s.FromHtml(); }
inline String	ToQuoted	( cString& s )					{ return s.ToQuoted(); }
inline String	FromQuoted	( cString& s )					{ return s.FromQuoted(); }
inline String	ToEscaped	( cString& s, bool f=no )		{ return s.ToEscaped(f); }
inline String	FromEscaped	( cString& s, bool f=no )		{ return s.FromEscaped(f); }

inline str		CString		( cString& s )					{ return s.CString(); }
inline double	NumVal		( cString& s )					{ return s.NumVal(); }

#endif



























