See Change Log entry 19991013-19:05 EDT David G. Holm <dholm@jsd-llc.com>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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" )
|
||||
|
||||
Reference in New Issue
Block a user