See Change Log entry 19991013-19:05 EDT David G. Holm <dholm@jsd-llc.com>

This commit is contained in:
David G. Holm
1999-10-13 23:22:49 +00:00
parent b3f4833aa3
commit 6089c4bf2d
8 changed files with 284 additions and 169 deletions

View File

@@ -1,3 +1,40 @@
19991013-19:05 EDT David G. Holm <dholm@jsd-llc.com>
* include/itemapi.h
+ Added a prototype for hb_itemString().
+ Added a prototype for hb_itemValToStr().
* source/compiler/harbour.l
! Removed yy_strdup() call from yy_ConvertNumber().
* source/rtl/console.c
- Removed the string conversion code from hb_out().
+ Added a call to hb_itemString() to hb_out().
* source/rtl/dates.c
! Corrected two erroneous instances of 'hb_stack.szDate' in
hb_dateDecStr() to use the 'szDate' parameter instead.
* source/rtl/itemapi.c
+ Moved hb_itemStr() from source/rtl/strings.c
+ New function hb_itemString() converts practically any value
to a string (this is a modification of the string conversion
code that used to be in hb_out() in source/rtl/console.c).
+ New function hb_itemValToStr(), suggested by Antonio Linares.
* source/rtl/strings.c
- Moved hb_itemStr() to source/rtl/itemapi.c
+ New function HB_HB_VALTOSTR(), suggested by Antonio Linares.
* tests/rtl_test.prg
+ Added several HB_VALTOSTR() tests.
Note: hb_itemStr() is not re-entrant and probably not thread-safe.
I'm not sure how to correct for that without requiring that
the caller free up strings allocated by this function, which
I would very much like to avoid. Any ideas?
19991013-13:46 GMT+8 Ron Pinkas <Ron@Profit-Master.com>
* harbour.y
+ added MACROOP (last session also added MACROALIAS)

View File

