mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 00:30:53 +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
ec7af312f4
commit
14577e9418
6 changed files with 229 additions and 14 deletions
|
@ -3,6 +3,10 @@
|
||||||
* Source/Source/GSFFCallInvocation.m: gs_objc_msg_forward() trust the
|
* Source/Source/GSFFCallInvocation.m: gs_objc_msg_forward() trust the
|
||||||
selector we are given. Rather than trying to find a better one.
|
selector we are given. Rather than trying to find a better one.
|
||||||
* Source/GSFFIInvocation.m: ditto
|
* 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>
|
2003-07-06 Adam Fedor <fedor@gnu.org>
|
||||||
|
|
||||||
|
|
|
@ -2002,3 +2002,4 @@ group_number (unichar *w, unichar *rear_ptr, const char *grouping,
|
||||||
}
|
}
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1004,21 +1004,25 @@ dataUsingEncoding_u(ivars self, NSStringEncoding encoding, BOOL flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern BOOL GSScanDouble(unichar*, unsigned, double*);
|
||||||
|
|
||||||
static inline double
|
static inline double
|
||||||
doubleValue_c(ivars self)
|
doubleValue_c(ivars self)
|
||||||
{
|
{
|
||||||
if (self->_count == 0)
|
if (self->_count == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned len = self->_count < 32 ? self->_count : 31;
|
unsigned l = self->_count < 32 ? self->_count : 32;
|
||||||
unsigned char buf[len+1];
|
unichar buf[l];
|
||||||
|
unichar *b = buf;
|
||||||
|
double d = 0.0;
|
||||||
|
|
||||||
memcpy(buf, self->_contents.c, len);
|
GSToUnicode(&b, &l, self->_contents.c, l, intEnc, 0, 0);
|
||||||
buf[len] = '\0';
|
GSScanDouble(b, l, &d);
|
||||||
return atof(buf);
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1027,16 +1031,14 @@ doubleValue_u(ivars self)
|
||||||
{
|
{
|
||||||
if (self->_count == 0)
|
if (self->_count == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int l = self->_count < 10 ? self->_count : 9;
|
double d = 0.0;
|
||||||
unsigned char buf[l+1];
|
|
||||||
unsigned char *b = buf;
|
|
||||||
|
|
||||||
GSFromUnicode(&b, &l, self->_contents.u, l, intEnc, 0, GSUniTerminate);
|
GSScanDouble(self->_contents.u, self->_count, &d);
|
||||||
return atof(buf);
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -646,6 +646,10 @@ static Class doubleNumberClass;
|
||||||
return NSCopyObject(self, 0, zone);
|
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
|
- (NSString*) description
|
||||||
{
|
{
|
||||||
return [self descriptionWithLocale: nil];
|
return [self descriptionWithLocale: nil];
|
||||||
|
|
|
@ -1113,3 +1113,181 @@ typedef struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@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;
|
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
|
- (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
|
- (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
|
- (int) intValue
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue