mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
A couple of locale fixes
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@17167 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
55aa234ddb
commit
afb5488c8b
6 changed files with 229 additions and 14 deletions
|
@ -3,6 +3,10 @@
|
|||
* Source/Source/GSFFCallInvocation.m: gs_objc_msg_forward() trust the
|
||||
selector we are given. Rather than trying to find a better one.
|
||||
* Source/GSFFIInvocation.m: ditto
|
||||
* Source/NSScanner.m: Add a couple of internal utility functions.
|
||||
* Source/NSString.m: Fix floatValue and doubelValue to use non
|
||||
localised conversions.
|
||||
* Source/GSString.m: ditto.
|
||||
|
||||
2003-07-06 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
|
|
|
@ -2002,3 +2002,4 @@ group_number (unichar *w, unichar *rear_ptr, const char *grouping,
|
|||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
|
|
|
@ -1004,21 +1004,25 @@ dataUsingEncoding_u(ivars self, NSStringEncoding encoding, BOOL flag)
|
|||
}
|
||||
}
|
||||
|
||||
extern BOOL GSScanDouble(unichar*, unsigned, double*);
|
||||
|
||||
static inline double
|
||||
doubleValue_c(ivars self)
|
||||
{
|
||||
if (self->_count == 0)
|
||||
{
|
||||
return 0;
|
||||
return 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned len = self->_count < 32 ? self->_count : 31;
|
||||
unsigned char buf[len+1];
|
||||
unsigned l = self->_count < 32 ? self->_count : 32;
|
||||
unichar buf[l];
|
||||
unichar *b = buf;
|
||||
double d = 0.0;
|
||||
|
||||
memcpy(buf, self->_contents.c, len);
|
||||
buf[len] = '\0';
|
||||
return atof(buf);
|
||||
GSToUnicode(&b, &l, self->_contents.c, l, intEnc, 0, 0);
|
||||
GSScanDouble(b, l, &d);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1027,16 +1031,14 @@ doubleValue_u(ivars self)
|
|||
{
|
||||
if (self->_count == 0)
|
||||
{
|
||||
return 0;
|
||||
return 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int l = self->_count < 10 ? self->_count : 9;
|
||||
unsigned char buf[l+1];
|
||||
unsigned char *b = buf;
|
||||
double d = 0.0;
|
||||
|
||||
GSFromUnicode(&b, &l, self->_contents.u, l, intEnc, 0, GSUniTerminate);
|
||||
return atof(buf);
|
||||
GSScanDouble(self->_contents.u, self->_count, &d);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -646,6 +646,10 @@ static Class doubleNumberClass;
|
|||
return NSCopyObject(self, 0, zone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string representation of this number using a non-localised
|
||||
* conversion (decimal point is '.' irrespective of the locale).
|
||||
*/
|
||||
- (NSString*) description
|
||||
{
|
||||
return [self descriptionWithLocale: nil];
|
||||
|
|
|
@ -1113,3 +1113,181 @@ typedef struct {
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
/*
|
||||
* Some utilities
|
||||
*/
|
||||
BOOL
|
||||
GSScanInt(unichar *buf, unsigned length, int *result)
|
||||
{
|
||||
unsigned int num = 0;
|
||||
const unsigned int limit = UINT_MAX / 10;
|
||||
BOOL negative = NO;
|
||||
BOOL overflow = NO;
|
||||
BOOL got_digits = NO;
|
||||
unsigned int pos = 0;
|
||||
|
||||
/* Check for sign */
|
||||
if (pos < length)
|
||||
{
|
||||
switch (buf[pos])
|
||||
{
|
||||
case '+':
|
||||
pos++;
|
||||
break;
|
||||
case '-':
|
||||
negative = YES;
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process digits */
|
||||
while (pos < length)
|
||||
{
|
||||
unichar digit = buf[pos];
|
||||
|
||||
if ((digit < '0') || (digit > '9'))
|
||||
break;
|
||||
if (!overflow)
|
||||
{
|
||||
if (num >= limit)
|
||||
overflow = YES;
|
||||
else
|
||||
num = num * 10 + (digit - '0');
|
||||
}
|
||||
pos++;
|
||||
got_digits = YES;
|
||||
}
|
||||
|
||||
/* Save result */
|
||||
if (!got_digits)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
if (overflow
|
||||
|| (num > (negative ? (unsigned int)INT_MIN : (unsigned int)INT_MAX)))
|
||||
*result = negative ? INT_MIN: INT_MAX;
|
||||
else if (negative)
|
||||
*result = -num;
|
||||
else
|
||||
*result = num;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan in a double value in the standard locale ('.' as decimal point).<br />
|
||||
* Return YES on success, NO on failure.<br />
|
||||
* The value pointed to by result is unmodified on failure.<br />
|
||||
* No value is returned in result if it is a null pointer.
|
||||
*/
|
||||
BOOL
|
||||
GSScanDouble(unichar *buf, unsigned length, double *result)
|
||||
{
|
||||
unichar c = 0;
|
||||
double num = 0.0;
|
||||
long int exponent = 0;
|
||||
BOOL negative = NO;
|
||||
BOOL got_dot = NO;
|
||||
BOOL got_digit = NO;
|
||||
unsigned pos = 0;
|
||||
|
||||
/* Skip whitespace */
|
||||
while (pos < length && isspace((int)buf[pos]))
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
|
||||
/* Check for sign */
|
||||
if (pos < length)
|
||||
{
|
||||
switch (buf[pos])
|
||||
{
|
||||
case '+':
|
||||
pos++;
|
||||
break;
|
||||
case '-':
|
||||
negative = YES;
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process number */
|
||||
while (pos < length)
|
||||
{
|
||||
c = buf[pos];
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
{
|
||||
/* Ensure that the number being accumulated will not overflow. */
|
||||
if (num >= (DBL_MAX / 10.000000001))
|
||||
{
|
||||
++exponent;
|
||||
}
|
||||
else
|
||||
{
|
||||
num = (num * 10.0) + (c - '0');
|
||||
got_digit = YES;
|
||||
}
|
||||
/* Keep track of the number of digits after the decimal point.
|
||||
If we just divided by 10 here, we would lose precision. */
|
||||
if (got_dot)
|
||||
{
|
||||
--exponent;
|
||||
}
|
||||
}
|
||||
else if (!got_dot && (c == '.'))
|
||||
{
|
||||
/* Note that we have found the decimal point. */
|
||||
got_dot = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Any other character terminates the number. */
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (!got_digit)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* Check for trailing exponent */
|
||||
if ((pos < length) && ((c == 'e') || (c == 'E')))
|
||||
{
|
||||
int expval;
|
||||
|
||||
pos++;
|
||||
if (GSScanInt(&buf[pos], length - pos, &expval) == YES)
|
||||
{
|
||||
/* Check for exponent overflow */
|
||||
if (num)
|
||||
{
|
||||
if ((exponent > 0) && (expval > (LONG_MAX - exponent)))
|
||||
exponent = LONG_MAX;
|
||||
else if ((exponent < 0) && (expval < (LONG_MIN - exponent)))
|
||||
exponent = LONG_MIN;
|
||||
else
|
||||
exponent += expval;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
if (num && exponent)
|
||||
num *= pow(10.0, (double) exponent);
|
||||
if (negative)
|
||||
*result = -num;
|
||||
else
|
||||
*result = num;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
|
|
@ -2425,14 +2425,40 @@ handle_printf_atsign (FILE *stream,
|
|||
return [self intValue] != 0 ? YES : NO;
|
||||
}
|
||||
|
||||
extern BOOL GSScanDouble(unichar*, unsigned, double*);
|
||||
|
||||
/**
|
||||
* Returns the strings content as a double. Skips leading whitespace.<br />
|
||||
* Conversion is not localised (ie uses '.' as the decimal separator).<br />
|
||||
* Returns 0.0 on underflow or if the string does not contain a number.
|
||||
*/
|
||||
- (double) doubleValue
|
||||
{
|
||||
return atof([self lossyCString]);
|
||||
unichar buf[32];
|
||||
unsigned len = [self length];
|
||||
double d = 0.0;
|
||||
|
||||
if (len > 32) len = 32;
|
||||
[self getCharacters: buf range: NSMakeRange(0, len)];
|
||||
GSScanDouble(buf, len, &d);
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the strings content as a double. Skips leading whitespace.<br />
|
||||
* Conversion is not localised (ie uses '.' as the decimal separator).<br />
|
||||
* Returns 0.0 on underflow or if the string does not contain a number.
|
||||
*/
|
||||
- (float) floatValue
|
||||
{
|
||||
return (float) atof([self lossyCString]);
|
||||
unichar buf[32];
|
||||
unsigned len = [self length];
|
||||
double d = 0.0;
|
||||
|
||||
if (len > 32) len = 32;
|
||||
[self getCharacters: buf range: NSMakeRange(0, len)];
|
||||
GSScanDouble(buf, len, &d);
|
||||
return (float)d;
|
||||
}
|
||||
|
||||
- (int) intValue
|
||||
|
|
Loading…
Reference in a new issue