@@ -97,6 +97,8 @@ extern int hb_itemStrCmp ( PHB_ITEM pFirst, PHB_ITEM pSecond, BOOL bForce
extern void hb_itemCopy ( PHB_ITEM pDest, PHB_ITEM pSource ); /* copies an item to one place to another respecting its containts */
extern void hb_itemClear ( PHB_ITEM pItem );
extern PHB_ITEM hb_itemUnRef ( PHB_ITEM pItem ); /* de-references passed variable */
extern char * hb_itemStr ( PHB_ITEM pNumber, PHB_ITEM pWidth, PHB_ITEM pDec ); /* convert number to string */
extern char * hb_itemStr ( PHB_ITEM pNumber, PHB_ITEM pWidth, PHB_ITEM pDec ); /* convert a number to a string */
extern char * hb_itemString ( PHB_ITEM pItem, ULONG * ulLen ); /* Convert any scalar to a string */
extern PHB_ITEM hb_itemValToStr ( PHB_ITEM pItem ); /* Convert any scalar to a string */
#endif /* HB_ITEMAPI_H_ */

View File

@@ -1299,8 +1299,6 @@ static int yy_ConvertNumber( char * szBuffer )
char * ptr;
yylval.dNum.dNumber = atof( szBuffer );
yylval.string = yy_strdup( yytext );
ptr = strchr( szBuffer, '.' );
if( ptr )
{

View File

@@ -287,48 +287,10 @@ typedef void hb_out_func_typedef( char *, ULONG );
/* Format items for output, then call specified output function */
static void hb_out( USHORT uiParam, hb_out_func_typedef * hb_out_func )
{
ULONG ulLen;
PHB_ITEM pItem = hb_param( uiParam, IT_ANY );
switch( pItem->type )
{
case IT_STRING:
hb_out_func( hb_itemGetCPtr( pItem ), hb_itemGetCLen( pItem ) );
break;
case IT_DATE:
{
char szBuffer[ 11 ];
hb_dtoc( hb_pards( uiParam ), szBuffer, hb_set.HB_SET_DATEFORMAT );
hb_out_func( szBuffer, strlen( szBuffer ) );
break;
}
case IT_DOUBLE:
case IT_INTEGER:
case IT_LONG:
{
char * szText = hb_itemStr( pItem, NULL, NULL ); /* Let hb_itemStr() do the hard work */
if( szText )
{
hb_out_func( szText, strlen( szText ) );
hb_xfree( szText );
}
break;
}
case IT_NIL:
hb_out_func( "NIL", 3 );
break;
case IT_LOGICAL:
if( hb_itemGetL( pItem ) )
hb_out_func( ".T.", 3 );
else
hb_out_func( ".F.", 3 );
break;
default:
break;
}
char * pString = hb_itemString( pItem, &ulLen );
hb_out_func( pString, ulLen );
}
/* Output an item to STDOUT */

View File

@@ -219,8 +219,8 @@ char * hb_dateDecStr( char * szDate, long lJulian )
long lDay, lMonth, lYear;
hb_dateDecode( lJulian, &lDay, &lMonth, &lYear );
hb_dateStrPut( hb_stack.szDate, lDay, lMonth, lYear );
hb_stack.szDate[ 8 ] = '\0';
hb_dateStrPut( szDate, lDay, lMonth, lYear );
szDate[ 8 ] = '\0';
return szDate;
}

View File

@@ -57,6 +57,9 @@
* Copyright 1999 Eddie Runia <eddie@runia.com>
* hb_itemStrCmp()
*
* Copyright 1999 David G. Holm <dholm@jsd-llc.com>
* hb_itemStr(), hb_itemString(), and hb_itemValToStr().
*
* See doc/license.txt for licensing terms.
*
*/
@@ -68,6 +71,9 @@
#include "dates.h"
#include "set.h"
/* DJGPP can sprintf a float that is almost 320 digits long */
#define HB_MAX_DOUBLE_LENGTH 320
BOOL hb_evalNew( PEVALINFO pEvalInfo, PHB_ITEM pItem )
{
BOOL bResult;
@@ -959,3 +965,182 @@ int hb_itemStrCmp( PHB_ITEM pFirst, PHB_ITEM pSecond, BOOL bForceExact )
return iRet;
}
/* converts a numeric to a string with optional width & precision.
This function should be used by any function that wants to format numeric
data for displaying, printing, or putting in a database.
Note: The caller is responsible for calling hb_xfree to free the results
buffer, but ONLY if the return value is not a NULL pointer! (If a NULL
pointer is returned, then there was a conversion error.)
*/
char * hb_itemStr( PHB_ITEM pNumber, PHB_ITEM pWidth, PHB_ITEM pDec )
{
char * szResult = NULL;
if( pNumber )
{
/* Default to the width and number of decimals specified by the item,
with a limit of 20 integer places and 9 decimal places, plus one
space for the sign. */
int iWidth;
int iDec;
hb_itemGetNLen( pNumber, &iWidth, &iDec );
if( iWidth > 20 )
iWidth = 20;
if( iDec > 9 )
iDec = 9;
if( hb_set.HB_SET_FIXED )
iDec = hb_set.HB_SET_DECIMALS;
if( pWidth )
{
/* If the width parameter is specified, override the default value
and set the number of decimals to zero */
int iWidthPar = hb_itemGetNI( pWidth );
if( iWidthPar < 1 )
iWidth = 10; /* If 0 or negative, use default */
else
iWidth = iWidthPar;
iDec = 0;
}
if( pDec )
{
/* This function does not include the decimal places in the width,
so the width must be adjusted downwards, if the decimal places
parameter is greater than 0 */
int iDecPar = hb_itemGetNI( pDec );
if( iDecPar < 0 )
iDec = 0;
else if( iDecPar > 0 )
{
iDec = iDecPar;
iWidth -= ( iDec + 1 );
}
}
if( iWidth )
{
/* We at least have a width value */
int iBytes;
int iSize = ( iDec ? iWidth + 1 + iDec : iWidth );
/* Be paranoid and use a large amount of padding */
szResult = ( char * ) hb_xgrab( HB_MAX_DOUBLE_LENGTH );
if( IS_DOUBLE( pNumber ) || iDec != 0 )
{
double dNumber = hb_itemGetND( pNumber );
#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY
if( pNumber->item.asDouble.length == 99 || dNumber == s_dInfinity || dNumber == -s_dInfinity )
/* Numeric overflow */
iBytes = iSize + 1;
else
#endif
{
if( IS_DOUBLE( pNumber ) && iDec < pNumber->item.asDouble.decimal )
dNumber = hb_numRound( dNumber, iDec );
if( iDec == 0 )
iBytes = sprintf( szResult, "%*.0f", iSize, dNumber );
else
iBytes = sprintf( szResult, "%*.*f", iSize, iDec, dNumber );
}
}
else
{
switch( pNumber->type & ~IT_BYREF )
{
case IT_INTEGER:
iBytes = sprintf( szResult, "%*i", iWidth, pNumber->item.asInteger.value );
break;
case IT_LONG:
iBytes = sprintf( szResult, "%*li", iWidth, pNumber->item.asLong.value );
break;
default:
iBytes = 0;
szResult[ 0 ] = '\0'; /* null string */
break;
}
}
/* Set to asterisks in case of overflow */
if( iBytes > iSize )
{
memset( szResult, '*', iSize );
szResult[ iSize ] = '\0';
}
}
}
return szResult;
}
char * hb_itemString( PHB_ITEM pItem, ULONG * ulLen )
{
static char buffer[ 32 ]; /* NOTE: Not re-entrant. Probably not thread safe. */
char * pointer;
switch( pItem->type )
{
case IT_STRING:
pointer = hb_itemGetCPtr( pItem );
* ulLen = hb_itemGetCLen( pItem );
break;
case IT_DATE:
{
char szDate[ 9 ];
hb_dateDecStr( szDate, pItem->item.asDate.value );
hb_dtoc( szDate, buffer, hb_set.HB_SET_DATEFORMAT );
pointer = buffer;
* ulLen = strlen( buffer );
}
break;
case IT_DOUBLE:
case IT_INTEGER:
case IT_LONG:
pointer = hb_itemStr( pItem, NULL, NULL );
if( pointer )
{
strncpy( buffer, pointer, sizeof( buffer ) );
buffer[ sizeof( buffer ) - 1 ] = '\0';
hb_xfree( pointer );
pointer = buffer;
* ulLen = strlen( buffer );
}
break;
case IT_NIL:
strcpy( buffer, "NIL" );
pointer = buffer;
* ulLen = 3;
break;
case IT_LOGICAL:
if( hb_itemGetL( pItem ) )
strcpy( buffer, ".T." );
else
strcpy( buffer, ".F." );
pointer = buffer;
* ulLen = 3;
break;
default:
buffer[ 0 ] = '\0';
pointer = buffer;
* ulLen = 0;
}
return pointer;
}
PHB_ITEM hb_itemValToStr( PHB_ITEM pItem )
{
ULONG ulLen;
char * pointer = hb_itemString( pItem, &ulLen );
return hb_itemPutCL( NULL, pointer, ulLen );
}

View File

@@ -38,7 +38,7 @@
* www - http://www.harbour-project.org
*
* Copyright 1999 David G. Holm <dholm@jsd-llc.com>
* hb_stricmp()
* hb_stricmp() and HB_HB_VALTOSTR().
*
* Copyright 1999 Victor Szel <info@szelvesz.hu>
* hb_strEmpty()
@@ -64,9 +64,6 @@
( c ) == HB_CHAR_CR || \
( c ) == ' ' )
/* DJGPP can sprintf a float that is almost 320 digits long */
#define HB_MAX_DOUBLE_LENGTH 320
#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY
#include "init.h"
@@ -1201,125 +1198,6 @@ HARBOUR HB_VAL( void )
hb_errRT_BASE( EG_ARGCOUNT, 3000, NULL, "VAL" ); /* NOTE: Clipper catches this at compile time! */
}
/* converts a numeric to a string with optional width & precision.
This function should be used by any function that wants to format numeric
data for displaying, printing, or putting in a database.
Note: The caller is responsible for calling hb_xfree to free the results buffer,
but ONLY if the return value is not a NULL pointer!
*/
/* TODO: Move it to itemapi.c */
char * hb_itemStr( PHB_ITEM pNumber, PHB_ITEM pWidth, PHB_ITEM pDec )
{
char * szResult = NULL;
if( pNumber )
{
/* Default to the width and number of decimals specified by the item,
with a limit of 20 integer places and 9 decimal places */
int iWidth;
int iDec;
hb_itemGetNLen( pNumber, &iWidth, &iDec );
if( iWidth > 20 )
iWidth = 20;
if( iDec > 9 )
iDec = 9;
if( hb_set.HB_SET_FIXED )
iDec = hb_set.HB_SET_DECIMALS;
if( pWidth )
{
/* If the width parameter is specified, override the default value
and set the number of decimals to zero */
int iWidthPar = hb_itemGetNI( pWidth );
if( iWidthPar < 1 )
iWidth = 10; /* If 0 or negative, use default */
else
iWidth = iWidthPar;
iDec = 0;
}
if( pDec )
{
/* This function does not include the decimal places in the width,
so the width must be adjusted downwards, if the decimal places
parameter is greater than 0 */
int iDecPar = hb_itemGetNI( pDec );
if( iDecPar < 0 )
iDec = 0;
else if( iDecPar > 0 )
{
iDec = iDecPar;
iWidth -= ( iDec + 1 );
}
}
if( iWidth )
{
/* We at least have a width value */
int iBytes;
int iSize = ( iDec ? iWidth + 1 + iDec : iWidth );
/* Be paranoid and use a large amount of padding */
szResult = ( char * ) hb_xgrab( HB_MAX_DOUBLE_LENGTH );
if( IS_DOUBLE( pNumber ) || iDec != 0 )
{
double dNumber = hb_itemGetND( pNumber );
#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY
if( pNumber->item.asDouble.length == 99 || dNumber == s_dInfinity || dNumber == -s_dInfinity )
/* Numeric overflow */
iBytes = iSize + 1;
else
#endif
{
if( IS_DOUBLE( pNumber ) && iDec < pNumber->item.asDouble.decimal )
dNumber = hb_numRound( dNumber, iDec );
if( iDec == 0 )
iBytes = sprintf( szResult, "%*.0f", iSize, dNumber );
else
iBytes = sprintf( szResult, "%*.*f", iSize, iDec, dNumber );
}
}
else
{
switch( pNumber->type & ~IT_BYREF )
{
case IT_INTEGER:
iBytes = sprintf( szResult, "%*i", iWidth, pNumber->item.asInteger.value );
break;
case IT_LONG:
iBytes = sprintf( szResult, "%*li", iWidth, pNumber->item.asLong.value );
break;
default:
iBytes = 0;
szResult[ 0 ] = '\0'; /* null string */
break;
}
}
/* Set to asterisks in case of overflow */
if( iBytes > iSize )
{
memset( szResult, '*', iSize );
szResult[ iSize ] = '\0';
}
}
}
return szResult;
}
/* $DOC$
* $FUNCNAME$
* STR
@@ -1617,3 +1495,45 @@ int hb_strgreater( char * szText1, char * szText2 )
return HB_STRGREATER_EQUAL;
}
/* $DOC$
* $FUNCNAME$
* HB_VALTOSTR
* $CATEGORY$
* Strings
* $ONELINER$
* Converts any scalar type to a string.
* $SYNTAX$
* HB_VALTOSTR( <xValue> )
* $ARGUMENTS$
* <xValue> is any scalar argument.
* $RETURNS$
* A string representation of <xValue> using default conversions.
* $DESCRIPTION$
* HB_VALTOSTR can be used to convert any scalar value to a string.
* $EXAMPLES$
* ? HB_VALTOSTR( 4 )
* ? HB_VALTOSTR( "String" )
* $TESTS$
* ? HB_VALTOSTR( 4 ) == " 4"
* ? HB_VALTOSTR( 4.0 / 2 ) == " 2.00"
* ? HB_VALTOSTR( "String" ) == "String"
* ? HB_VALTOSTR( CTOD( "01/01/2001" ) ) == "01/01/01"
* ? HB_VALTOSTR( NIL ) == "NIL"
* ? HB_VALTOSTR( .F. ) == ".F."
* ? HB_VALTOSTR( .T. ) == ".T."
* $STATUS$
* C
* $COMPLIANCE$
* HB_VALTOSTR is a Harbour enhancement.
* $SEEALSO$
* STR(), VAL()
* $END$
*/
HARBOUR HB_HB_VALTOSTR( void )
{
ULONG ulLen;
char * pointer = hb_itemString( hb_param( 1, IT_ANY ), &ulLen );
hb_retclen( pointer, ulLen );
}

View File

@@ -146,6 +146,7 @@ FUNCTION Main( cPar1, cPar2 )
Main_MATH()
Main_STRINGS()
#ifdef __HARBOUR__
New_STRINGS()
Long_STRINGS()
#endif
Main_MISC()
@@ -1653,6 +1654,16 @@ STATIC FUNCTION Main_STRINGS()
RETURN NIL
#ifdef __HARBOUR__
STATIC FUNCTION New_STRINGS()
TEST_LINE( HB_VALTOSTR( 4 ) , " 4" )
TEST_LINE( HB_VALTOSTR( 4.0 / 2 ) , " 2.00" )
TEST_LINE( HB_VALTOSTR( "String" ) , "String" )
TEST_LINE( HB_VALTOSTR( CTOD( "2001/01/01" ) ), "2001.01.01" )
TEST_LINE( HB_VALTOSTR( NIL ) , "NIL" )
TEST_LINE( HB_VALTOSTR( .F. ) , ".F." )
TEST_LINE( HB_VALTOSTR( .T. ) , ".T." )
RETURN NIL
STATIC FUNCTION Long_STRINGS()
TEST_LINE( RIGHT( SPACE( 64 * 1024 - 5 ) + "12345 7890", 10 ), "12345 7890" )