From: <bi...@us...> - 2008-09-11 22:00:59
|
Revision: 3278 http://oorexx.svn.sourceforge.net/oorexx/?rev=3278&view=rev Author: bigrixx Date: 2008-09-11 22:01:10 +0000 (Thu, 11 Sep 2008) Log Message: ----------- Fix edge cases for integer formatting Modified Paths: -------------- main/trunk/interpreter/classes/NumberStringClass.cpp main/trunk/interpreter/runtime/Numerics.cpp main/trunk/interpreter/runtime/Numerics.hpp Modified: main/trunk/interpreter/classes/NumberStringClass.cpp =================================================================== --- main/trunk/interpreter/classes/NumberStringClass.cpp 2008-09-11 20:19:30 UTC (rev 3277) +++ main/trunk/interpreter/classes/NumberStringClass.cpp 2008-09-11 22:01:10 UTC (rev 3278) @@ -2101,8 +2101,6 @@ /* Function : Format the integer num into a numberstring. */ /******************************************************************************/ { - char *current; /* current position */ - if (integer == 0) { /* is integer 0? */ /* indicate this. */ @@ -2114,18 +2112,9 @@ if (integer < 0 ) { /* Negative integer number? */ this->sign = -1; - integer = -integer; /* take the positive version */ } /* convert value into string */ - Numerics::formatWholeNumber(integer, (char *)this->number); - current = this->number; /* point to the data start */ - while (*current != '\0') - { /* while still have digits */ - *current -= '0'; /* make zero based */ - current++; /* step to the next one */ - } - /* set the proper length */ - this->length = current - this->number; + this->length = Numerics::normalizeWholeNumber(integer, (char *)this->number); } } Modified: main/trunk/interpreter/runtime/Numerics.cpp =================================================================== --- main/trunk/interpreter/runtime/Numerics.cpp 2008-09-11 20:19:30 UTC (rev 3277) +++ main/trunk/interpreter/runtime/Numerics.cpp 2008-09-11 22:01:10 UTC (rev 3278) @@ -463,39 +463,137 @@ // zero? this is pretty easy if (integer == 0) { - strcpy((char *)dest, "0"); + strcpy(dest, "0"); return 1; } size_t sign = 0; + // we convert this directly because portable numeric-to-ascii routines + // don't really exist for the various 32/64 bit values. + char buffer[24]; + size_t index = sizeof(buffer); + // negative number? copy a negative sign, and take the abs value if (integer < 0) { *dest++ = '-'; - integer = -integer; + integer = -(integer + 1); sign = 1; // added in to the length + int carry = 1; // we add this in when handling the first digit + + while (integer > 0) + { + // get the digit and reduce the size of the integer + int digit = (int)(integer % 10) + carry; + // if adding the carry caused a carry, we need to propagate this along + if (digit > 9) + { + digit = 0; // this is a zero digit, keep the carry + } + else + { + carry = 0; // done adding in + } + integer = integer / 10; + // store the digit + buffer[--index] = digit + '0'; + } + // we might have a carry out here + if (carry != 0) + { + buffer[--index] = '1'; + } } + else + { + while (integer > 0) + { + // get the digit and reduce the size of the integer + int digit = (int)(integer % 10) + '0'; + integer = integer / 10; + // store the digit + buffer[--index] = digit; + } + } + // copy into the buffer and set the length + stringsize_t length = sizeof(buffer) - index; + memcpy(dest, &buffer[index], length); + // make sure we have a terminating null + dest[length] = '\0'; + return length + sign; +} + + +/** + * Do portable formatting of a wholenumber value into + * numberstring format. + * + * @param integer The value to convert. + * @param dest The location to store the formatted string. + * + * @return The length of the converted number. + */ +stringsize_t Numerics::normalizeWholeNumber(wholenumber_t integer, char *dest) +{ + // zero? this is pretty easy + if (integer == 0) + { + *dest = '\0'; + return 1; + } + // we convert this directly because portable numeric-to-ascii routines // don't really exist for the various 32/64 bit values. char buffer[24]; size_t index = sizeof(buffer); - while (integer > 0) + // negative number? copy a negative sign, and take the abs value + if (integer < 0) { - // get the digit and reduce the size of the integer - int digit = (int)(integer % 10) + '0'; - integer = integer / 10; - // store the digit - buffer[--index] = digit; + integer = -(integer + 1); + int carry = 1; // we add this in when handling the first digit + while (integer > 0) + { + // get the digit and reduce the size of the integer + int digit = (int)(integer % 10) + carry; + // if adding the carry caused a carry, we need to propagate this along + if (digit > 9) + { + digit = 0; // this is a zero digit, keep the carry + } + else + { + carry = 0; // done adding in + } + integer = integer / 10; + // store the digit + buffer[--index] = digit; + } + // we might have had a carry out + if (carry != 0) + { + buffer[--index] = 1; + } } + else + { + while (integer > 0) + { + // get the digit and reduce the size of the integer + int digit = (int)(integer % 10); + integer = integer / 10; + // store the digit + buffer[--index] = digit; + } + } // copy into the buffer and set the length stringsize_t length = sizeof(buffer) - index; memcpy(dest, &buffer[index], length); // make sure we have a terminating null dest[length] = '\0'; - return length + sign; + return length; } /** @@ -557,27 +655,53 @@ return 1; } + // we convert this directly because portable numeric-to-ascii routines + // don't really exist for the various 32/64 bit values. + char buffer[32]; + size_t index = sizeof(buffer); size_t sign = 0; + // negative number? copy a negative sign, and take the abs value if (integer < 0) { *dest++ = '-'; - integer = -integer; - sign = 1; // added in to the length + integer = -(integer + 1); + sign = 1; // added in to the length + int carry = 1; // we add this in when handling the first digit + + while (integer > 0) + { + // get the digit and reduce the size of the integer + int digit = (int)(integer % 10) + carry; + // if adding the carry caused a carry, we need to propagate this along + if (digit > 9) + { + digit = 0; // this is a zero digit, keep the carry + } + else + { + carry = 0; // done adding in + } + integer = integer / 10; + // store the digit + buffer[--index] = digit + '0'; + } + // we might have a carry out here + if (carry != 0) + { + buffer[--index] = '1'; + } } - - // we convert this directly because portable numeric-to-ascii routines - // don't really exist for the various 32/64 bit values. - char buffer[32]; - size_t index = sizeof(buffer); - - while (integer > 0) + else { - // get the digit and reduce the size of the integer - int digit = (int)(integer % 10) + '0'; - integer = integer / 10; - // store the digit - buffer[--index] = digit; + while (integer > 0) + { + // get the digit and reduce the size of the integer + int digit = (int)(integer % 10) + '0'; + integer = integer / 10; + // store the digit + buffer[--index] = digit; + } } // copy into the buffer and set the length Modified: main/trunk/interpreter/runtime/Numerics.hpp =================================================================== --- main/trunk/interpreter/runtime/Numerics.hpp 2008-09-11 20:19:30 UTC (rev 3277) +++ main/trunk/interpreter/runtime/Numerics.hpp 2008-09-11 22:01:10 UTC (rev 3278) @@ -94,11 +94,13 @@ static bool objectToUintptr(RexxObject *source, uintptr_t &result); static bool objectToIntptr(RexxObject *source, intptr_t &result); - static stringsize_t formatWholeNumber(wholenumber_t integer, char *dest); - static stringsize_t formatStringSize(stringsize_t integer, char *dest); - static stringsize_t formatInt64(int64_t integer, char *dest); - static stringsize_t formatUnsignedInt64(uint64_t integer, char *dest); + static size_t formatWholeNumber(wholenumber_t integer, char *dest); + static size_t formatStringSize(stringsize_t integer, char *dest); + static size_t formatInt64(int64_t integer, char *dest); + static size_t formatUnsignedInt64(uint64_t integer, char *dest); + static size_t normalizeWholeNumber(wholenumber_t integer, char *dest); + static size_t digits() { return settings->digits; } static size_t fuzz() { return settings->fuzz; } static bool form() { return settings->form; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |