@@ -415,34 +415,24 @@ s->cString = [self allocMemoryWithSize: (length * 4) + 1]; s->length = length; for (i = 0; i < length; i++) { char buffer[4]; + size_t len = of_string_utf8_encode(characters[i], + buffer); - switch (of_string_utf8_encode(characters[i], buffer)) { + switch (len) { case 1: s->cString[j++] = buffer[0]; break; case 2: - s->isUTF8 = YES; - - memcpy(s->cString + j, buffer, 2); - j += 2; - - break; case 3: - s->isUTF8 = YES; - - memcpy(s->cString + j, buffer, 3); - j += 3; - - break; case 4: s->isUTF8 = YES; - memcpy(s->cString + j, buffer, 4); - j += 4; + memcpy(s->cString + j, buffer, len); + j += len; break; default: @throw [OFInvalidEncodingException exceptionWithClass: [self class]]; @@ -486,19 +476,18 @@ } else if (byteOrder != OF_BYTE_ORDER_NATIVE) swap = YES; s = &s_store; - s->cStringLength = length; s->cString = [self allocMemoryWithSize: (length * 4) + 1]; s->length = length; for (i = 0; i < length; i++) { char buffer[4]; of_unichar_t character = (swap ? OF_BSWAP16(string[i]) : string[i]); - size_t characterLen; + size_t len; /* Missing high surrogate */ if ((character & 0xFC00) == 0xDC00) @throw [OFInvalidEncodingException exceptionWithClass: [self class]]; @@ -520,55 +509,40 @@ character = (((character & 0x3FF) << 10) | (nextCharacter & 0x3FF)) + 0x10000; i++; - s->cStringLength--; s->length--; } - characterLen = of_string_utf8_encode(character, buffer); + len = of_string_utf8_encode(character, buffer); - switch (characterLen) { + switch (len) { case 1: s->cString[j++] = buffer[0]; break; case 2: - s->isUTF8 = YES; - s->cStringLength++; - - memcpy(s->cString + j, buffer, 2); - j += 2; - - break; case 3: - s->isUTF8 = YES; - s->cStringLength += 2; - - memcpy(s->cString + j, buffer, 3); - j += 3; - - break; case 4: s->isUTF8 = YES; - s->cStringLength += 3; - memcpy(s->cString + j, buffer, 4); - j += 4; + memcpy(s->cString + j, buffer, len); + j += len; break; default: @throw [OFInvalidEncodingException exceptionWithClass: [self class]]; } } s->cString[j] = '\0'; + s->cStringLength = j; @try { s->cString = [self resizeMemory: s->cString - size: s->cStringLength + 1]; + size: j + 1]; } @catch (OFOutOfMemoryException *e) { /* We don't care, as we only tried to make it smaller */ } } @catch (id e) { [self release]; @@ -603,37 +577,25 @@ s->cString = [self allocMemoryWithSize: (length * 4) + 1]; s->length = length; for (i = 0; i < length; i++) { char buffer[4]; - size_t characterLen = of_string_utf8_encode( + size_t len = of_string_utf8_encode( (swap ? OF_BSWAP32(characters[i]) : characters[i]), buffer); - switch (characterLen) { + switch (len) { case 1: s->cString[j++] = buffer[0]; break; case 2: - s->isUTF8 = YES; - - memcpy(s->cString + j, buffer, 2); - j += 2; - - break; case 3: - s->isUTF8 = YES; - - memcpy(s->cString + j, buffer, 3); - j += 3; - - break; case 4: s->isUTF8 = YES; - memcpy(s->cString + j, buffer, 4); - j += 4; + memcpy(s->cString + j, buffer, len); + j += len; break; default: @throw [OFInvalidEncodingException exceptionWithClass: [self class]]; @@ -773,21 +735,45 @@ if (s != NULL && s->freeWhenDone != NULL) free(s->freeWhenDone); [super dealloc]; } + +- (size_t)getCString: (char*)cString + maxLength: (size_t)maxLength + encoding: (of_string_encoding_t)encoding +{ + switch (encoding) { + case OF_STRING_ENCODING_ASCII: + if (s->isUTF8) + @throw [OFInvalidEncodingException + exceptionWithClass: [self class]]; + /* intentional fall-through */ + case OF_STRING_ENCODING_UTF_8: + if (s->cStringLength + 1 > maxLength) + @throw [OFOutOfRangeException + exceptionWithClass: [self class]]; + + memcpy(cString, s->cString, s->cStringLength + 1); + + return s->cStringLength; + default: + return [super getCString: cString + maxLength: maxLength + encoding: encoding]; + } +} - (const char*)cStringWithEncoding: (of_string_encoding_t)encoding { switch (encoding) { - case OF_STRING_ENCODING_UTF_8: - return s->cString; case OF_STRING_ENCODING_ASCII: if (s->isUTF8) @throw [OFInvalidEncodingException exceptionWithClass: [self class]]; - + /* intentional fall-through */ + case OF_STRING_ENCODING_UTF_8: return s->cString; default: return [super cStringWithEncoding: encoding]; } }