/**************************************************************************
 * Source Id :
 *
 * $Id: mystring.cpp,v 1.5 2001/04/20 10:15:01 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.cc:
 *  Operators for the variable length string class.
 *
 *  Original Author : Kev
 *
 **************************************************************************/

// FOR NOW::
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#include <ctype.h>

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

#include <diamond/mystring.h>
// #if !defined(__MSVC__)
// #pragma implementation
// #endif

const size_t CHUNKSIZE = 256;

void
DIA_EXPORT dbData::fill(const unsigned char c, size_t count)
{
	if (count == 0) {
		if (size == 0)
			return;
		else
			count = size-isstr;
	} else
		setSize(count+isstr);
	memset(data, c, (size_t)count);
	if (isstr)
		data[count] = 0;
}

dbData DIA_EXPORT operator + (const dbData& S, const unsigned char* s)
{
	dbData res(S);
	res.cat(s);
	return res;
}
dbData DIA_EXPORT operator + (const dbData& S, const dbData& s)
{
	dbData res(S);
	res.cat(s);
	return res;
}
ostream& DIA_EXPORT operator << (ostream& o, const dbData& s)
{
	if (s.isstr)
		o << (char*)s;
	else
		o.write((char*)s, (size_t)s.getSize());
	return o;
}
istream& DIA_EXPORT operator >> (istream& i, dbData& s)
{
	s.clr();
	s.setSize(CHUNKSIZE);
	size_t curLen = 0; // Speeds things up
	s[curLen] = 0;
	int c;
	if (s.isstr) {
		do {
			c = i.get();
			if (c == '\n' || c == EOF || !i.good())
				return i;
		} while (isspace(c));
		i.putback((char)c);
	}
	while (i.good()) {
		c = i.get();
		if (c == EOF || !i.good())
			break;
		else if (s.isstr)
			if (c == '\n' || isspace(c)) {
				i.putback((char)c);
				break;
			}
		if (curLen >= (uint32)s.getSize()-1)
			s.addSize(CHUNKSIZE);
		s[curLen++] = (unsigned char)c;
	}
	if (s.isstr)
		s[curLen] = 0;
	s.setSize(curLen);
	return i;
}

void
DIA_EXPORT dbData::createDbData(const dbData& D)
{
	dummyc[1] = 0;
	if (D.data) {
		size=D.len()+isstr;
		data = new unsigned char[size];
		// data = (unsigned char *)malloc(size);
		copyMem(D.data, data, (size_t)size);
	} else {
		size=0;
		data=0;
	}
}

void
DIA_EXPORT dbData::createCharPtr(const unsigned char* s)
{
	dummyc[1] = 0;
	if (s) {
		data = (unsigned char*)strDup(s);
		size = strLen(s)+1;
	} else {
		size=0;
		data=0;
	}
}

DIA_EXPORT dbData::dbData(const void* s, const size_t newlen, const char e) : isstr(e)
{
	dummyc[1] = 0;
	if (s) {
		data = new unsigned char[newlen];
		copyMem(s, (void*)data, (size_t)newlen);
		size = newlen;
	} else {
		size=0;
		data=0;
	}
}

size_t
DIA_EXPORT dbData::setSize(const size_t newLen)
{
	if (isstr && newLen < size) {
		// Nothing
	} else {
		if (data) {
			unsigned char *temp = data;
			data = new unsigned char[newLen];
			if (size < newLen)
				copyMem(temp, data, size); // Don't want to overrun data
			else
				copyMem(temp, data, newLen); // Don't want to overread temp
			delete temp;
		} else {
			data = new unsigned char[newLen];
			if (isstr) *data = 0;
		}
		size = newLen;
	}
	return size;
}

unsigned char*
DIA_EXPORT dbData::cat(const unsigned char* s)
{
	if (s) {
		size_t slen = strLen(s);
		size_t newsize = len()+slen+1; // always 1 'cos adding a string
		size_t oldsize = len();
		setSize(newsize);
		copyMem(s, data+oldsize,slen+1);
	}
	return data;
}

unsigned char*
DIA_EXPORT dbData::cat(const dbData& d)
{
	if (d.data) {
		size_t newsize = len()+d.len()+isstr;
		size_t oldsize = len();
		setSize(newsize);
		copyMem(d.data, data+oldsize, d.len()+isstr);
	}
	return data;
}

