/**************************************************************************
 * Source Id :
 *
 * $Id: mystring.h,v 1.2 2001/04/19 10:10:28 georgetasker Exp $
 *-------------------------------------------------------------------------
 * Project Notes :
 *
 *  Diamond Base
 *  ============
 *      A solid database implementation, spurred on by the continuing
 *  Metal (Lead) Base saga.
 *
 *  Project Team :
 *        A. Davison
 *        K. Lentin
 *        D. Platt
 *
 *	Project Commenced : 05-02-1993
 *
 *-------------------------------------------------------------------------
 *  Module Notes :
 *
 *  mystring.h:
 *  A the variable length string class for variable length records
 *
 *  Original Author : Kev
 *
 **************************************************************************/

// #if !(defined _MSC_VER || defined(__BORLAND_C__))
// #pragma implementation
// #endif
#ifndef __DB_MYSTRING_H__
#define __DB_MYSTRING_H__

#include <diamond/dbconf.h>

//#if !defined(__MSVC__)
//#pragma interface     
//#endif

#if HAVE_STDLIB_H
#include <stdlib.h>
#endif

#if HAVE_MALLOC_H && !MALLOC_H_INCLUDED
extern "C" {
#include <malloc.h>
}
#define MALLOC_H_INCLUDED 1
#endif

#if defined(__BORLAND_C__) || defined(_MSC_VER)
#include <strstrea.h>
#else 
#include <strstream.h>
#endif

#include <string.h>
#include <diamond/defs.h>


inline int
strCmp(const unsigned char* s1, const unsigned char* s2)
{
	return strcmp((const char*)s1,(const char*)s2);
}
inline int
strCmp(const char* s1, const char* s2)
{
	return strcmp(s1, s2);
}
inline int
strLen(const unsigned char* s)
{
	return strlen((const char*)s);
}
inline int
strLen(const char* s)
{
	return strlen(s);
}
inline unsigned char*
strDup(const unsigned char* s)
{
	unsigned char* s1 = new unsigned char[strLen(s)+1];
	strcpy((char*)s1,(const char*)s);
	return s1;
}
inline char*
strDup(const char* s)
{
	unsigned char* s1 = new unsigned char[strLen(s)+1];
	strcpy((char*)s1,(const char*)s);
	return (char*)s1;
}
#ifndef __BROKEN_SIGNED_CHAR
inline int
strCmp(const signed char* s1, const signed char* s2)
{
	return strcmp((const char*)s1,(const char*)s2);
}
inline int
strLen(const signed char* s)
{
	return strlen((const char*)s);
}
inline signed char*
strDup(const signed char* s)
{
	return (signed char*)strDup((const unsigned char*)s);
}
#endif

class dbString;

class dbData
{

	friend class dbString;

	unsigned char dummyc[2];
	unsigned char isstr; // Extra space needed on end of data
	size_t size;  // How much memory do we need for the char*;
public:
	unsigned char *data;  // The data being played with

	const char* verStr(void) { return "$Id"; }
	dbData(const unsigned char e = 0) : isstr(e) { data=0; size=0; }
	dbData(const dbData& D) : isstr(D.isstr) { createDbData(D); }
	dbData(const dbData& D, const char e) : isstr(e) { createDbData(D); }
	dbData(const char* s, const unsigned char e = 0) : isstr(e) { createCharPtr((const unsigned char*)s); }
	dbData(const unsigned char* s, const unsigned char e = 0) : isstr(e) { createCharPtr(s); }
#ifndef __BROKEN_SIGNED_CHAR
	dbData(const signed char* s, const unsigned char e = 0) : isstr(e) { createCharPtr((const unsigned char*)s); }
#endif
	void createDbData(const dbData& D);
	void createCharPtr(const unsigned char* s);
	dbData(const void* s, const size_t newlen, const char e = 0);
	~dbData(void) { if (data) delete data; data=0; size=0; }
	size_t len(void) const { return (isstr)?(data?strLen(data):0):size; }
	size_t storage(void) const { return (isstr)?(data?strLen(data)+1:0):size; }
	size_t setSize(const size_t newLen);
	int32 getSize(void) const
	{
		return size;
	}
	unsigned char* cat(const unsigned char* s);
	char* cat(const char* s) { return (char*)cat((const unsigned char*)s); }
#ifndef __BROKEN_SIGNED_CHAR
	signed char* cat(const signed char* s) { return (signed char*)cat((const unsigned char*)s); }
#endif
	unsigned char* cat(const dbData& d);
	unsigned char* cpy(const unsigned char* s);
	char* cpy(const char* s) { return (char*)cpy((const unsigned char*) s); }
#ifndef __BROKEN_SIGNED_CHAR
	signed char* cpy(const signed char* s) { return (signed char*)cpy((const unsigned char*) s); }
#endif
	unsigned char* cpy(const dbData& d);
	void fill(const unsigned char c, size_t count = 0);
	void fill(const char c, size_t count = 0) { fill((const unsigned char)c, count); }
#ifndef __BROKEN_SIGNED_CHAR
	void fill(const signed char c, size_t count = 0) { fill((const unsigned char)c, count); }
#endif
	void clr(void);
	void dispose(void) { if (data) delete data; data=0; size=0; }
	operator char*() const { return (char*)data; }
	operator const char*() const { return (const char*)data; }
	operator unsigned char*() const { return (unsigned char*)data; }
	operator const unsigned char*() const { return (const unsigned char*)data; }
#ifndef __BROKEN_SIGNED_CHAR
	operator signed char*() const { return (signed char*)data; }
	operator const signed char*() const { return (const signed char*)data; }
#endif
	operator void*() const { return (void*)data; }
	operator const void*() const { return (const void*)data; }
	bool empty(void) const { return (bool)((data == 0) || (*data==0)); }
	friend dbData operator + (const dbData& S, const unsigned char* s);
	friend dbData operator + (const dbData& S, const char* s);
#ifndef __BROKEN_SIGNED_CHAR
	friend dbData operator + (const dbData& S, const signed char* s);
#endif
	friend dbData operator + (const dbData& S, const dbData& s);
	friend ostream& operator << (ostream& o, const dbData& s);
	friend istream& operator >> (istream& i, dbData& s);
	unsigned char& operator [] (size_t i) { 
		if (data && i < size) {
			return (unsigned char &)data[i];
		} else {
			return (unsigned char &)dummyc[0];
		}
	}
	dbData& operator = (const unsigned char* s)
	{
		cpy(s);
		return *this;
	}
	dbData& operator = (const char* s) { return (*this) = (const unsigned char*)s; }
#ifndef __BROKEN_SIGNED_CHAR
	dbData& operator = (const signed char* s) { return (*this) = (const unsigned char*)s; }
#endif
	dbData& operator = (const dbData& d)
	{
		cpy(d);
		return *this;
	}
	dbData& operator = (const char c)
	{
		dummyc[0] = c;
		dummyc[1] = 0;
		cpy(dummyc);
		return *this;
	}
	dbData& operator += (const unsigned char* s)
	{
		cat(s);
		return *this;
	}
	dbData& operator += (const char* s) { return (*this) += (const unsigned char*)s; }
#ifndef __BROKEN_SIGNED_CHAR
	dbData& operator += (const signed char* s) { return (*this) += (const unsigned char*)s; }
#endif
	dbData& operator += (const dbData& d)
	{
		cat(d);
		return *this;
	}
	dbData& operator += (const char c)
	{
		dummyc[0] = c;
		dummyc[1] = 0;
		cat(dummyc);
		return *this;
	}
#if 0
	int32 operator = (const int32 s)
	{
		int32 sz = setSize(s);
		if (isstr && s)
			data[s-1] = 0;
		return sz;
	}
#endif
//	int32 operator += (const size_t s)
	size_t addSize(const size_t s)
	{
		return setSize(size+s);
	}
//	int32 operator -= (const size_t s)
	size_t subSize(size_t s)
	{
		if (s > size)
			s = size;
		s = size - s;
		size_t sz = setSize(s);
		if (isstr && s)
			data[s-1] = 0;
		return sz;
	}
};

inline dbData operator + (const dbData& S, const char* s)
	{ return operator +(S, (const unsigned char*)s); };
#ifndef __BROKEN_SIGNED_CHAR
inline dbData operator + (const dbData& S, const signed char* s)
	{ return operator +(S, (const unsigned char*)s); };
#endif

class dbString : public dbData
{
public:
	dbString(void) : dbData(1) { }
	dbString(const dbData& D) : dbData((char*)D, 1) { }
	dbString(const dbString& D) : dbData(D, 1) { }
	dbString(const char* s) : dbData(s, 1) { }
	dbString(const unsigned char* s) : dbData(s, 1) { }
#ifndef __BROKEN_SIGNED_CHAR
	dbString(const signed char* s) : dbData(s, 1) { }
#endif
	dbString& operator = (const unsigned char* s)
	{
		cpy(s);
		return *this;
	}
	dbString& operator = (const char* s) { return (*this) = (const unsigned char*)s; }
#ifndef __BROKEN_SIGNED_CHAR
	dbString& operator = (const signed char* s) { return (*this) = (const unsigned char*)s; }
#endif

	dbString& operator = (const dbData& d)
	{
		cpy(d);
		return *this;
	}
	dbData& operator = (const char c)
	{
		dummyc[0] = c;
		dummyc[1] = 0;
		cpy(dummyc);
		return *this;
	}
	int operator == (const unsigned char* str)
	{
		return !strCmp(data, str);
	}
	int operator == (const char* str) { return (*this) == (const unsigned char*) str; }
#ifndef __BROKEN_SIGNED_CHAR
	int operator == (const signed char* str) { return (*this) == (const unsigned char*) str; }
#endif
	int operator != (const unsigned char* str)
	{
		return strCmp(data, str);
	}
	int operator != (const char* str) { return (*this) != (const unsigned char*) str; }
#ifndef __BROKEN_SIGNED_CHAR
	int operator != (const signed char* str) { return (*this) != (const unsigned char*) str; }
#endif
	int operator == (const dbString& d)
	{
		return !strCmp(data, d);
	}
	int operator != (const dbString& d)
	{
		return strCmp(data, d);
	}
	int operator > (const dbString& d)
	{
		return (strCmp(data, d) > 0);
	}
	int operator < (const dbString& d)
	{
		return (strCmp(data, d) < 0);
	}
	int operator > (const unsigned char* str)
	{
		return (strCmp(data, str) > 0);
	}
	int operator > (const char* str) { return (*this) > (const unsigned char*) str; }
#ifndef __BROKEN_SIGNED_CHAR
	int operator > (const signed char* str) { return (*this) > (const unsigned char*) str; }
#endif
	int operator < (const unsigned char* str)
	{
		return (strCmp(data, str) < 0);
	}
	int operator < (const char* str) { return (*this) < (const unsigned char*) str; }
#ifndef __BROKEN_SIGNED_CHAR
	int operator < (const signed char* str) { return (*this) < (const unsigned char*) str; }
#endif
	int operator >= (const unsigned char* str)
	{
		return !operator < (str);
	}
	int operator >= (const char* str) { return (*this) >= (const unsigned char*) str; }
#ifndef __BROKEN_SIGNED_CHAR
	int operator >= (const signed char* str) { return (*this) >= (const unsigned char*) str; }
#endif
	int operator <= (const unsigned char* str)
	{
		return !operator > (str);
	}
	int operator <= (const char* str) { return (*this) <= (const unsigned char*) str; }
#ifndef __BROKEN_SIGNED_CHAR
	int operator <= (const signed char* str) { return (*this) <= (const unsigned char*) str; }
#endif
	int operator >= (const dbString& d)
	{
		return !operator < (d);
	}
	int operator <= (const dbString& d)
	{
		return !operator > (d);
	}
};

dbString intTodbString(int i);
#endif

///////////////////////////////////////////////////////////////////////////
// Revision History:
//
// $Log: mystring.h,v $
// Revision 1.2  2001/04/19 10:10:28  georgetasker
// Fixed strstrea.h for Borland C, though I don't think this #include matters here
//
// Revision 1.1  2001/04/03 20:10:26  aleksandras
// big one 3.1 (comments later)
//
// Revision 1.47  1996/08/22  12:42:10  dmb
// Removed interface/implementation pragmas till they work properly
//
// Revision 1.46  1996/08/22 11:47:00  dmb
// Silenced pragma
//
// Revision 1.45  1996/08/06  10:46:07  daz
// Changes to incorporate the 'byte' type and the Windows NT patches.
//
// Revision 1.44  1996/06/21  13:20:43  daz
// Added necessary #pragma for GNU.
//
// Revision 1.43  1996/03/05  22:04:29  dmb
// removed ^M.
//
// Revision 1.42  1996/03/05  21:42:35  dmb
// Preliminary modifications to get Dos/Windows 0.4 portability.
//
// Revision 1.41  1996/02/01  23:04:14  dmb
// int32 changes and added intTodbString
//
// Revision 1.40  1995/06/27  13:27:16  kevinl
// Fixes to repair the gcc 2.7.0 carnage:
// modified for loop local variable scope semantics
// some new errors invented.
// moved some inline friends out of classes (stoopid - mystring)
// Modified the setUnique generated member
//
// Revision 1.39  1995/06/26  01:36:38  kevinl
// Moved some inline friends out of the class
//
// Revision 1.38  1995/02/08  05:39:39  kevinl
// Added some const conversions
//
// Revision 1.37  1995/01/22  11:41:34  kevinl
// It's good to remember to actually do a copy in strDup.
//
// Revision 1.36  1995/01/21  14:46:42  kevinl
// Added storage() member
//
// Revision 1.35  1994/12/22  03:56:54  kevinl
// Added strCpy, strLen etc.
// Made unsigned char* the default char format and cast _to_ that.
//
// Revision 1.34  1994/12/12  03:51:27  kevinl
// stdlib.h
//
// Revision 1.33  1994/09/07  07:58:37  kevinl
// added stdlib.h
//
// Revision 1.32  1994/05/15  05:07:23  kevinl
// Type fixups. Moved out some inline functions into .cc
//
// Revision 1.31  1994/02/25  03:13:55  darrenp
// Changes for DOS binary compatibility.
//
// Revision 1.29  1994/02/03  05:54:19  kevinl
// Moved include files to diamond/ and fixed HAVE_MALLOC_H
//
// Revision 1.28  1994/01/11  22:58:09  kevinl
// OK OK. So empty is when there's nothing there. Big deal. Only 50% wrong.
//
// Revision 1.27  1993/12/23  22:58:48  kevinl
// dbErr uses dbString, autoconf stuff, moved logs, added const and size_t
//
// Revision 1.26  1993/11/30  03:23:31  kevinl
// More operators
//
// Revision 1.25  1993/11/18  02:59:27  kevinl
// Moved logs
// Fixedaggregate type returning/passing
//
// Revision 1.24  1993/11/09  00:26:49  davison
// added != operator to dbString
//
// Revision 1.23  1993/11/05  12:45:05  kevinl
// Fixed problems that CC picked up (and some multi bugs)
//
// Revision 1.22  1993/10/28  13:31:20  davison
// Changed clear() method to clr().
//
// Revision 1.21  1993/10/24  15:36:12  kevinl
// A spelling error and a dbString copy constructor
//
// Revision 1.20  1993/10/24  11:43:46  davison
// Fixed up operator +=(char) and operator =(char).
// They now ensure that dummyc[1] = 0.
//
// Revision 1.19  1993/10/24  10:09:38  kevinl
// Removed a const
//
// Revision 1.18  1993/10/24  09:14:48  kevinl
// dummyc is now a char[2] so we can remove the aggregate initialiser
// from the char operators
//
// Revision 1.17  1993/10/19  11:59:05  kevinl
// copying (char*)0 or a totally empty dbData/dbString now truncates
//
// Revision 1.16  1993/10/18  09:07:23  davison
// Killed unsigned int manipulations.
// Added addSize & subSize.
// Added char concatination method.
//
// Revision 1.15  1993/10/18  05:55:51  davison
// Added a string comparison operator to dbString. Compiled ok. Hope it
// works :-)
//
// Revision 1.14  1993/10/05  07:34:31  kevinl
// Now handles dbData AND dbString properly
//
// Revision 1.13  1993/09/26  08:34:32  kevinl
// Fixed ambiguous constructors
//
// Revision 1.12  1993/08/29  12:56:27  kevinl
// Fixed problems of assigning relations to each other.
//
// Revision 1.11  1993/07/20  12:59:30  kevinl
// Some unisgned int vs int32 problems
//
// Revision 1.10  1993/07/19  11:57:58  kevinl
// Added some dummy cahrs to remove Borland warnings re temporaries
// Added some {} to remove Borland's confusion about multiple if/elses
//
// Revision 1.9  1993/07/13  00:18:08  kevinl
// We weren't setting size in cat/cpy johnb@kea.grace.cri.nz (John Burnell)
//
// Revision 1.8  1993/07/11  10:49:21  kevinl
// dbString version
//
// Revision 1.7  1993/07/11  09:42:05  kevinl
// Changed String to dbString
//
// Revision 1.6  1993/07/11  08:20:17  kevinl
// Fixed [] operator
// Added CHUNKSIZE
//
// Revision 1.5  1993/07/09  06:26:52  kevinl
// Made some operators that take String
//
// Revision 1.4  1993/07/09  03:57:55  kevinl
// Removed realloc of null pointers.
//
// Revision 1.3  1993/06/20  23:29:05  kevinl
// Added -=
//
// Revision 1.2  1993/06/20  13:38:27  kevinl
// Fixed multiple mallocs
// int32s now unsigned int, cat/cpy return the string
// added fill, =,+= unsigned int and moved += operator in
//
// Revision 1.1  1993/06/18  12:31:14  kevinl
// Initial revision
//
///////////////////////////////////////////////////////////////////////////
