diff options
Diffstat (limited to 'xbase64/xbfields.cpp')
-rwxr-xr-x | xbase64/xbfields.cpp | 672 |
1 files changed, 672 insertions, 0 deletions
diff --git a/xbase64/xbfields.cpp b/xbase64/xbfields.cpp new file mode 100755 index 0000000..d3e2388 --- /dev/null +++ b/xbase64/xbfields.cpp @@ -0,0 +1,672 @@ +/* xbfields.cpp + + Xbase64 project source code + + This file contains the basic X-Base routines for reading and writing + Xbase fields. + + Copyright (C) 1997,2003 Gary A Kunkel + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser 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 + + + Contact: + + Email: + + xdb-devel@lists.sourceforge.net + xdb-users@lists.sourceforge.net + + + Regular Mail: + + XBase Support + 149C South Main St + Keller Texas, 76248 + USA +*/ + +#ifdef __WIN32__ +#include <xbase64/xbwincfg.h> +#else +#include <xbase64/xbconfig.h> +#endif + +#include <xbase64/xbase64.h> + +/*! \file xbfields.cpp +*/ +/************************************************************************/ +/* This function returns true if the data is valid logical data */ +//! Determines if data is valid logical data. +/*! Determines if the data in buf is valid for a logical field value. + + \param buf data to be tested + \returns TRUE (non-zero) if valid, FALSE (zero) if not. +*/ +xbShort xbDbf::ValidLogicalData(const char * buf) { + if( buf[0] ) + if( buf[0] == 'T' || buf[0] == 't' || buf[0] == 'F' || buf[0] == 'f' || + buf[0] == 'Y' || buf[0] == 'y' || buf[0] == 'N' || buf[0] == 'n' || + buf[0] == '?' ) + return 1; + return 0; +} +/************************************************************************/ +/* This function returns true if the data is valid numeric data */ +//! Determines if data is valid numeric data. +/*! Determines if the data in buf is valid for a numeric field value. + + \param buf + \returns TRUE (non-zero) if valid, FALSE (zero) if not. +*/ +xbShort xbDbf::ValidNumericData(const char * buf) { + const char *p; + + p = buf; + while( *p ){ + if( *p != '+' && *p != '-' && *p != '.' && *p != '0' && *p != '1' && + *p != '2' && *p != '3' && *p != '4' && *p != '5' && *p != '6' && + *p != '7' && *p != '8' && *p != '9' ) + return 0; + else + p++; + } + return 1; +} +/************************************************************************/ +/* This function returns a fields length */ +//! Returns the length of the specified field. +/*! Returns the length of the field specified by FieldNo. + + \param FieldNo Number of field. + \returns Length of the specified field in bytes. +*/ +xbShort xbDbf::GetFieldLen( xbShort FieldNo ) +{ + if( FieldNo >= 0 && FieldNo < NoOfFields ){ + if( SchemaPtr[FieldNo].Type == 'C' && SchemaPtr[FieldNo].NoOfDecs > 0 ) + return SchemaPtr[FieldNo].LongFieldLen; + else + return SchemaPtr[FieldNo].FieldLen; + } + else + return 0; +} +/************************************************************************/ +/* This function returns a fields decimal length */ +//! Returns the number of decimals in the specified field. +/*! Returns the number of decimals in the field specified by FieldNo. + + \param FieldNo Number of field. + \returns Length of the specified field in bytes. +*/ + +xbShort xbDbf::GetFieldDecimal( xbShort FieldNo ) +{ + if( FieldNo >= 0 && FieldNo < NoOfFields ) + return SchemaPtr[FieldNo].NoOfDecs; + else + return 0; +} +/************************************************************************/ +/* This function returns a fields type */ +//! Returns the type of the specified field. +/*! Returns the type of the field specified by FieldNo. + + \param FieldNo Number of field. + \returns Type of specified field. +*/ +char xbDbf::GetFieldType( xbShort FieldNo ) const +{ + if( FieldNo >= 0 && FieldNo < NoOfFields ) + return SchemaPtr[FieldNo].Type; + else + return 0; +} +/************************************************************************/ +/* This function returns a fields name */ +//! Returns the name of the specified field. +/*! Returns a pointer to the name for the field specified by FieldNo. + + \param FieldNo Number of field. + \returns A pointer to the name of the field. +*/ +char * xbDbf::GetFieldName( xbShort FieldNo ) +{ + if( FieldNo >= 0 && FieldNo < NoOfFields ) + return SchemaPtr[FieldNo].FieldName; + else + return 0; +} +/************************************************************************/ +/* This function returns the field ID number for a given field + or -1 if the field is not one of the fields of the database */ +//! Returns the field number of the specified field. +/*! Returns the field number for the named field. + + \param name Name of field. + \returns Number of field named name. +*/ +xbShort xbDbf::GetFieldNo( const char * name ) const +{ + int i, len1, len2; + + if(( len1 = strlen( name )) > 10 ) + return -1; + + for( i = 0; i < NoOfFields; i++ ){ + len2 = strlen( SchemaPtr[i].FieldName ); + if( len1 == len2 ) + +//#ifndef __WIN32__ +#ifdef HAVE_STRCASECMP + if(!strcasecmp( SchemaPtr[i].FieldName, name )) +#else + if(!stricmp( SchemaPtr[i].FieldName, name )) +#endif + + return i; + } + return -1; +} +/************************************************************************/ +/* + Helpers +*/ + +//! Get the value of the specified field. +/*! Get the value of the field referenced by Name and place its value + in buf. + + \param Name Name of field. + \param buf Buffer to hold field value. Must be large enough to hold + the entire field value. Use GetFieldLen() to determine + the length of the field, if necessary. + \param RecBufSw + \returns One of the following: +*/ +xbShort xbDbf::GetField(const char *Name, char *buf, + const xbShort RecBufSw ) const +{ + return GetField(GetFieldNo(Name), buf, RecBufSw); +} + +/************************************************************************/ +//! Get the value of the specified field. +/*! Get the value of the field specified by Name and place its value + in buf. + + \param Name Name of field. + \param buf Buffer to hold field value. Must be large enough to hold + the entire field value. Use GetFieldLen() to determine + the length of the field, if necessary. + \returns One of the following: +*/ +xbShort xbDbf::GetField(const char *Name, char *buf) const +{ + return GetField(GetFieldNo(Name), buf); +} +/************************************************************************/ +//! Get the raw value of the specified field. +/*! Get the value of the field specified by Name and place its value + in buf. + + \param Name Name of field. + \param buf Buffer to hold field value. Must be large enough to hold + the entire field value. Use GetFieldLen() to determine + the length of the field, if necessary. + \returns One of the following: +*/ +xbShort xbDbf::GetRawField(const char *Name, char *buf) const +{ + return GetRawField(GetFieldNo(Name), buf); +} + +/************************************************************************/ + +// FIXME this function doesn't follow look and feel of the rest of the lib +// GAK + +static char __buf[1024]; + +static void trim(char *s) { + int len = strlen(s)-1; + if (len > 0) { + while ((len != 0) && (s[len] == ' ')) + len--; + s[len+1] = 0; + } +} + +//! Get the value of the specified field. +/*! Returns the value of the field specified by Name. + + \param Name Name of field. + \returns Value of the specified field. +*/ +const char *xbDbf::GetField(const char *Name) const { + GetField(GetFieldNo(Name), __buf); + trim(__buf); + return __buf; +} + +//! Get the value of the specified field. +/*! Returns the value of the field specified by FieldNo. + + \param FieldNo Number of field. + \returns Value of the specified field. +*/ +const char *xbDbf::GetField(xbShort FieldNo) const { + GetField(FieldNo, __buf); + trim(__buf); + return __buf; +} +/************************************************************************/ +/* This function fills a buffer with data from the record buffer + for a particular field number. + + Use GetFieldNo to get a number based on a field's name + + If successful, this function returns the field size. +*/ + +//! Get the value of the specified field. +/*! Get the value of the field specified by FieldNo and place its value + in buf. + + \param FieldNo Number of field. + \param buf Buffer to hold field value. Must be large enough to hold + the entire field value. Use GetFieldLen() to determine + the length of the field, if necessary. + \param RecBufSw + \returns The length of the field. +*/ +xbShort xbDbf::GetField( xbShort FieldNo, char * buf, xbShort RecBufSw) const +{ + xbShort length; + if( FieldNo < 0 || FieldNo >= NoOfFields ) { + buf[0] = 0x00; + return 0x00; + } + +// Check for existence of a long field length + if( SchemaPtr[FieldNo].Type == 'C' && SchemaPtr[FieldNo].NoOfDecs > 0 ) + length = SchemaPtr[FieldNo].LongFieldLen; + else + length = SchemaPtr[FieldNo].FieldLen; + + if( RecBufSw ) + memcpy( buf, SchemaPtr[FieldNo].Address2, length ); + else + memcpy( buf, SchemaPtr[FieldNo].Address, length ); + buf[length] = 0x00; + return( length ); +} +/************************************************************************/ +xbShort xbDbf::GetField( xbShort FieldNo, xbString & sf, xbShort RecBufSw) const +{ + xbShort length; + if( FieldNo < 0 || FieldNo >= NoOfFields ) { + sf = ""; + return 0; + } + + // Check for existence of a long field length + if( SchemaPtr[FieldNo].Type == 'C' && SchemaPtr[FieldNo].NoOfDecs > 0 ) + length = SchemaPtr[FieldNo].LongFieldLen; + else + length = SchemaPtr[FieldNo].FieldLen; + + if( RecBufSw ) + sf.assign( xbString(SchemaPtr[FieldNo].Address2, length), 0, length ); + else + sf.assign( xbString(SchemaPtr[FieldNo].Address, length), 0, length ); + + return( length ); +} +/************************************************************************/ +/* This function fills a field in the record buffer with data from + a buffer for a particular field. + + Use GetFieldNo to get a number based on a field's name + + Field type N or F is loaded as right justified, left blank filled. + Other fields are loaded as left justified, right blank filled. + + This method does check the data's validity. + + If successful, this function returns 0, if invalid data, it returns -1 + or XB_INVALID_FIELDNO +*/ + +//! Put a value into the specified field. +/*! +*/ +xbShort xbDbf::PutField(const char *Name, const char *buf) { + return PutField(GetFieldNo(Name), buf); +} +/************************************************************************/ +//! Put a raw value into the specified field. +/*! +*/ +xbShort xbDbf::PutRawField(const char *Name, const char *buf) { + return PutRawField(GetFieldNo(Name), buf); +} +/************************************************************************/ +//! Put a value into the specified field. +/*! +*/ +xbShort xbDbf::PutField(const xbShort FieldNo, const char *buf) { + xbShort len, i; + char * startpos; + char * tp; /* target pointer */ + const char * sp; /* source pointer */ + + if( FieldNo < 0 || FieldNo >= NoOfFields ) + return XB_INVALID_FIELDNO; + + if( DbfStatus != XB_UPDATED ){ + DbfStatus = XB_UPDATED; + memcpy( RecBuf2, RecBuf, RecordLen ); + } + + if( SchemaPtr[FieldNo].Type == 'L' && !ValidLogicalData( buf )) + return XB_INVALID_DATA; + + else if(( SchemaPtr[FieldNo].Type == 'F' || SchemaPtr[FieldNo].Type == 'N' ) + && !ValidNumericData( buf )) + return XB_INVALID_DATA; + + else if( SchemaPtr[FieldNo].Type == 'D' ){ + xbDate d; + if( !d.DateIsValid( buf )) + return XB_INVALID_DATA; + } + + if( SchemaPtr[FieldNo].Type == 'C' && SchemaPtr[FieldNo].NoOfDecs > 0 ) + memset( SchemaPtr[FieldNo].Address, 0x20, SchemaPtr[FieldNo].LongFieldLen ); + else + memset( SchemaPtr[FieldNo].Address, 0x20, SchemaPtr[FieldNo].FieldLen ); + + len = strlen( buf ); + + if(( SchemaPtr[FieldNo].Type == 'N' || SchemaPtr[FieldNo].Type == 'F') + && len > SchemaPtr[FieldNo].FieldLen ) + return XB_INVALID_DATA; + else if( len > SchemaPtr[FieldNo].FieldLen ) + len = SchemaPtr[FieldNo].FieldLen; + + if( SchemaPtr[FieldNo].Type == 'F' || SchemaPtr[FieldNo].Type == 'N' + || SchemaPtr[FieldNo].Type == 'M') { + + const char *sdp = strchr( buf, '.' ); /* source decimal point */ + len = 0; + sp =buf; + while( *sp && *sp != '.' ) { len++; sp++; } + if( SchemaPtr[FieldNo].NoOfDecs > 0 ){ + /* do the right of decimal area */ + tp = SchemaPtr[FieldNo].Address; + tp += SchemaPtr[FieldNo].FieldLen - SchemaPtr[FieldNo].NoOfDecs - 1; + *tp++ = '.'; + sp = sdp; + if( sp ) sp++; + for( i = 0; i < SchemaPtr[FieldNo].NoOfDecs; i++ ) + if( sp && *sp ) *tp++ = *sp++; else *tp++ = '0'; + + startpos= SchemaPtr[FieldNo].Address + + SchemaPtr[FieldNo].FieldLen - + SchemaPtr[FieldNo].NoOfDecs - len - 1; + } + else + { + startpos=SchemaPtr[FieldNo].Address+SchemaPtr[FieldNo].FieldLen-len; + } + } + else + startpos = SchemaPtr[FieldNo].Address; + + memcpy( startpos, buf, len ); + return 0; +} + +/************************************************************************/ +//! Put a raw value into the specified field. +/*! +*/ +xbShort xbDbf::PutRawField(const xbShort FieldNo, const char *buf) { + xbShort len; + char * startpos; + + if( FieldNo < 0 || FieldNo >= NoOfFields ) + return XB_INVALID_FIELDNO; + + if( DbfStatus != XB_UPDATED ){ + DbfStatus = XB_UPDATED; + memcpy( RecBuf2, RecBuf, RecordLen ); + } + + startpos = SchemaPtr[FieldNo].Address; + len = SchemaPtr[FieldNo].FieldLen; + memcpy( startpos, buf, len ); + + return 0; +} + +/************************************************************************/ +//! Get the value of the specified field. +/*! +*/ +xbShort xbDbf::GetField( xbShort FieldNo, char *buf) const { + return GetField(FieldNo, buf, 0); +} +/************************************************************************/ +//! Get the raw value of the specified field. +/*! +*/ +xbShort xbDbf::GetRawField( xbShort FieldNo, char *buf ) const { + return GetField(FieldNo, buf, 0); +} +/************************************************************************/ +//! Get the long value of the specified field. +/*! +*/ +xbLong xbDbf::GetLongField( xbShort FieldNo ) const +{ + char buf[18]; + memset( buf, 0x00, 18 ); + GetField( FieldNo, buf ); + return atol( buf ); +} +/************************************************************************/ +//! Get the long value of the specified field. +/*! +*/ +xbLong xbDbf::GetLongField( const char * FieldName ) const +{ + return( GetLongField( GetFieldNo( FieldName ))); +} +/************************************************************************/ +//! Put a long value into the specified field. +/*! +*/ +xbShort xbDbf::PutLongField( xbShort FieldNo, xbLong Val ) +{ + char buf[18]; + memset( buf, 0x00, 18 ); + sprintf( buf, "%ld", Val ); + return( PutField( FieldNo, buf )); +} +/************************************************************************/ +//! Put a long value into the specified field. +/*! +*/ +xbShort xbDbf::PutLongField(const char *FieldName, xbLong Val) { + return ( PutLongField( GetFieldNo( FieldName ), Val )); +} +/************************************************************************/ +//! Get the float value of the specified field. +/*! +*/ +xbFloat xbDbf::GetFloatField( xbShort FieldNo ) +{ + char buf[21]; + memset( buf, 0x00, 21 ); + if( GetField( FieldNo, buf ) != 0 ) + return atof( buf ); + else + return 0; +} +/************************************************************************/ +//! Get the float value of the specified field. +/*! +*/ +xbFloat xbDbf::GetFloatField(const char * FieldName) { + xbShort fnum; + if((fnum = GetFieldNo(FieldName)) != -1) + return GetFloatField(fnum); + else + return 0; +} +/************************************************************************/ +//! Put a float value into the specified field. +/*! +*/ +xbShort xbDbf::PutFloatField( xbShort FldNo, xbFloat f ) +{ + char buf[25]; + char buf2[12]; + memset( buf, 0x00, 25 ); + memset( buf2, 0x00, 12 ); + sprintf( buf, "%d.%df", GetFieldLen( FldNo ), GetFieldDecimal( FldNo )); + strcpy( buf2, "%-" ); + strcat( buf2, buf ); + sprintf( buf, buf2, f ); + + /* remove trailing space */ + xbShort i = 0; + while( i < 25 ) + if( buf[i] == 0x20 ){ + buf[i] = 0x00; + break; + } else + i++; + return PutField( FldNo, buf ); +} +/************************************************************************/ +//! Put a float value into the specified field. +/*! +*/ +xbShort xbDbf::PutFloatField(const char *FieldName, xbFloat f) { + xbShort fnum; + if ((fnum = GetFieldNo(FieldName)) != -1) + return PutFloatField(fnum, f); + else + return 0; +} +/************************************************************************/ +//! Get the double value of the specified field. +/*! +*/ +xbDouble xbDbf::GetDoubleField( xbShort FieldNo, xbShort RecBufSw ) +{ + char buf[21]; + memset( buf, 0x00, 21 ); + if( GetField( FieldNo, buf, RecBufSw ) != 0 ) + return strtod( buf, NULL ); + else + return 0; +} +/************************************************************************/ +//! Get the double value of the specified field. +/*! +*/ +xbDouble xbDbf::GetDoubleField(const char *FieldName) { + xbShort fnum; + if ((fnum = GetFieldNo(FieldName)) != -1) + return GetDoubleField(fnum); + else + return 0; +} +/************************************************************************/ +//! Put a double value into the specified field. +/*! +*/ +xbShort xbDbf::PutDoubleField( xbShort FieldNo, xbDouble d) { + return PutFloatField(FieldNo, (xbFloat)d); +} +/************************************************************************/ +//! Put a double value into the specified field. +/*! +*/ +xbShort xbDbf::PutDoubleField(const char *FieldName, xbDouble d) { + xbShort fnum; + if ((fnum = GetFieldNo(FieldName)) != -1) + return PutFloatField(fnum, (xbFloat)d); + else + return 0; +} +/************************************************************************/ +//! Get the logical value of the specified field. +/*! +*/ +xbShort xbDbf::GetLogicalField( xbShort FieldNo ) +{ + char buf[3]; + if( GetFieldType( FieldNo ) != 'L' ) return -1; + memset( buf, 0x00, 3 ); + GetField( FieldNo, buf ); + if( buf[0] == 'Y' || buf[0] == 'y' || buf[0] == 'T' || buf[0] == 't' ) + return 1; + else + return 0; +} +/************************************************************************/ +//! Get the logical value of the specified field. +/*! +*/ +xbShort xbDbf::GetLogicalField( const char * FieldName ) +{ + xbShort fnum; + if(( fnum = GetFieldNo( FieldName )) != -1 ) + return GetLogicalField( fnum ); + else + return -1; +} +/************************************************************************/ +//! Get the string value of the specified field. +/*! +*/ +char * xbDbf::GetStringField( const char * FieldName ) +{ + return GetStringField(GetFieldNo(FieldName)); +} +/************************************************************************/ +//! Get the string value of the specified field. +/*! +*/ +char * xbDbf::GetStringField( xbShort FieldNo ) +{ + /* allocate memory if needed */ + if( !SchemaPtr[FieldNo].fp ) + SchemaPtr[FieldNo].fp = new char[GetFieldLen(FieldNo)+1]; + + if( !SchemaPtr[FieldNo].fp ) + return 0; + + GetField( FieldNo, SchemaPtr[FieldNo].fp ); + return SchemaPtr[FieldNo].fp; +} +/************************************************************************/ |