unsigned char*
DIA_EXPORT dbData::cpy(const unsigned char* s)
{
	if (s) {
		size_t slen = strLen(s);
		setSize(slen+1);
		copyMem(s, data, (size_t)(slen+1));
	} else {
		setSize(isstr);
		if (isstr)
			*data = 0;
	}
	return data;
}

unsigned char*
DIA_EXPORT dbData::cpy(const dbData& d)
{
	if (d.data) {
		setSize(d.len()+isstr);
		copyMem(d.data, data, (size_t)(d.len()+isstr));
	} else {
		setSize(isstr);
		if (isstr)
			*data = 0;
	}
	return data;
}

void
DIA_EXPORT dbData::clr(void)
{
	if (isstr) {
		if (data) {
			data[0] = 0;
		}
	} else
		dispose();
}

dbString DIA_EXPORT intTodbString(int i)
{
	strstream str;

	str << i << '\000';
	char *cp = str.str();
	dbString d(cp);
	delete [] cp;
	return d;
}

///////////////////////////////////////////////////////////////////////////
// Revision History:
//
// $Log: mystring.cpp,v $
// Revision 1.5  2001/04/20 10:15:01  georgetasker
// Cygwin compilation fixes, compilation speed enhancements
// Code modified to get rid of some compiler warnings
//
// Revision 1.4  2001/04/19 21:12:54  georgetasker
// cygwin compilation fixes
//
// Revision 1.3  2001/04/05 01:22:33  georgetasker
// Same fix for Borland as I just did for MSVC so that <strstrea.h> is used if it is either of these two compilers, otherwise use <strstream.h>
//
// Revision 1.1  2001/04/04 12:05:49  aleksandras
// forgotten diamond .cpps
//
// Revision 1.24  1996/08/22  12:42:10  dmb
// Removed interface/implementation pragmas till they work properly
//
// Revision 1.23  1996/08/20 13:25:23  daz
// Changes by Alex Zeltser to support NT using MSVC.
//
// Revision 1.22  1996/03/05  22:04:29  dmb
// removed ^M.
//
// Revision 1.21  1996/03/05  21:42:35  dmb
// Preliminary modifications to get Dos/Windows 0.4 portability.
//
// Revision 1.20  1996/02/01  22:31:57  dmb
// long->int32
// added intToDbString
//
// Revision 1.19  1995/01/22  11:42:07  kevinl
// When copying a dbData, don't overrun source or destination memory.
//
// Revision 1.18  1995/01/21  14:46:25  kevinl
// Had a bad realloc replacement. fixed.
//
// Revision 1.17  1994/12/22  03:56:28  kevinl
// s/bcopy/copyMem/g
// Lots of const and char* type fixups
//
// Revision 1.16  1994/12/12  03:51:33  kevinl
// Now using addSize instead of silly +=
//
// Revision 1.15  1994/07/19  04:19:58  darrenp
// Fixed handling of multi identifier index names.
//
// Revision 1.14  1994/05/15  04:58:56  kevinl
// Moved many inlines from .h to here to keep CC happy.
//
// Revision 1.13  1994/03/17  04:34:45  kevinl
// Added \n as separator
//
// Revision 1.12  1994/02/24  06:35:30  darrenp
// DOS/Windows modifications.
//
// Revision 1.11  1994/02/03  06:01:42  kevinl
// Moved include files to diamond/ and fixed HAVE_MALLOC_H
//
// Revision 1.10  1993/12/23  22:58:48  kevinl
// dbErr uses dbString, autoconf stuff, moved logs, added const and size_t
//
// Revision 1.9  1993/11/18  02:59:27  kevinl
// Moved logs
// Fixedaggregate type returning/passing
//
// Revision 1.8  1993/10/28  13:31:20  davison
// Changed clear() method to clr().
//
// Revision 1.7  1993/10/05  07:34:31  kevinl
// Now handles dbData AND dbString properly
//
// Revision 1.6  1993/08/29  12:56:27  kevinl
// Fixed problems of assigning relations to each other.
//
// Revision 1.5  1993/07/11  09:42:05  kevinl
// Changed String to dbString
//
// Revision 1.4  1993/07/11  08:20:42  kevinl
// Fixed >> operator. Now gets enough memory for itself.
//
// Revision 1.3  1993/06/23  05:21:22  kevinl
// Mallocs are now in angular brackets
//
// Revision 1.2  1993/06/20  13:40:01  kevinl
// Fixed multiple mallocs
// += removed and put in header
//
// Revision 1.1  1993/06/18  12:31:14  kevinl
// Initial revision
//
///////////////////////////////////////////////////////////////////////////
