Author: rfm
Date: Tue May 5 13:54:14 2015
New Revision: 38476
URL: http://svn.gna.org/viewcvs/gnustep?rev=38476&view=rev
Log:
Fixups to get acceptable performance from TinyString objects.
Modified:
libs/base/trunk/ChangeLog
libs/base/trunk/Source/GSString.m
Modified: libs/base/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/ChangeLog?rev=38476&r1=38475&r2=38476&view=diff
==============================================================================
--- libs/base/trunk/ChangeLog (original)
+++ libs/base/trunk/ChangeLog Tue May 5 13:54:14 2015
@@ -1,3 +1,9 @@
+2015-05-05 Richard Frith-Macdonald <[email protected]>
+
+ * Source/GSString.m:
+ Fix for 64bit systems using TinyString objects ... missing
+ implementations for common methods were making performance dire.
+
2015-05-02 Niels Grewe <[email protected]>
* Source/GSSet.m
Modified: libs/base/trunk/Source/GSString.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/GSString.m?rev=38476&r1=38475&r2=38476&view=diff
==============================================================================
--- libs/base/trunk/Source/GSString.m (original)
+++ libs/base/trunk/Source/GSString.m Tue May 5 13:54:14 2015
@@ -759,29 +759,217 @@
fprintf(stderr, "%d tiny strings created\n", tinyStrings);
}
#endif
+
+static int
+tsbytes(uintptr_t s, char *buf)
+{
+ int length = (s >> TINY_STRING_LENGTH_SHIFT) & TINY_STRING_LENGTH_MASK;
+ int index;
+
+ for (index = 0; index < length; index++)
+ {
+ buf[index] = (char)TINY_STRING_CHAR(s, index);
+ }
+ buf[index] = 0;
+ return index;
+}
+
@implementation GSTinyString
+
+- (BOOL) boolValue
+{
+ char buf[9];
+ int count = tsbytes((uintptr_t)self, buf);
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ char c = buf[i];
+
+ if (strchr("123456789yYtT", c) != 0)
+ {
+ return YES;
+ }
+ if (!isspace(c) && c != '0' && c != '-' && c != '+')
+ {
+ break;
+ }
+ }
+ return NO;
+}
+
+- (unichar) characterAtIndex: (NSUInteger)anIndex
+{
+ uintptr_t s = (uintptr_t)self;
+ NSUInteger length = (s >> TINY_STRING_LENGTH_SHIFT) &
TINY_STRING_LENGTH_MASK;
+
+ if (anIndex >= length)
+ {
+ [NSException raise: NSInvalidArgumentException
+ format: @"-characterAtIndex: index out of range"];
+ }
+ // Implicit NULL terminator on slightly-too-long strings.
+ if (anIndex == 8)
+ {
+ return '\0';
+ }
+ return TINY_STRING_CHAR(s, anIndex);
+}
+
+- (void) getCharacters: (unichar*)buffer
+{
+ uintptr_t s = (uintptr_t)self;
+ int length = (s >> TINY_STRING_LENGTH_SHIFT) & TINY_STRING_LENGTH_MASK;
+ int index;
+
+ for (index = 0; index < length; index++)
+ {
+ buffer[index] = (unichar)TINY_STRING_CHAR(s, index);
+ }
+}
+
+- (void) getCharacters: (unichar*)buffer range: (NSRange)aRange
+{
+ uintptr_t s = (uintptr_t)self;
+ int length = (s >> TINY_STRING_LENGTH_SHIFT) & TINY_STRING_LENGTH_MASK;
+ int index;
+ int offset;
+
+ GS_RANGE_CHECK(aRange, length);
+ length = NSMaxRange(aRange);
+ offset = 0;
+ for (index = aRange.location; index < length; index++)
+ {
+ buffer[offset++] = (unichar)TINY_STRING_CHAR(s, index);
+ }
+}
+
+- (BOOL) getCString: (char*)buffer
+ maxLength: (NSUInteger)maxLength
+ encoding: (NSStringEncoding)encoding
+{
+ uintptr_t s = (uintptr_t)self;
+ int length = (s >> TINY_STRING_LENGTH_SHIFT) & TINY_STRING_LENGTH_MASK;
+ int index;
+
+ if (buffer == 0)
+ {
+ return NO; // Can't fit in here
+ }
+ if (NSUnicodeStringEncoding == encoding)
+ {
+ maxLength /= 2;
+ if (maxLength > 1)
+ {
+ unichar *buf = (unichar*)buffer;
+
+ if (maxLength <= length)
+ {
+ length = maxLength - 1;
+ }
+ for (index = 0; index < length; index++)
+ {
+ buf[index] = (unichar)TINY_STRING_CHAR(s, index);
+ }
+ buf[index] = 0;
+ return YES;
+ }
+ return NO;
+ }
+ else if (isByteEncoding(encoding))
+ {
+ if (maxLength > 0)
+ {
+ if (maxLength <= length)
+ {
+ length = maxLength - 1;
+ }
+ for (index = 0; index < length; index++)
+ {
+ buffer[index] = (char)TINY_STRING_CHAR(s, index);
+ }
+ buffer[index] = 0;
+ return YES;
+ }
+ return NO;
+ }
+ return [super getCString: buffer maxLength: maxLength encoding: encoding];
+}
+
+- (NSUInteger) hash
+{
+ uintptr_t s = (uintptr_t)self;
+ int length = (s >> TINY_STRING_LENGTH_SHIFT) & TINY_STRING_LENGTH_MASK;
+ uint32_t ret = 0;
+
+ if (length > 0)
+ {
+ unichar buf[10];
+ int index;
+
+ for (index = 0; index < length; index++)
+ {
+ buf[index] = (char)TINY_STRING_CHAR(s, index);
+ }
+ ret = GSPrivateHash(0, buf, length * sizeof(unichar));
+
+ /*
+ * The hash caching in our concrete string classes uses zero to denote
+ * an empty cache value, so we MUST NOT return a hash of zero.
+ */
+ ret &= 0x0fffffff;
+ if (ret == 0)
+ {
+ ret = 0x0fffffff;
+ }
+ }
+ else
+ {
+ ret = 0x0ffffffe; /* Hash for an empty string. */
+ }
+ return ret;
+}
+
+- (int) intValue
+{
+ char buf[9];
+
+ tsbytes((uintptr_t)self, buf);
+ return strtol(buf, 0, 10);
+}
+
+- (NSInteger) integerValue
+{
+ char buf[9];
+
+ tsbytes((uintptr_t)self, buf);
+#if GS_SIZEOF_VOIDP == GS_SIZEOF_LONG
+ return strtol(buf, 0, 10);
+#else
+ return strtoll(buf, 0, 10);
+#endif
+}
+
- (NSUInteger) length
{
uintptr_t s = (uintptr_t)self;
return (s >> TINY_STRING_LENGTH_SHIFT) & TINY_STRING_LENGTH_MASK;
}
-- (unichar) characterAtIndex: (NSUInteger)anIndex
-{
- uintptr_t s = (uintptr_t)self;
- NSUInteger length = (s >> TINY_STRING_LENGTH_SHIFT) &
TINY_STRING_LENGTH_MASK;
-
- if (anIndex >= length)
- {
- [NSException raise: NSInvalidArgumentException
- format: @"-characterAtIndex: index out of range"];
- }
- // Implicit NULL terminator on slightly-too-long strings.
- if (anIndex == 8)
- {
- return '\0';
- }
- return TINY_STRING_CHAR(s, anIndex);
+- (long long) longLongValue
+{
+ char buf[9];
+
+ tsbytes((uintptr_t)self, buf);
+ return strtoll(buf, 0, 10);
+}
+
+- (const char*) UTF8String
+{
+ char *buf = GSAutoreleasedBuffer(9);
+
+ tsbytes((uintptr_t)self, buf);
+ return buf;
}
+ (void) load
@@ -1557,10 +1745,10 @@
static inline BOOL
boolValue_c(GSStr self)
{
- unsigned c = self->_count;
+ unsigned count = self->_count;
unsigned i;
- for (i = 0; i < c; i++)
+ for (i = 0; i < count; i++)
{
char c = self->_contents.c[i];
@@ -1579,10 +1767,10 @@
static inline BOOL
boolValue_u(GSStr self)
{
- unsigned c = self->_count;
+ unsigned count = self->_count;
unsigned i;
- for (i = 0; i < c; i++)
+ for (i = 0; i < count; i++)
{
unichar c = self->_contents.u[i];
@@ -1600,6 +1788,62 @@
}
}
return NO;
+}
+
+static inline void
+intBuf_c(GSStr self, char *buf)
+{
+ unsigned c = self->_count;
+ unsigned i = 0;
+ unsigned j = 0;
+
+ while (i < c && isspace(self->_contents.c[i]))
+ {
+ i++;
+ }
+ if (i < c)
+ {
+ char sign = self->_contents.c[i];
+
+ if ('+' == sign || '-' == sign)
+ {
+ buf[j++] = sign;
+ i++;
+ }
+ }
+ while (i < c && j < 20 && isdigit(self->_contents.c[i]))
+ {
+ buf[j++] = self->_contents.c[i++];
+ }
+ buf[j] = '\0';
+}
+
+static inline void
+intBuf_u(GSStr self, char *buf)
+{
+ unsigned c = self->_count;
+ unsigned i = 0;
+ unsigned j = 0;
+
+ while (i < c && isspace(self->_contents.u[i]))
+ {
+ i++;
+ }
+ if (i < c)
+ {
+ unichar sign = self->_contents.u[i];
+
+ if ('+' == sign || '-' == sign)
+ {
+ buf[j++] = (char)sign;
+ i++;
+ }
+ }
+ while (i < c && j < 20 && isdigit(self->_contents.u[i]))
+ {
+ buf[j++] = (char)self->_contents.u[i++];
+ }
+ buf[j] = '\0';
}
static inline BOOL
@@ -2621,56 +2865,6 @@
}
}
-static inline int
-intValue_c(GSStr self)
-{
- const char *ptr = (const char*)self->_contents.c;
- const char *end = ptr + self->_count;
-
- while (ptr < end && isspace(*ptr))
- {
- ptr++;
- }
- if (ptr == end)
- {
- return 0;
- }
- else
- {
- unsigned int l = (end - ptr) < 32 ? (end - ptr) : 31;
- char buf[32];
-
- memcpy(buf, ptr, l);
- buf[l] = '\0';
- return atol((const char*)buf);
- }
-}
-
-static inline int
-intValue_u(GSStr self)
-{
- const unichar *ptr = self->_contents.u;
- const unichar *end = ptr + self->_count;
-
- while (ptr < end && isspace(*ptr))
- {
- ptr++;
- }
- if (ptr == end)
- {
- return 0;
- }
- else
- {
- unsigned int l = (end - ptr) < 32 ? (end - ptr) : 31;
- unsigned char buf[32];
- unsigned char *b = buf;
-
- GSFromUnicode(&b, &l, ptr, l, internalEncoding, 0, GSUniTerminate);
- return atol((const char*)buf);
- }
-}
-
static inline BOOL
isEqual_c(GSStr self, id anObject)
{
@@ -3666,7 +3860,22 @@
- (int) intValue
{
- return intValue_c((GSStr)self);
+ char buf[24];
+
+ intBuf_c((GSStr)self, buf);
+ return strtol(buf, 0, 10);
+}
+
+- (NSInteger) integerValue
+{
+ char buf[24];
+
+ intBuf_c((GSStr)self, buf);
+#if GS_SIZEOF_VOIDP == GS_SIZEOF_LONG
+ return strtol(buf, 0, 10);
+#else
+ return strtoll(buf, 0, 10);
+#endif
}
- (BOOL) isEqual: (id)anObject
@@ -3687,6 +3896,14 @@
- (NSUInteger) lengthOfBytesUsingEncoding: (NSStringEncoding)encoding
{
return cStringLength_c((GSStr)self, encoding);
+}
+
+- (long long) longLongValue
+{
+ char buf[24];
+
+ intBuf_c((GSStr)self, buf);
+ return strtoll(buf, 0, 10);
}
- (const char*) lossyCString
@@ -4020,7 +4237,22 @@
- (int) intValue
{
- return intValue_u((GSStr)self);
+ char buf[24];
+
+ intBuf_u((GSStr)self, buf);
+ return strtol(buf, 0, 10);
+}
+
+- (NSInteger) integerValue
+{
+ char buf[24];
+
+ intBuf_u((GSStr)self, buf);
+#if GS_SIZEOF_VOIDP == GS_SIZEOF_LONG
+ return strtol(buf, 0, 10);
+#else
+ return strtoll(buf, 0, 10);
+#endif
}
- (BOOL) isEqual: (id)anObject
@@ -4041,6 +4273,14 @@
- (NSUInteger) lengthOfBytesUsingEncoding: (NSStringEncoding)encoding
{
return cStringLength_u((GSStr)self, encoding);
+}
+
+- (long long) longLongValue
+{
+ char buf[24];
+
+ intBuf_u((GSStr)self, buf);
+ return strtoll(buf, 0, 10);
}
- (const char*) lossyCString
@@ -4832,10 +5072,28 @@
- (int) intValue
{
+ char buf[24];
+
if (_flags.wide == 1)
- return intValue_u((GSStr)self);
- else
- return intValue_c((GSStr)self);
+ intBuf_u((GSStr)self, buf);
+ else
+ intBuf_c((GSStr)self, buf);
+ return strtol(buf, 0, 10);
+}
+
+- (NSInteger) integerValue
+{
+ char buf[24];
+
+ if (_flags.wide == 1)
+ intBuf_u((GSStr)self, buf);
+ else
+ intBuf_c((GSStr)self, buf);
+#if GS_SIZEOF_VOIDP == GS_SIZEOF_LONG
+ return strtol(buf, 0, 10);
+#else
+ return strtoll(buf, 0, 10);
+#endif
}
- (BOOL) isEqual: (id)anObject
@@ -4865,6 +5123,17 @@
return cStringLength_u((GSStr)self, encoding);
else
return cStringLength_c((GSStr)self, encoding);
+}
+
+- (long long) longLongValue
+{
+ char buf[24];
+
+ if (_flags.wide == 1)
+ intBuf_u((GSStr)self, buf);
+ else
+ intBuf_c((GSStr)self, buf);
+ return strtoll(buf, 0, 10);
}
- (const char*) lossyCString
@@ -5619,9 +5888,28 @@
return literalIsEqual(self, other);
}
+- (int) intValue
+{
+ return strtol((const char*)nxcsptr, 0, 10);
+}
+
+- (NSInteger) integerValue
+{
+#if GS_SIZEOF_VOIDP == GS_SIZEOF_LONG
+ return strtol((const char*)nxcsptr, 0, 10);
+#else
+ return strtoll((const char*)nxcsptr, 0, 10);
+#endif
+}
+
- (NSUInteger) length
{
return lengthUTF8((const uint8_t*)nxcsptr, nxcslen, 0, 0);
+}
+
+- (long long) longLongValue
+{
+ return strtoll((const char*)nxcsptr, 0, 10);
}
- (NSRange) rangeOfCharacterFromSet: (NSCharacterSet*)aSet
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs