Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -274,10 +274,26 @@ * \param delimiter The delimiter for splitting * \return An autoreleased OFArray with the splitted string */ - (OFArray*)splitWithDelimiter: (OFString*)delimiter; +/** + * Returns the decimal value of the string as an intmax_t or throws an + * OFInvalidEncoding exception if the string contains any non-number characters. + * + * \return An OFNumber + */ +- (intmax_t)decimalValueAsInteger; + +/** + * Returns the hexadecimal value of the string as an intmax_t or throws an + * OFInvalidEncoding exception if the string contains any non-number characters. + * + * \return An OFNumber + */ +- (intmax_t)hexadecimalValueAsInteger; + - setToCString: (const char*)str; - appendCString: (const char*)str; - appendCString: (const char*)str withLength: (size_t)len; - appendCStringWithoutUTF8Checking: (const char*)str; Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -721,10 +721,61 @@ [pool release]; return array; } + +- (intmax_t)decimalValueAsInteger +{ + int i = 0; + intmax_t num = 0; + + if (string[0] == '-') + i++; + + for (; i < length; i++) { + if (string[i] >= '0' && string[i] <= '9') + num = (num * 10) + (string[i] - '0'); + else + @throw [OFInvalidEncodingException newWithClass: isa]; + } + + if (string[0] == '-') + num *= -1; + + return num; +} + +- (intmax_t)hexadecimalValueAsInteger +{ + int i = 0; + intmax_t num = 0; + + if (length == 0) + return 0; + + if (length >= 2 && string[0] == '0' && string[1] == 'x') + i = 2; + else if (length >= 1 && (string[0] == 'x' || string[0] == '$')) + i = 1; + + if (i == length) + @throw [OFInvalidEncodingException newWithClass: isa]; + + for (; i < length; i++) { + if (string[i] >= '0' && string[i] <= '9') + num = (num << 4) | (string[i] - '0'); + else if (string[i] >= 'A' && string[i] <= 'F') + num = (num << 4) | (string[i] - 'A' + 10); + else if (string[i] >= 'a' && string[i] <= 'f') + num = (num << 4) | (string[i] - 'a' + 10); + else + @throw [OFInvalidEncodingException newWithClass: isa]; + } + + return num; +} - setToCString: (const char*)str { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; Index: tests/string.m ================================================================== --- tests/string.m +++ tests/string.m @@ -175,10 +175,38 @@ [[a objectAtIndex: i++] isEqual: @""] && [[a objectAtIndex: i++] isEqual: @"baz"] && [[a objectAtIndex: i++] isEqual: @""] && [[a objectAtIndex: i++] isEqual: @""]) + TEST(@"-[decimalValueAsInteger]", + [@"1234" decimalValueAsInteger] == 1234 && + [@"" decimalValueAsInteger] == 0) + + TEST(@"-[hexadecimalValueAsInteger]", + [@"123f" hexadecimalValueAsInteger] == 0x123f && + [@"0xABcd" hexadecimalValueAsInteger] == 0xABCD && + [@"xbCDE" hexadecimalValueAsInteger] == 0xBCDE && + [@"$CdEf" hexadecimalValueAsInteger] == 0xCDEF && + [@"" hexadecimalValueAsInteger] == 0) + + EXPECT_EXCEPTION(@"Detect invalid characters in " + @"-[decimalValueAsInteger] #1", OFInvalidEncodingException, + [@"abc" decimalValueAsInteger]) + EXPECT_EXCEPTION(@"Detect invalid characters in " + @"-[decimalValueAsInteger] #2", OFInvalidEncodingException, + [@"0a" decimalValueAsInteger]) + + EXPECT_EXCEPTION(@"Detect invalid chars in " + @"-[hexadecimalValueAsInteger] #1", OFInvalidEncodingException, + [@"0xABCDEFG" hexadecimalValueAsInteger]) + EXPECT_EXCEPTION(@"Detect invalid chars in " + @"-[hexadecimalValueAsInteger] #2", OFInvalidEncodingException, + [@"0x" hexadecimalValueAsInteger]) + EXPECT_EXCEPTION(@"Detect invalid chars in " + @"-[hexadecimalValueAsInteger] #3", OFInvalidEncodingException, + [@"$" hexadecimalValueAsInteger]) + TEST(@"-[md5Hash]", [[@"asdfoobar" md5Hash] isEqual: @"184dce2ec49b5422c7cfd8728864db4c"]) TEST(@"-[sha1Hash]", [[@"asdfoobar" sha1Hash] isEqual: @"f5f81ac0a8b5cbfdc4585ec1ad32e7b3a12b9b49"])