Index: .fossil-settings/clean-glob
==================================================================
--- .fossil-settings/clean-glob
+++ .fossil-settings/clean-glob
@@ -25,10 +25,11 @@
extra.mk
generators/gen_tables
src/Info.plist
src/bridge/Info.plist
src/objfw-defs.h
+src/runtime/Info.plist
src/runtime/amiga-library-functable.inc
src/runtime/inline.h
tests/DerivedData
tests/EBOOT.PBP
tests/Info.plist
Index: .fossil-settings/ignore-glob
==================================================================
--- .fossil-settings/ignore-glob
+++ .fossil-settings/ignore-glob
@@ -27,10 +27,11 @@
extra.mk
generators/gen_tables
src/Info.plist
src/bridge/Info.plist
src/objfw-defs.h
+src/runtime/Info.plist
src/runtime/amiga-library-functable.inc
src/runtime/inline.h
tests/DerivedData
tests/EBOOT.PBP
tests/Info.plist
Index: .gitignore
==================================================================
--- .gitignore
+++ .gitignore
@@ -27,10 +27,11 @@
extra.mk
generators/gen_tables
src/Info.plist
src/bridge/Info.plist
src/objfw-defs.h
+src/runtime/Info.plist
src/runtime/amiga-library-functable.inc
src/runtime/inline.h
tests/DerivedData
tests/EBOOT.PBP
tests/Info.plist
Index: README.md
==================================================================
--- README.md
+++ README.md
@@ -119,16 +119,23 @@
It's also possible to open the same local repository multiple times, so that
you have multiple working directories all backed by the same local
repository.
+ In order to verify the signature of the currently checked out checkin, you
+ can use:
+
+ $ fossil artifact current | gpg --verify
+
Git
To clone the Git repository, use the following:
$ git clone https://github.com/ObjFW/ObjFW
+ Git commits are not signed, so if you want to check the signature of an
+ individual commit, branch head or tag, please use Fossil.
Installation
To install ObjFW, just run the following commands:
Index: configure.ac
==================================================================
--- configure.ac
+++ configure.ac
@@ -412,10 +412,11 @@
AC_DEFINE_UNQUOTED(PLUGIN_SUFFIX, "$PLUGIN_SUFFIX", [Suffix for plugins])
AS_IF([test x"$enable_files" != x"no" -a x"$PLUGIN_SUFFIX" != x""], [
AC_SUBST(USE_SRCS_PLUGINS, '${SRCS_PLUGINS}')
AC_SUBST(TESTPLUGIN, "plugin")
AC_DEFINE(OF_HAVE_PLUGINS, 1, [Whether we have plugin support])
+ AC_CONFIG_FILES(tests/plugin/Info.plist)
AS_IF([test x"$build_framework" = x"yes"], [
TESTPLUGIN_LIBS="-F../../src -F../../src/runtime"
TESTPLUGIN_LIBS="$TESTPLUGIN_LIBS -framework ObjFW"
TESTPLUGIN_LIBS="$TESTPLUGIN_LIBS \${RUNTIME_FRAMEWORK_LIBS}"
@@ -522,10 +523,11 @@
AC_MSG_RESULT(no)
old_compiler="yes"
])
AC_SUBST(RUNTIME, "runtime")
+ AC_CONFIG_FILES(src/runtime/Info.plist)
AS_IF([test x"$enable_shared" != x"no"], [
AC_SUBST(OBJFWRT_SHARED_LIB,
"${LIB_PREFIX}objfwrt${LIB_SUFFIX}")
])
@@ -1572,10 +1574,11 @@
])
AS_IF([test x"$objc_runtime" = x"Apple runtime"], [
AC_CHECK_HEADER(Foundation/NSObject.h, [
AC_SUBST(BRIDGE, "bridge")
+ AC_CONFIG_FILES(src/bridge/Info.plist)
AS_IF([test x"$enable_shared" != x"no"], [
AC_SUBST(OBJFWBRIDGE_SHARED_LIB,
"${LIB_PREFIX}objfwbridge${LIB_SUFFIX}")
])
@@ -1907,13 +1910,11 @@
AC_CONFIG_FILES([
buildsys.mk
extra.mk
src/Info.plist
- src/bridge/Info.plist
tests/Info.plist
- tests/plugin/Info.plist
utils/objfw-config
])
AC_CONFIG_HEADERS([config.h src/objfw-defs.h])
AC_OUTPUT
Index: generators/TableGenerator.m
==================================================================
--- generators/TableGenerator.m
+++ generators/TableGenerator.m
@@ -119,22 +119,22 @@
if (components.count != 15) {
of_log(@"Invalid line: %@\n", line);
[OFApplication terminateWithStatus: 1];
}
- codePoint = (of_unichar_t)
- [[components objectAtIndex: 0] hexadecimalValue];
+ codePoint = (of_unichar_t)[[components objectAtIndex: 0]
+ unsignedLongLongValueWithBase: 16];
if (codePoint > 0x10FFFF)
@throw [OFOutOfRangeException exception];
- _uppercaseTable[codePoint] = (of_unichar_t)
- [[components objectAtIndex: 12] hexadecimalValue];
- _lowercaseTable[codePoint] = (of_unichar_t)
- [[components objectAtIndex: 13] hexadecimalValue];
- _titlecaseTable[codePoint] = (of_unichar_t)
- [[components objectAtIndex: 14] hexadecimalValue];
+ _uppercaseTable[codePoint] = (of_unichar_t)[[components
+ objectAtIndex: 12] unsignedLongLongValueWithBase: 16];
+ _lowercaseTable[codePoint] = (of_unichar_t)[[components
+ objectAtIndex: 13] unsignedLongLongValueWithBase: 16];
+ _titlecaseTable[codePoint] = (of_unichar_t)[[components
+ objectAtIndex: 14] unsignedLongLongValueWithBase: 16];
if ([[components objectAtIndex: 5] length] > 0) {
OFArray *decomposed = [[components objectAtIndex: 5]
componentsSeparatedByString: @" "];
bool compat = false;
@@ -147,12 +147,12 @@
}
string = [OFMutableString string];
for (OFString *character in decomposed) {
- of_unichar_t unichar =
- (of_unichar_t)character.hexadecimalValue;
+ of_unichar_t unichar = (of_unichar_t)[character
+ unsignedLongLongValueWithBase: 16];
[string appendCharacters: &unichar
length: 1];
}
@@ -202,18 +202,18 @@
if (![[components objectAtIndex: 1] isEqual: @"S"] &&
![[components objectAtIndex: 1] isEqual: @"C"])
continue;
- codePoint = (of_unichar_t)
- [[components objectAtIndex: 0] hexadecimalValue];
+ codePoint = (of_unichar_t)[[components objectAtIndex: 0]
+ unsignedLongLongValueWithBase: 16];
if (codePoint > 0x10FFFF)
@throw [OFOutOfRangeException exception];
- _casefoldingTable[codePoint] = (of_unichar_t)
- [[components objectAtIndex: 2] hexadecimalValue];
+ _casefoldingTable[codePoint] = (of_unichar_t)[[components
+ objectAtIndex: 2] unsignedLongLongValueWithBase: 16];
objc_autoreleasePoolPop(pool2);
}
[of_stdout writeLine: @" done"];
@@ -265,10 +265,12 @@
[table[i] release];
table[i] = [replacement copy];
done = false;
}
+
+ objc_autoreleasePoolPop(pool);
}
} while (!done);
}
- (void)writeFiles
Index: src/Info.plist.in
==================================================================
--- src/Info.plist.in
+++ src/Info.plist.in
@@ -5,11 +5,11 @@
CFBundleExecutable
ObjFW
CFBundleName
ObjFW
CFBundleIdentifier
- zone.heap.objfw
+ im.nil.objfw
CFBundleInfoDictionaryVersion
6.0
CFBundlePackageType
FMWK
CFBundleVersion
Index: src/Makefile
==================================================================
--- src/Makefile
+++ src/Makefile
@@ -27,13 +27,13 @@
OFCharacterSet.m \
OFColor.m \
OFConstantString.m \
OFCountedSet.m \
OFData.m \
- OFData+ASN1DERValue.m \
+ OFData+ASN1DERParsing.m \
OFData+CryptoHashing.m \
- OFData+MessagePackValue.m \
+ OFData+MessagePackParsing.m \
OFDate.m \
OFDictionary.m \
OFEnumerator.m \
OFFileManager.m \
OFGZIPStream.m \
@@ -84,12 +84,12 @@
OFSortedList.m \
OFStdIOStream.m \
OFStream.m \
OFString.m \
OFString+CryptoHashing.m \
- OFString+JSONValue.m \
- OFString+PropertyListValue.m \
+ OFString+JSONParsing.m \
+ OFString+PropertyListParsing.m \
OFString+Serialization.m \
OFString+URLEncoding.m \
OFString+XMLEscaping.m \
OFString+XMLUnescaping.m \
OFSystemInfo.m \
Index: src/OFASN1Enumerated.h
==================================================================
--- src/OFASN1Enumerated.h
+++ src/OFASN1Enumerated.h
@@ -24,37 +24,36 @@
* @brief An ASN.1 Enumerated.
*/
OF_SUBCLASSING_RESTRICTED
@interface OFASN1Enumerated: OFObject
{
- intmax_t _integerValue;
+ long long _longLongValue;
}
/*!
* @brief The integer value.
*/
-@property (readonly, nonatomic) intmax_t integerValue;
+@property (readonly, nonatomic) long long longLongValue;
/*!
* @brief Creates an ASN.1 Enumerated with the specified integer value.
*
- * @param integerValue The integer value of the Enumerated
+ * @param value The `long long` value of the Enumerated
* @return A new, autoreleased OFASN1Enumerated
*/
-+ (instancetype)enumeratedWithIntegerValue: (intmax_t)integerValue;
++ (instancetype)enumeratedWithLongLong: (long long)value;
- (instancetype)init OF_UNAVAILABLE;
/*!
* @brief Initializes an already allocated ASN.1 Enumerated with the specified
* integer value.
*
- * @param integerValue The integer value of the Enumerated
+ * @param value The `long long` value of the Enumerated
* @return An initialized OFASN1Enumerated
*/
-- (instancetype)initWithIntegerValue: (intmax_t)integerValue
- OF_DESIGNATED_INITIALIZER;
+- (instancetype)initWithLongLong: (long long)value OF_DESIGNATED_INITIALIZER;
/*!
* @brief Initializes an already allocated ASN.1 Enumerated with the specified
* arguments.
*
Index: src/OFASN1Enumerated.m
==================================================================
--- src/OFASN1Enumerated.m
+++ src/OFASN1Enumerated.m
@@ -21,53 +21,53 @@
#import "OFData.h"
#import "OFString.h"
#import "OFInvalidArgumentException.h"
-extern intmax_t of_asn1_der_integer_parse(const unsigned char *buffer,
+extern long long of_asn1_der_integer_parse(const unsigned char *buffer,
size_t length);
@implementation OFASN1Enumerated
-@synthesize integerValue = _integerValue;
+@synthesize longLongValue = _longLongValue;
-+ (instancetype)enumeratedWithIntegerValue: (intmax_t)integerValue
++ (instancetype)enumeratedWithLongLong: (long long)value
{
- return [[[self alloc] initWithIntegerValue: integerValue] autorelease];
+ return [[[self alloc] initWithLongLong: value] autorelease];
}
-- (instancetype)initWithIntegerValue: (intmax_t)integerValue
+- (instancetype)initWithLongLong: (long long)value
{
self = [super init];
- _integerValue = integerValue;
+ _longLongValue = value;
return self;
}
- (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass
tagNumber: (of_asn1_tag_number_t)tagNumber
constructed: (bool)constructed
DEREncodedContents: (OFData *)DEREncodedContents
{
- intmax_t integerValue;
+ long long value;
@try {
if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL ||
tagNumber != OF_ASN1_TAG_NUMBER_ENUMERATED || constructed)
@throw [OFInvalidArgumentException exception];
if (DEREncodedContents.itemSize != 1)
@throw [OFInvalidArgumentException exception];
- integerValue = of_asn1_der_integer_parse(
+ value = of_asn1_der_integer_parse(
DEREncodedContents.items, DEREncodedContents.count);
} @catch (id e) {
[self release];
@throw e;
}
- return [self initWithIntegerValue: integerValue];
+ return [self initWithLongLong: value];
}
- (instancetype)init
{
OF_INVALID_INIT_METHOD
@@ -83,22 +83,22 @@
if (![object isKindOfClass: [OFASN1Enumerated class]])
return false;
enumerated = object;
- if (enumerated->_integerValue != _integerValue)
+ if (enumerated->_longLongValue != _longLongValue)
return false;
return true;
}
- (uint32_t)hash
{
- return (uint32_t)_integerValue;
+ return (uint32_t)_longLongValue;
}
- (OFString *)description
{
- return [OFString stringWithFormat: @"",
- _integerValue];
+ return [OFString stringWithFormat: @"",
+ _longLongValue];
}
@end
Index: src/OFASN1Integer.h
==================================================================
--- src/OFASN1Integer.h
+++ src/OFASN1Integer.h
@@ -24,37 +24,36 @@
* @brief An ASN.1 Integer.
*/
OF_SUBCLASSING_RESTRICTED
@interface OFASN1Integer: OFObject
{
- intmax_t _integerValue;
+ long long _longLongValue;
}
/*!
* @brief The Integer value.
*/
-@property (readonly, nonatomic) intmax_t integerValue;
+@property (readonly, nonatomic) long long longLongValue;
/*!
* @brief Creates an ASN.1 Integer with the specified integer value.
*
- * @param integerValue The integer value of the Integer
+ * @param value The `long long` value of the Integer
* @return A new, autoreleased OFASN1Integer
*/
-+ (instancetype)integerWithIntegerValue: (intmax_t)integerValue;
++ (instancetype)integerWithLongLong: (long long)value;
- (instancetype)init OF_UNAVAILABLE;
/*!
* @brief Initializes an already allocated ASN.1 Integer with the specified
* integer value.
*
- * @param integerValue The integer value of the Integer
+ * @param value The `long long` value of the Integer
* @return An initialized OFASN1Integer
*/
-- (instancetype)initWithIntegerValue: (intmax_t)integerValue
- OF_DESIGNATED_INITIALIZER;
+- (instancetype)initWithLongLong: (long long)value OF_DESIGNATED_INITIALIZER;
/*!
* @brief Initializes an already allocated ASN.1 Integer with the specified
* arguments.
*
Index: src/OFASN1Integer.m
==================================================================
--- src/OFASN1Integer.m
+++ src/OFASN1Integer.m
@@ -23,73 +23,73 @@
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"
-intmax_t
+long long
of_asn1_der_integer_parse(const unsigned char *buffer, size_t length)
{
- uintmax_t value = 0;
+ unsigned long long value = 0;
/* TODO: Support for big numbers */
- if (length > sizeof(uintmax_t) &&
- (length != sizeof(uintmax_t) + 1 || buffer[0] != 0))
+ if (length > sizeof(unsigned long long) &&
+ (length != sizeof(unsigned long long) + 1 || buffer[0] != 0))
@throw [OFOutOfRangeException exception];
if (length >= 2 && ((buffer[0] == 0 && !(buffer[1] & 0x80)) ||
(buffer[0] == 0xFF && buffer[1] & 0x80)))
@throw [OFInvalidFormatException exception];
if (length >= 1 && buffer[0] & 0x80)
- value = ~(uintmax_t)0;
+ value = ~0ull;
while (length--)
value = (value << 8) | *buffer++;
return value;
}
@implementation OFASN1Integer
-@synthesize integerValue = _integerValue;
+@synthesize longLongValue = _longLongValue;
-+ (instancetype)integerWithIntegerValue: (intmax_t)integerValue
++ (instancetype)integerWithLongLong: (long long)value
{
- return [[[self alloc] initWithIntegerValue: integerValue] autorelease];
+ return [[[self alloc] initWithLongLong: value] autorelease];
}
-- (instancetype)initWithIntegerValue: (intmax_t)integerValue
+- (instancetype)initWithLongLong: (long long)value
{
self = [super init];
- _integerValue = integerValue;
+ _longLongValue = value;
return self;
}
- (instancetype)initWithTagClass: (of_asn1_tag_class_t)tagClass
tagNumber: (of_asn1_tag_number_t)tagNumber
constructed: (bool)constructed
DEREncodedContents: (OFData *)DEREncodedContents
{
- intmax_t integerValue;
+ long long value;
@try {
if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL ||
tagNumber != OF_ASN1_TAG_NUMBER_INTEGER || constructed)
@throw [OFInvalidArgumentException exception];
if (DEREncodedContents.itemSize != 1)
@throw [OFInvalidArgumentException exception];
- integerValue = of_asn1_der_integer_parse(
+ value = of_asn1_der_integer_parse(
DEREncodedContents.items, DEREncodedContents.count);
} @catch (id e) {
[self release];
@throw e;
}
- return [self initWithIntegerValue: integerValue];
+ return [self initWithLongLong: value];
}
- (instancetype)init
{
OF_INVALID_INIT_METHOD
@@ -105,22 +105,22 @@
if (![object isKindOfClass: [OFASN1Integer class]])
return false;
integer = object;
- if (integer->_integerValue != _integerValue)
+ if (integer->_longLongValue != _longLongValue)
return false;
return true;
}
- (uint32_t)hash
{
- return (uint32_t)_integerValue;
+ return (uint32_t)_longLongValue;
}
- (OFString *)description
{
- return [OFString stringWithFormat: @"",
- _integerValue];
+ return [OFString stringWithFormat: @"",
+ _longLongValue];
}
@end
Index: src/OFASN1ObjectIdentifier.m
==================================================================
--- src/OFASN1ObjectIdentifier.m
+++ src/OFASN1ObjectIdentifier.m
@@ -44,11 +44,11 @@
@try {
if (subidentifiers.count < 1)
@throw [OFInvalidFormatException exception];
- switch ([[subidentifiers objectAtIndex: 0] intMaxValue]) {
+ switch ([[subidentifiers objectAtIndex: 0] longLongValue]) {
case 0:
case 1:
case 2:
break;
default:
@@ -73,11 +73,11 @@
OFMutableArray OF_GENERIC(OFNumber *) *subidentifiers;
@try {
const unsigned char *items = DEREncodedContents.items;
size_t count = DEREncodedContents.count;
- uintmax_t value = 0;
+ unsigned long long value = 0;
uint_fast8_t bits = 0;
if (tagClass != OF_ASN1_TAG_CLASS_UNIVERSAL ||
tagNumber != OF_ASN1_TAG_NUMBER_OBJECT_IDENTIFIER ||
constructed)
@@ -93,33 +93,33 @@
@throw [OFInvalidFormatException exception];
value = (value << 7) | (items[i] & 0x7F);
bits += 7;
- if (bits > sizeof(uintmax_t) * 8)
+ if (bits > sizeof(unsigned long long) * 8)
@throw [OFOutOfRangeException exception];
if (items[i] & 0x80)
continue;
if (subidentifiers.count == 0) {
if (value < 40)
[subidentifiers addObject:
- [OFNumber numberWithUIntMax: 0]];
+ [OFNumber numberWithInt: 0]];
else if (value < 80) {
[subidentifiers addObject:
- [OFNumber numberWithUIntMax: 1]];
+ [OFNumber numberWithInt: 1]];
value -= 40;
} else {
[subidentifiers addObject:
- [OFNumber numberWithUIntMax: 2]];
+ [OFNumber numberWithInt: 2]];
value -= 80;
}
}
[subidentifiers addObject:
- [OFNumber numberWithUIntMax: value]];
+ [OFNumber numberWithUnsignedLongLong: value]];
value = 0;
bits = 0;
}
Index: src/OFConstantString.m
==================================================================
--- src/OFConstantString.m
+++ src/OFConstantString.m
@@ -573,29 +573,36 @@
[self finishInitialization];
return self.stringByDeletingLastPathComponent;
}
-- (intmax_t)decimalValue
+- (long long)longLongValue
+{
+ [self finishInitialization];
+
+ return self.longLongValue;
+}
+
+- (long long)longLongValueWithBase: (int)base
+{
+ [self finishInitialization];
+
+ return [self longLongValueWithBase: base];
+}
+
+- (unsigned long long)unsignedLongLongValue
{
[self finishInitialization];
- return self.decimalValue;
+ return self.unsignedLongLongValue;
}
-- (uintmax_t)hexadecimalValue
+- (unsigned long long)unsignedLongLongValueWithBase: (int)base
{
[self finishInitialization];
- return self.hexadecimalValue;
-}
-
-- (uintmax_t)octalValue
-{
- [self finishInitialization];
-
- return self.octalValue;
+ return [self unsignedLongLongValueWithBase: base];
}
- (float)floatValue
{
[self finishInitialization];
Index: src/OFCountedMapTableSet.m
==================================================================
--- src/OFCountedMapTableSet.m
+++ src/OFCountedMapTableSet.m
@@ -136,26 +136,21 @@
[element elementsForName: @"object"
namespace: OF_SERIALIZATION_NS]) {
void *pool2 = objc_autoreleasePoolPush();
OFXMLElement *object;
OFXMLAttribute *countAttribute;
- intmax_t signedCount;
- uintmax_t count;
+ unsigned long long count;
object = [objectElement elementsForNamespace:
OF_SERIALIZATION_NS].firstObject;
countAttribute =
[objectElement attributeForName: @"count"];
if (object == nil || countAttribute == nil)
@throw [OFInvalidFormatException exception];
- signedCount = countAttribute.decimalValue;
- if (signedCount < 0)
- @throw [OFOutOfRangeException exception];
-
- count = signedCount;
+ count = countAttribute.unsignedLongLongValue;
if (count > SIZE_MAX || count > UINTPTR_MAX)
@throw [OFOutOfRangeException exception];
[_mapTable setObject: (void *)(uintptr_t)count
forKey: object.objectByDeserializing];
Index: src/OFDNSResolver.m
==================================================================
--- src/OFDNSResolver.m
+++ src/OFDNSResolver.m
@@ -491,11 +491,11 @@
queryData = [OFMutableData dataWithCapacity: 512];
/* Header */
- tmp = OF_BSWAP16_IF_LE(_ID.uInt16Value);
+ tmp = OF_BSWAP16_IF_LE(_ID.unsignedShortValue);
[queryData addItems: &tmp
count: 2];
/* RD */
tmp = OF_BSWAP16_IF_LE(1u << 8);
@@ -812,11 +812,11 @@
OFNumber *ID;
OFDNSResolverContext *context;
/* Random, unused ID */
do {
- ID = [OFNumber numberWithUInt16: of_random16()];
+ ID = [OFNumber numberWithUnsignedShort: of_random16()];
} while ([_queries objectForKey: ID] != nil);
if (query.domainName.UTF8StringLength > 253)
@throw [OFOutOfRangeException exception];
@@ -911,11 +911,11 @@
if (length < 2)
/* We can't get the ID to get the context. Ignore packet. */
return true;
- ID = [OFNumber numberWithUInt16: (buffer[0] << 8) | buffer[1]];
+ ID = [OFNumber numberWithUnsignedShort: (buffer[0] << 8) | buffer[1]];
context = [[[_queries objectForKey: ID] retain] autorelease];
if (context == nil)
return true;
Index: src/OFDNSResolverSettings.m
==================================================================
--- src/OFDNSResolverSettings.m
+++ src/OFDNSResolverSettings.m
@@ -32,10 +32,11 @@
#endif
#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfMemoryException.h"
+#import "OFOutOfRangeException.h"
#ifdef OF_WINDOWS
# define interface struct
# include
# undef interface
@@ -236,30 +237,41 @@
# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4)
- (void)parseResolvConfOption: (OFString *)option
{
@try {
if ([option hasPrefix: @"ndots:"]) {
+ unsigned long long number;
+
option = [option substringWithRange:
of_range(6, option.length - 6)];
+ number = option.unsignedLongLongValue;
+
+ if (number > UINT_MAX)
+ @throw [OFOutOfRangeException exception];
- _minNumberOfDotsInAbsoluteName =
- (unsigned int)option.decimalValue;
+ _minNumberOfDotsInAbsoluteName = (unsigned int)number;
} else if ([option hasPrefix: @"timeout:"]) {
option = [option substringWithRange:
of_range(8, option.length - 8)];
- _timeout = option.decimalValue;
+ _timeout = option.unsignedLongLongValue;
} else if ([option hasPrefix: @"attempts:"]) {
+ unsigned long long number;
+
option = [option substringWithRange:
of_range(9, option.length - 9)];
+ number = option.unsignedLongLongValue;
+
+ if (number > UINT_MAX)
+ @throw [OFOutOfRangeException exception];
- _maxAttempts = (unsigned int)option.decimalValue;
+ _maxAttempts = (unsigned int)number;
} else if ([option hasPrefix: @"reload-period:"]) {
option = [option substringWithRange:
of_range(14, option.length - 14)];
- _configReloadInterval = option.decimalValue;
+ _configReloadInterval = option.unsignedLongLongValue;
} else if ([option isEqual: @"tcp"])
_usesTCP = true;
} @catch (OFInvalidFormatException *e) {
}
}
Index: src/OFDNSResourceRecord.m
==================================================================
--- src/OFDNSResourceRecord.m
+++ src/OFDNSResourceRecord.m
@@ -79,11 +79,12 @@
if ([string isEqual: @"IN"])
DNSClass = OF_DNS_CLASS_IN;
else {
@try {
- DNSClass = (of_dns_class_t)string.decimalValue;
+ DNSClass = (of_dns_class_t)
+ [string unsignedLongLongValueWithBase: 0];
} @catch (OFInvalidFormatException *e) {
@throw [OFInvalidArgumentException exception];
}
}
@@ -123,12 +124,12 @@
recordType = OF_DNS_RECORD_TYPE_SRV;
else if ([string isEqual: @"ALL"])
recordType = OF_DNS_RECORD_TYPE_ALL;
else {
@try {
- recordType =
- (of_dns_record_type_t)string.decimalValue;
+ recordType = (of_dns_record_type_t)
+ [string unsignedLongLongValueWithBase: 0];
} @catch (OFInvalidFormatException *e) {
@throw [OFInvalidArgumentException exception];
}
}
ADDED src/OFData+ASN1DERParsing.h
Index: src/OFData+ASN1DERParsing.h
==================================================================
--- src/OFData+ASN1DERParsing.h
+++ src/OFData+ASN1DERParsing.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019, 2020
+ * Jonathan Schleifer
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#import "OFData.h"
+#import "OFASN1Value.h"
+
+OF_ASSUME_NONNULL_BEGIN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int _OFData_ASN1DERParsing_reference;
+#ifdef __cplusplus
+}
+#endif
+
+@interface OFData (ASN1DERParsing)
+/*!
+ * @brief The data interpreted as ASN.1 in DER representation and parsed as an
+ * object.
+ *
+ * This is either an OFArray (for a sequence), an OFSet (for a set) or an
+ * OFASN1Value.
+ */
+@property (readonly, nonatomic) id objectByParsingASN1DER;
+
+/*!
+ * @brief Parses the ASN.1 DER representation and returns it as an object.
+ *
+ * This is either an OFArray (for a sequence), an OFSet (for a set) or an
+ * OFASN1Value.
+ *
+ * @param depthLimit The maximum depth the parser should accept (defaults to 32
+ * if not specified, 0 means no limit (insecure!))
+ * @return The ASN.1 DER representation as an object
+ */
+- (id)objectByParsingASN1DERWithDepthLimit: (size_t)depthLimit;
+@end
+
+OF_ASSUME_NONNULL_END
ADDED src/OFData+ASN1DERParsing.m
Index: src/OFData+ASN1DERParsing.m
==================================================================
--- src/OFData+ASN1DERParsing.m
+++ src/OFData+ASN1DERParsing.m
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019, 2020
+ * Jonathan Schleifer
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#include "config.h"
+
+#import "OFData+ASN1DERParsing.h"
+#import "OFASN1BitString.h"
+#import "OFASN1Boolean.h"
+#import "OFASN1Enumerated.h"
+#import "OFASN1IA5String.h"
+#import "OFASN1Integer.h"
+#import "OFASN1NumericString.h"
+#import "OFASN1ObjectIdentifier.h"
+#import "OFASN1OctetString.h"
+#import "OFASN1PrintableString.h"
+#import "OFASN1UTF8String.h"
+#import "OFASN1Value.h"
+#import "OFArray.h"
+#import "OFNull.h"
+#import "OFSet.h"
+
+#import "OFInvalidArgumentException.h"
+#import "OFInvalidFormatException.h"
+#import "OFOutOfRangeException.h"
+#import "OFTruncatedDataException.h"
+
+enum {
+ ASN1_TAG_CONSTRUCTED_MASK = 0x20
+};
+
+int _OFData_ASN1DERParsing_reference;
+
+static size_t parseObject(OFData *self, id *object, size_t depthLimit);
+
+static OFArray *
+parseSequence(OFData *contents, size_t depthLimit)
+{
+ OFMutableArray *ret = [OFMutableArray array];
+ size_t count = contents.count;
+
+ if (depthLimit == 0)
+ @throw [OFOutOfRangeException exception];
+
+ while (count > 0) {
+ id object;
+ size_t objectLength;
+
+ objectLength = parseObject(contents, &object, depthLimit);
+
+ count -= objectLength;
+ contents = [contents subdataWithRange:
+ of_range(objectLength, count)];
+
+ [ret addObject: object];
+ }
+
+ [ret makeImmutable];
+
+ return ret;
+}
+
+static OFSet *
+parseSet(OFData *contents, size_t depthLimit)
+{
+ OFMutableSet *ret = [OFMutableSet set];
+ size_t count = contents.count;
+ OFData *previousObjectData = nil;
+
+ if (depthLimit == 0)
+ @throw [OFOutOfRangeException exception];
+
+ while (count > 0) {
+ id object;
+ size_t objectLength;
+ OFData *objectData;
+
+ objectLength = parseObject(contents, &object, depthLimit);
+ objectData = [contents subdataWithRange:
+ of_range(0, objectLength)];
+
+ if (previousObjectData != nil &&
+ [objectData compare: previousObjectData] !=
+ OF_ORDERED_DESCENDING)
+ @throw [OFInvalidFormatException exception];
+
+ count -= objectLength;
+ contents = [contents subdataWithRange:
+ of_range(objectLength, count)];
+
+ [ret addObject: object];
+
+ previousObjectData = objectData;
+ }
+
+ [ret makeImmutable];
+
+ return ret;
+}
+
+static size_t
+parseObject(OFData *self, id *object, size_t depthLimit)
+{
+ const unsigned char *items = self.items;
+ size_t count = self.count;
+ unsigned char tag;
+ size_t contentsLength, bytesConsumed = 0;
+ Class valueClass;
+ OFData *contents;
+
+ if (count < 2)
+ @throw [OFTruncatedDataException exception];
+
+ tag = *items++;
+ contentsLength = *items++;
+ bytesConsumed += 2;
+
+ if (contentsLength > 127) {
+ uint_fast8_t lengthLength = contentsLength & 0x7F;
+
+ if (lengthLength > sizeof(size_t))
+ @throw [OFOutOfRangeException exception];
+
+ if (count - bytesConsumed < lengthLength)
+ @throw [OFTruncatedDataException exception];
+
+ if (lengthLength == 0 ||
+ (lengthLength == 1 && items[0] < 0x80) ||
+ (lengthLength >= 2 && items[0] == 0))
+ @throw [OFInvalidFormatException exception];
+
+ contentsLength = 0;
+
+ for (uint_fast8_t i = 0; i < lengthLength; i++)
+ contentsLength = (contentsLength << 8) | *items++;
+
+ bytesConsumed += lengthLength;
+
+ if (contentsLength <= 127)
+ @throw [OFInvalidFormatException exception];
+ }
+
+ if (count - bytesConsumed < contentsLength)
+ @throw [OFTruncatedDataException exception];
+
+ contents = [self subdataWithRange:
+ of_range(bytesConsumed, contentsLength)];
+ bytesConsumed += contentsLength;
+
+ switch (tag & ~ASN1_TAG_CONSTRUCTED_MASK) {
+ case OF_ASN1_TAG_NUMBER_BOOLEAN:
+ valueClass = [OFASN1Boolean class];
+ break;
+ case OF_ASN1_TAG_NUMBER_INTEGER:
+ valueClass = [OFASN1Integer class];
+ break;
+ case OF_ASN1_TAG_NUMBER_BIT_STRING:
+ valueClass = [OFASN1BitString class];
+ break;
+ case OF_ASN1_TAG_NUMBER_OCTET_STRING:
+ valueClass = [OFASN1OctetString class];
+ break;
+ case OF_ASN1_TAG_NUMBER_NULL:
+ if (tag & ASN1_TAG_CONSTRUCTED_MASK)
+ @throw [OFInvalidFormatException exception];
+
+ if (contents.count != 0)
+ @throw [OFInvalidFormatException exception];
+
+ *object = [OFNull null];
+ return bytesConsumed;
+ case OF_ASN1_TAG_NUMBER_OBJECT_IDENTIFIER:
+ valueClass = [OFASN1ObjectIdentifier class];
+ break;
+ case OF_ASN1_TAG_NUMBER_ENUMERATED:
+ valueClass = [OFASN1Enumerated class];
+ break;
+ case OF_ASN1_TAG_NUMBER_UTF8_STRING:
+ valueClass = [OFASN1UTF8String class];
+ break;
+ case OF_ASN1_TAG_NUMBER_SEQUENCE:
+ if (!(tag & ASN1_TAG_CONSTRUCTED_MASK))
+ @throw [OFInvalidFormatException exception];
+
+ *object = parseSequence(contents, depthLimit - 1);
+ return bytesConsumed;
+ case OF_ASN1_TAG_NUMBER_SET:
+ if (!(tag & ASN1_TAG_CONSTRUCTED_MASK))
+ @throw [OFInvalidFormatException exception];
+
+ *object = parseSet(contents, depthLimit - 1);
+ return bytesConsumed;
+ case OF_ASN1_TAG_NUMBER_NUMERIC_STRING:
+ valueClass = [OFASN1NumericString class];
+ break;
+ case OF_ASN1_TAG_NUMBER_PRINTABLE_STRING:
+ valueClass = [OFASN1PrintableString class];
+ break;
+ case OF_ASN1_TAG_NUMBER_IA5_STRING:
+ valueClass = [OFASN1IA5String class];
+ break;
+ default:
+ valueClass = [OFASN1Value class];
+ break;
+ }
+
+ *object = [[[valueClass alloc]
+ initWithTagClass: tag >> 6
+ tagNumber: tag & 0x1F
+ constructed: tag & ASN1_TAG_CONSTRUCTED_MASK
+ DEREncodedContents: contents] autorelease];
+ return bytesConsumed;
+}
+
+@implementation OFData (ASN1DERParsing)
+- (id)objectByParsingASN1DER
+{
+ return [self objectByParsingASN1DERWithDepthLimit: 32];
+}
+
+- (id)objectByParsingASN1DERWithDepthLimit: (size_t)depthLimit
+{
+ void *pool = objc_autoreleasePoolPush();
+ id object;
+
+ if (self.itemSize != 1)
+ @throw [OFInvalidArgumentException exception];
+
+ if (parseObject(self, &object, depthLimit) != self.count)
+ @throw [OFInvalidFormatException exception];
+
+ [object retain];
+
+ objc_autoreleasePoolPop(pool);
+
+ return [object autorelease];
+}
+@end
DELETED src/OFData+ASN1DERValue.h
Index: src/OFData+ASN1DERValue.h
==================================================================
--- src/OFData+ASN1DERValue.h
+++ src/OFData+ASN1DERValue.h
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
- * 2018, 2019, 2020
- * Jonathan Schleifer
- *
- * All rights reserved.
- *
- * This file is part of ObjFW. It may be distributed under the terms of the
- * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
- * the packaging of this file.
- *
- * Alternatively, it may be distributed under the terms of the GNU General
- * Public License, either version 2 or 3, which can be found in the file
- * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
- * file.
- */
-
-#import "OFData.h"
-#import "OFASN1Value.h"
-
-OF_ASSUME_NONNULL_BEGIN
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern int _OFData_ASN1DERValue_reference;
-#ifdef __cplusplus
-}
-#endif
-
-@interface OFData (ASN1DERValue)
-/*!
- * @brief The data interpreted as ASN.1 in DER representation and parsed as an
- * object.
- *
- * This is either an OFArray (for a sequence), an OFSet (for a set) or an
- * OFASN1Value.
- */
-@property (readonly, nonatomic) id ASN1DERValue;
-
-/*!
- * @brief Parses the ASN.1 DER representation and returns it as an object.
- *
- * This is either an OFArray (for a sequence), an OFSet (for a set) or an
- * OFASN1Value.
- *
- * @param depthLimit The maximum depth the parser should accept (defaults to 32
- * if not specified, 0 means no limit (insecure!))
- * @return The ASN.1 DER representation as an object
- */
-- (id)ASN1DERValueWithDepthLimit: (size_t)depthLimit;
-@end
-
-OF_ASSUME_NONNULL_END
DELETED src/OFData+ASN1DERValue.m
Index: src/OFData+ASN1DERValue.m
==================================================================
--- src/OFData+ASN1DERValue.m
+++ src/OFData+ASN1DERValue.m
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
- * 2018, 2019, 2020
- * Jonathan Schleifer
- *
- * All rights reserved.
- *
- * This file is part of ObjFW. It may be distributed under the terms of the
- * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
- * the packaging of this file.
- *
- * Alternatively, it may be distributed under the terms of the GNU General
- * Public License, either version 2 or 3, which can be found in the file
- * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
- * file.
- */
-
-#include "config.h"
-
-#import "OFData+ASN1DERValue.h"
-#import "OFASN1BitString.h"
-#import "OFASN1Boolean.h"
-#import "OFASN1Enumerated.h"
-#import "OFASN1IA5String.h"
-#import "OFASN1Integer.h"
-#import "OFASN1NumericString.h"
-#import "OFASN1ObjectIdentifier.h"
-#import "OFASN1OctetString.h"
-#import "OFASN1PrintableString.h"
-#import "OFASN1UTF8String.h"
-#import "OFASN1Value.h"
-#import "OFArray.h"
-#import "OFNull.h"
-#import "OFSet.h"
-
-#import "OFInvalidArgumentException.h"
-#import "OFInvalidFormatException.h"
-#import "OFOutOfRangeException.h"
-#import "OFTruncatedDataException.h"
-
-enum {
- ASN1_TAG_CONSTRUCTED_MASK = 0x20
-};
-
-int _OFData_ASN1DERValue_reference;
-
-static size_t parseObject(OFData *self, id *object, size_t depthLimit);
-
-static OFArray *
-parseSequence(OFData *contents, size_t depthLimit)
-{
- OFMutableArray *ret = [OFMutableArray array];
- size_t count = contents.count;
-
- if (depthLimit == 0)
- @throw [OFOutOfRangeException exception];
-
- while (count > 0) {
- id object;
- size_t objectLength;
-
- objectLength = parseObject(contents, &object, depthLimit);
-
- count -= objectLength;
- contents = [contents subdataWithRange:
- of_range(objectLength, count)];
-
- [ret addObject: object];
- }
-
- [ret makeImmutable];
-
- return ret;
-}
-
-static OFSet *
-parseSet(OFData *contents, size_t depthLimit)
-{
- OFMutableSet *ret = [OFMutableSet set];
- size_t count = contents.count;
- OFData *previousObjectData = nil;
-
- if (depthLimit == 0)
- @throw [OFOutOfRangeException exception];
-
- while (count > 0) {
- id object;
- size_t objectLength;
- OFData *objectData;
-
- objectLength = parseObject(contents, &object, depthLimit);
- objectData = [contents subdataWithRange:
- of_range(0, objectLength)];
-
- if (previousObjectData != nil &&
- [objectData compare: previousObjectData] !=
- OF_ORDERED_DESCENDING)
- @throw [OFInvalidFormatException exception];
-
- count -= objectLength;
- contents = [contents subdataWithRange:
- of_range(objectLength, count)];
-
- [ret addObject: object];
-
- previousObjectData = objectData;
- }
-
- [ret makeImmutable];
-
- return ret;
-}
-
-static size_t
-parseObject(OFData *self, id *object, size_t depthLimit)
-{
- const unsigned char *items = self.items;
- size_t count = self.count;
- unsigned char tag;
- size_t contentsLength, bytesConsumed = 0;
- Class valueClass;
- OFData *contents;
-
- if (count < 2)
- @throw [OFTruncatedDataException exception];
-
- tag = *items++;
- contentsLength = *items++;
- bytesConsumed += 2;
-
- if (contentsLength > 127) {
- uint_fast8_t lengthLength = contentsLength & 0x7F;
-
- if (lengthLength > sizeof(size_t))
- @throw [OFOutOfRangeException exception];
-
- if (count - bytesConsumed < lengthLength)
- @throw [OFTruncatedDataException exception];
-
- if (lengthLength == 0 ||
- (lengthLength == 1 && items[0] < 0x80) ||
- (lengthLength >= 2 && items[0] == 0))
- @throw [OFInvalidFormatException exception];
-
- contentsLength = 0;
-
- for (uint_fast8_t i = 0; i < lengthLength; i++)
- contentsLength = (contentsLength << 8) | *items++;
-
- bytesConsumed += lengthLength;
-
- if (contentsLength <= 127)
- @throw [OFInvalidFormatException exception];
- }
-
- if (count - bytesConsumed < contentsLength)
- @throw [OFTruncatedDataException exception];
-
- contents = [self subdataWithRange:
- of_range(bytesConsumed, contentsLength)];
- bytesConsumed += contentsLength;
-
- switch (tag & ~ASN1_TAG_CONSTRUCTED_MASK) {
- case OF_ASN1_TAG_NUMBER_BOOLEAN:
- valueClass = [OFASN1Boolean class];
- break;
- case OF_ASN1_TAG_NUMBER_INTEGER:
- valueClass = [OFASN1Integer class];
- break;
- case OF_ASN1_TAG_NUMBER_BIT_STRING:
- valueClass = [OFASN1BitString class];
- break;
- case OF_ASN1_TAG_NUMBER_OCTET_STRING:
- valueClass = [OFASN1OctetString class];
- break;
- case OF_ASN1_TAG_NUMBER_NULL:
- if (tag & ASN1_TAG_CONSTRUCTED_MASK)
- @throw [OFInvalidFormatException exception];
-
- if (contents.count != 0)
- @throw [OFInvalidFormatException exception];
-
- *object = [OFNull null];
- return bytesConsumed;
- case OF_ASN1_TAG_NUMBER_OBJECT_IDENTIFIER:
- valueClass = [OFASN1ObjectIdentifier class];
- break;
- case OF_ASN1_TAG_NUMBER_ENUMERATED:
- valueClass = [OFASN1Enumerated class];
- break;
- case OF_ASN1_TAG_NUMBER_UTF8_STRING:
- valueClass = [OFASN1UTF8String class];
- break;
- case OF_ASN1_TAG_NUMBER_SEQUENCE:
- if (!(tag & ASN1_TAG_CONSTRUCTED_MASK))
- @throw [OFInvalidFormatException exception];
-
- *object = parseSequence(contents, depthLimit - 1);
- return bytesConsumed;
- case OF_ASN1_TAG_NUMBER_SET:
- if (!(tag & ASN1_TAG_CONSTRUCTED_MASK))
- @throw [OFInvalidFormatException exception];
-
- *object = parseSet(contents, depthLimit - 1);
- return bytesConsumed;
- case OF_ASN1_TAG_NUMBER_NUMERIC_STRING:
- valueClass = [OFASN1NumericString class];
- break;
- case OF_ASN1_TAG_NUMBER_PRINTABLE_STRING:
- valueClass = [OFASN1PrintableString class];
- break;
- case OF_ASN1_TAG_NUMBER_IA5_STRING:
- valueClass = [OFASN1IA5String class];
- break;
- default:
- valueClass = [OFASN1Value class];
- break;
- }
-
- *object = [[[valueClass alloc]
- initWithTagClass: tag >> 6
- tagNumber: tag & 0x1F
- constructed: tag & ASN1_TAG_CONSTRUCTED_MASK
- DEREncodedContents: contents] autorelease];
- return bytesConsumed;
-}
-
-@implementation OFData (ASN1DERValue)
-- (id)ASN1DERValue
-{
- return [self ASN1DERValueWithDepthLimit: 32];
-}
-
-- (id)ASN1DERValueWithDepthLimit: (size_t)depthLimit
-{
- void *pool = objc_autoreleasePoolPush();
- id object;
-
- if (self.itemSize != 1)
- @throw [OFInvalidArgumentException exception];
-
- if (parseObject(self, &object, depthLimit) != self.count)
- @throw [OFInvalidFormatException exception];
-
- [object retain];
-
- objc_autoreleasePoolPop(pool);
-
- return [object autorelease];
-}
-@end
ADDED src/OFData+MessagePackParsing.h
Index: src/OFData+MessagePackParsing.h
==================================================================
--- src/OFData+MessagePackParsing.h
+++ src/OFData+MessagePackParsing.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019, 2020
+ * Jonathan Schleifer
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#import "OFData.h"
+
+OF_ASSUME_NONNULL_BEGIN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int _OFData_MessagePackParsing_reference;
+#ifdef __cplusplus
+}
+#endif
+
+@interface OFData (MessagePackParsing)
+/*!
+ * @brief The data interpreted as MessagePack representation and parsed as an
+ * object.
+ */
+@property (readonly, nonatomic) id objectByParsingMessagePack;
+
+/*!
+ * @brief Parses the MessagePack representation and returns it as an object.
+ *
+ * @param depthLimit The maximum depth the parser should accept (defaults to 32
+ * if not specified, 0 means no limit (insecure!))
+ * @return The MessagePack representation as an object
+ */
+- (id)objectByParsingMessagePackWithDepthLimit: (size_t)depthLimit;
+@end
+
+OF_ASSUME_NONNULL_END
ADDED src/OFData+MessagePackParsing.m
Index: src/OFData+MessagePackParsing.m
==================================================================
--- src/OFData+MessagePackParsing.m
+++ src/OFData+MessagePackParsing.m
@@ -0,0 +1,572 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019, 2020
+ * Jonathan Schleifer
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#include "config.h"
+
+#include
+
+#import "OFData+MessagePackParsing.h"
+#import "OFArray.h"
+#import "OFDate.h"
+#import "OFDictionary.h"
+#import "OFMessagePackExtension.h"
+#import "OFNull.h"
+#import "OFNumber.h"
+#import "OFString.h"
+
+#import "OFInvalidArgumentException.h"
+#import "OFInvalidFormatException.h"
+#import "OFOutOfRangeException.h"
+#import "OFTruncatedDataException.h"
+
+int _OFData_MessagePackParsing_reference;
+
+static size_t parseObject(const unsigned char *buffer, size_t length,
+ id *object, size_t depthLimit);
+
+static uint16_t
+readUInt16(const unsigned char *buffer)
+{
+ return ((uint16_t)buffer[0] << 8) | buffer[1];
+}
+
+static uint32_t
+readUInt32(const unsigned char *buffer)
+{
+ return ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) |
+ ((uint32_t)buffer[2] << 8) | buffer[3];
+}
+
+static uint64_t
+readUInt64(const unsigned char *buffer)
+{
+ return ((uint64_t)buffer[0] << 56) | ((uint64_t)buffer[1] << 48) |
+ ((uint64_t)buffer[2] << 40) | ((uint64_t)buffer[3] << 32) |
+ ((uint64_t)buffer[4] << 24) | ((uint64_t)buffer[5] << 16) |
+ ((uint64_t)buffer[6] << 8) | buffer[7];
+}
+
+static size_t
+parseArray(const unsigned char *buffer, size_t length, id *object, size_t count,
+ size_t depthLimit)
+{
+ void *pool;
+ size_t pos = 0;
+
+ if (--depthLimit == 0)
+ @throw [OFOutOfRangeException exception];
+
+ /*
+ * Don't use capacity! For data and strings, this is safe, as we can
+ * check if we still have enough bytes left. For an array however, we
+ * can't know this, as every child can be more than one byte.
+ */
+ *object = [OFMutableArray array];
+
+ for (size_t i = 0; i < count; i++) {
+ id child;
+
+ pool = objc_autoreleasePoolPush();
+
+ pos += parseObject(buffer + pos, length - pos, &child,
+ depthLimit);
+
+ [*object addObject: child];
+
+ objc_autoreleasePoolPop(pool);
+ }
+
+ return pos;
+}
+
+static size_t
+parseTable(const unsigned char *buffer, size_t length, id *object, size_t count,
+ size_t depthLimit)
+{
+ void *pool;
+ size_t pos = 0;
+
+ if (--depthLimit == 0)
+ @throw [OFOutOfRangeException exception];
+
+ /*
+ * Don't use capacity! For data and strings, this is safe, as we can
+ * check if we still have enough bytes left. For a dictionary however,
+ * we can't know this, as every key / value can be more than one byte.
+ */
+ *object = [OFMutableDictionary dictionary];
+
+ for (size_t i = 0; i < count; i++) {
+ id key, value;
+
+ pool = objc_autoreleasePoolPush();
+
+ pos += parseObject(buffer + pos, length - pos, &key,
+ depthLimit);
+ pos += parseObject(buffer + pos, length - pos, &value,
+ depthLimit);
+
+ [*object setObject: value
+ forKey: key];
+
+ objc_autoreleasePoolPop(pool);
+ }
+
+ return pos;
+}
+
+static OFDate *
+createDate(OFData *data)
+{
+ switch (data.count) {
+ case 4: {
+ uint32_t timestamp;
+
+ memcpy(×tamp, data.items, 4);
+ timestamp = OF_BSWAP32_IF_LE(timestamp);
+
+ return [OFDate dateWithTimeIntervalSince1970: timestamp];
+ }
+ case 8: {
+ uint64_t combined;
+
+ memcpy(&combined, data.items, 8);
+ combined = OF_BSWAP64_IF_LE(combined);
+
+ return [OFDate dateWithTimeIntervalSince1970:
+ (double)(combined & 0x3FFFFFFFF) +
+ (double)(combined >> 34) / 1000000000];
+ }
+ case 12: {
+ uint32_t nanoseconds;
+ int64_t seconds;
+
+ memcpy(&nanoseconds, data.items, 4);
+ memcpy(&seconds, (char *)data.items + 4, 8);
+
+ nanoseconds = OF_BSWAP32_IF_LE(nanoseconds);
+ seconds = OF_BSWAP64_IF_LE(seconds);
+
+ return [OFDate dateWithTimeIntervalSince1970:
+ (double)seconds + (double)nanoseconds / 1000000000];
+ }
+ default:
+ @throw [OFInvalidFormatException exception];
+ }
+}
+
+static id
+createExtension(int8_t type, OFData *data)
+{
+ switch (type) {
+ case -1:
+ return createDate(data);
+ default:
+ return [OFMessagePackExtension extensionWithType: type
+ data: data];
+ }
+}
+
+static size_t
+parseObject(const unsigned char *buffer, size_t length, id *object,
+ size_t depthLimit)
+{
+ size_t count;
+ OFData *data;
+
+ if (length < 1)
+ @throw [OFTruncatedDataException exception];
+
+ /* positive fixint */
+ if ((buffer[0] & 0x80) == 0) {
+ *object = [OFNumber numberWithUnsignedChar: buffer[0] & 0x7F];
+ return 1;
+ }
+ /* negative fixint */
+ if ((buffer[0] & 0xE0) == 0xE0) {
+ *object = [OFNumber numberWithChar:
+ ((int8_t)(buffer[0] & 0x1F)) - 32];
+ return 1;
+ }
+
+ /* fixstr */
+ if ((buffer[0] & 0xE0) == 0xA0) {
+ count = buffer[0] & 0x1F;
+
+ if (length < count + 1)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFString
+ stringWithUTF8String: (const char *)buffer + 1
+ length: count];
+ return count + 1;
+ }
+
+ /* fixarray */
+ if ((buffer[0] & 0xF0) == 0x90)
+ return parseArray(buffer + 1, length - 1, object,
+ buffer[0] & 0xF, depthLimit) + 1;
+
+ /* fixmap */
+ if ((buffer[0] & 0xF0) == 0x80)
+ return parseTable(buffer + 1, length - 1, object,
+ buffer[0] & 0xF, depthLimit) + 1;
+
+ /* Prefix byte */
+ switch (buffer[0]) {
+ /* Unsigned integers */
+ case 0xCC: /* uint8 */
+ if (length < 2)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFNumber numberWithUnsignedChar: buffer[1]];
+ return 2;
+ case 0xCD: /* uint 16 */
+ if (length < 3)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFNumber numberWithUnsignedShort:
+ readUInt16(buffer + 1)];
+ return 3;
+ case 0xCE: /* uint 32 */
+ if (length < 5)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFNumber numberWithUnsignedLong:
+ readUInt32(buffer + 1)];
+ return 5;
+ case 0xCF: /* uint 64 */
+ if (length < 9)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFNumber numberWithUnsignedLongLong:
+ readUInt64(buffer + 1)];
+ return 9;
+ /* Signed integers */
+ case 0xD0: /* int 8 */
+ if (length < 2)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFNumber numberWithChar: buffer[1]];
+ return 2;
+ case 0xD1: /* int 16 */
+ if (length < 3)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFNumber numberWithShort: readUInt16(buffer + 1)];
+ return 3;
+ case 0xD2: /* int 32 */
+ if (length < 5)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFNumber numberWithLong: readUInt32(buffer + 1)];
+ return 5;
+ case 0xD3: /* int 64 */
+ if (length < 9)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFNumber numberWithLongLong: readUInt64(buffer + 1)];
+ return 9;
+ /* Floating point */
+ case 0xCA:; /* float 32 */
+ float f;
+
+ if (length < 5)
+ @throw [OFTruncatedDataException exception];
+
+ memcpy(&f, buffer + 1, 4);
+
+ *object = [OFNumber numberWithFloat: OF_BSWAP_FLOAT_IF_LE(f)];
+ return 5;
+ case 0xCB:; /* float 64 */
+ double d;
+
+ if (length < 9)
+ @throw [OFTruncatedDataException exception];
+
+ memcpy(&d, buffer + 1, 8);
+
+ *object = [OFNumber numberWithDouble: OF_BSWAP_DOUBLE_IF_LE(d)];
+ return 9;
+ /* nil */
+ case 0xC0:
+ *object = [OFNull null];
+ return 1;
+ /* false */
+ case 0xC2:
+ *object = [OFNumber numberWithBool: false];
+ return 1;
+ /* true */
+ case 0xC3:
+ *object = [OFNumber numberWithBool: true];
+ return 1;
+ /* Data */
+ case 0xC4: /* bin 8 */
+ if (length < 2)
+ @throw [OFTruncatedDataException exception];
+
+ count = buffer[1];
+
+ if (length < count + 2)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFData dataWithItems: buffer + 2
+ count: count];
+
+ return count + 2;
+ case 0xC5: /* bin 16 */
+ if (length < 3)
+ @throw [OFTruncatedDataException exception];
+
+ count = readUInt16(buffer + 1);
+
+ if (length < count + 3)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFData dataWithItems: buffer + 3
+ count: count];
+
+ return count + 3;
+ case 0xC6: /* bin 32 */
+ if (length < 5)
+ @throw [OFTruncatedDataException exception];
+
+ count = readUInt32(buffer + 1);
+
+ if (length < count + 5)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFData dataWithItems: buffer + 5
+ count: count];
+
+ return count + 5;
+ /* Extensions */
+ case 0xC7: /* ext 8 */
+ if (length < 3)
+ @throw [OFTruncatedDataException exception];
+
+ count = buffer[1];
+
+ if (length < count + 3)
+ @throw [OFTruncatedDataException exception];
+
+ data = [[OFData alloc] initWithItems: buffer + 3
+ count: count];
+ @try {
+ *object = createExtension(buffer[2], data);
+ } @finally {
+ [data release];
+ }
+
+ return count + 3;
+ case 0xC8: /* ext 16 */
+ if (length < 4)
+ @throw [OFTruncatedDataException exception];
+
+ count = readUInt16(buffer + 1);
+
+ if (length < count + 4)
+ @throw [OFTruncatedDataException exception];
+
+ data = [[OFData alloc] initWithItems: buffer + 4
+ count: count];
+ @try {
+ *object = createExtension(buffer[3], data);
+ } @finally {
+ [data release];
+ }
+
+ return count + 4;
+ case 0xC9: /* ext 32 */
+ if (length < 6)
+ @throw [OFTruncatedDataException exception];
+
+ count = readUInt32(buffer + 1);
+
+ if (length < count + 6)
+ @throw [OFTruncatedDataException exception];
+
+ data = [[OFData alloc] initWithItems: buffer + 6
+ count: count];
+ @try {
+ *object = createExtension(buffer[5], data);
+ } @finally {
+ [data release];
+ }
+
+ return count + 6;
+ case 0xD4: /* fixext 1 */
+ if (length < 3)
+ @throw [OFTruncatedDataException exception];
+
+ data = [[OFData alloc] initWithItems: buffer + 2
+ count: 1];
+ @try {
+ *object = createExtension(buffer[1], data);
+ } @finally {
+ [data release];
+ }
+
+ return 3;
+ case 0xD5: /* fixext 2 */
+ if (length < 4)
+ @throw [OFTruncatedDataException exception];
+
+ data = [[OFData alloc] initWithItems: buffer + 2
+ count: 2];
+ @try {
+ *object = createExtension(buffer[1], data);
+ } @finally {
+ [data release];
+ }
+
+ return 4;
+ case 0xD6: /* fixext 4 */
+ if (length < 6)
+ @throw [OFTruncatedDataException exception];
+
+ data = [[OFData alloc] initWithItems: buffer + 2
+ count: 4];
+ @try {
+ *object = createExtension(buffer[1], data);
+ } @finally {
+ [data release];
+ }
+
+ return 6;
+ case 0xD7: /* fixext 8 */
+ if (length < 10)
+ @throw [OFTruncatedDataException exception];
+
+ data = [[OFData alloc] initWithItems: buffer + 2
+ count: 8];
+ @try {
+ *object = createExtension(buffer[1], data);
+ } @finally {
+ [data release];
+ }
+
+ return 10;
+ case 0xD8: /* fixext 16 */
+ if (length < 18)
+ @throw [OFTruncatedDataException exception];
+
+ data = [[OFData alloc] initWithItems: buffer + 2
+ count: 16];
+ @try {
+ *object = createExtension(buffer[1], data);
+ } @finally {
+ [data release];
+ }
+
+ return 18;
+ /* Strings */
+ case 0xD9: /* str 8 */
+ if (length < 2)
+ @throw [OFTruncatedDataException exception];
+
+ count = buffer[1];
+
+ if (length < count + 2)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFString
+ stringWithUTF8String: (const char *)buffer + 2
+ length: count];
+ return count + 2;
+ case 0xDA: /* str 16 */
+ if (length < 3)
+ @throw [OFTruncatedDataException exception];
+
+ count = readUInt16(buffer + 1);
+
+ if (length < count + 3)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFString
+ stringWithUTF8String: (const char *)buffer + 3
+ length: count];
+ return count + 3;
+ case 0xDB: /* str 32 */
+ if (length < 5)
+ @throw [OFTruncatedDataException exception];
+
+ count = readUInt32(buffer + 1);
+
+ if (length < count + 5)
+ @throw [OFTruncatedDataException exception];
+
+ *object = [OFString
+ stringWithUTF8String: (const char *)buffer + 5
+ length: count];
+ return count + 5;
+ /* Arrays */
+ case 0xDC: /* array 16 */
+ if (length < 3)
+ @throw [OFTruncatedDataException exception];
+
+ return parseArray(buffer + 3, length - 3, object,
+ readUInt16(buffer + 1), depthLimit) + 3;
+ case 0xDD: /* array 32 */
+ if (length < 5)
+ @throw [OFTruncatedDataException exception];
+
+ return parseArray(buffer + 5, length - 5, object,
+ readUInt32(buffer + 1), depthLimit) + 5;
+ /* Maps */
+ case 0xDE: /* map 16 */
+ if (length < 3)
+ @throw [OFTruncatedDataException exception];
+
+ return parseTable(buffer + 3, length - 3, object,
+ readUInt16(buffer + 1), depthLimit) + 3;
+ case 0xDF: /* map 32 */
+ if (length < 5)
+ @throw [OFTruncatedDataException exception];
+
+ return parseTable(buffer + 5, length - 5, object,
+ readUInt32(buffer + 1), depthLimit) + 5;
+ default:
+ @throw [OFInvalidFormatException exception];
+ }
+}
+
+@implementation OFData (MessagePackParsing)
+- (id)objectByParsingMessagePack
+{
+ return [self objectByParsingMessagePackWithDepthLimit: 32];
+}
+
+- (id)objectByParsingMessagePackWithDepthLimit: (size_t)depthLimit
+{
+ void *pool = objc_autoreleasePoolPush();
+ size_t count = self.count;
+ id object;
+
+ if (self.itemSize != 1)
+ @throw [OFInvalidArgumentException exception];
+
+ if (parseObject(self.items, count, &object, depthLimit) != count)
+ @throw [OFInvalidFormatException exception];
+
+ [object retain];
+
+ objc_autoreleasePoolPop(pool);
+
+ return [object autorelease];
+}
+@end
DELETED src/OFData+MessagePackValue.h
Index: src/OFData+MessagePackValue.h
==================================================================
--- src/OFData+MessagePackValue.h
+++ src/OFData+MessagePackValue.h
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
- * 2018, 2019, 2020
- * Jonathan Schleifer
- *
- * All rights reserved.
- *
- * This file is part of ObjFW. It may be distributed under the terms of the
- * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
- * the packaging of this file.
- *
- * Alternatively, it may be distributed under the terms of the GNU General
- * Public License, either version 2 or 3, which can be found in the file
- * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
- * file.
- */
-
-#import "OFData.h"
-
-OF_ASSUME_NONNULL_BEGIN
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern int _OFData_MessagePackValue_reference;
-#ifdef __cplusplus
-}
-#endif
-
-@interface OFData (MessagePackValue)
-/*!
- * @brief The data interpreted as MessagePack representation and parsed as an
- * object.
- */
-@property (readonly, nonatomic) id messagePackValue;
-
-/*!
- * @brief Parses the MessagePack representation and returns it as an object.
- *
- * @param depthLimit The maximum depth the parser should accept (defaults to 32
- * if not specified, 0 means no limit (insecure!))
- * @return The MessagePack representation as an object
- */
-- (id)messagePackValueWithDepthLimit: (size_t)depthLimit;
-@end
-
-OF_ASSUME_NONNULL_END
DELETED src/OFData+MessagePackValue.m
Index: src/OFData+MessagePackValue.m
==================================================================
--- src/OFData+MessagePackValue.m
+++ src/OFData+MessagePackValue.m
@@ -1,569 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
- * 2018, 2019, 2020
- * Jonathan Schleifer
- *
- * All rights reserved.
- *
- * This file is part of ObjFW. It may be distributed under the terms of the
- * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
- * the packaging of this file.
- *
- * Alternatively, it may be distributed under the terms of the GNU General
- * Public License, either version 2 or 3, which can be found in the file
- * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
- * file.
- */
-
-#include "config.h"
-
-#include
-
-#import "OFData+MessagePackValue.h"
-#import "OFArray.h"
-#import "OFDate.h"
-#import "OFDictionary.h"
-#import "OFMessagePackExtension.h"
-#import "OFNull.h"
-#import "OFNumber.h"
-#import "OFString.h"
-
-#import "OFInvalidArgumentException.h"
-#import "OFInvalidFormatException.h"
-#import "OFOutOfRangeException.h"
-#import "OFTruncatedDataException.h"
-
-int _OFData_MessagePackValue_reference;
-
-static size_t parseObject(const unsigned char *buffer, size_t length,
- id *object, size_t depthLimit);
-
-static uint16_t
-readUInt16(const unsigned char *buffer)
-{
- return ((uint16_t)buffer[0] << 8) | buffer[1];
-}
-
-static uint32_t
-readUInt32(const unsigned char *buffer)
-{
- return ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) |
- ((uint32_t)buffer[2] << 8) | buffer[3];
-}
-
-static uint64_t
-readUInt64(const unsigned char *buffer)
-{
- return ((uint64_t)buffer[0] << 56) | ((uint64_t)buffer[1] << 48) |
- ((uint64_t)buffer[2] << 40) | ((uint64_t)buffer[3] << 32) |
- ((uint64_t)buffer[4] << 24) | ((uint64_t)buffer[5] << 16) |
- ((uint64_t)buffer[6] << 8) | buffer[7];
-}
-
-static size_t
-parseArray(const unsigned char *buffer, size_t length, id *object, size_t count,
- size_t depthLimit)
-{
- void *pool;
- size_t pos = 0;
-
- if (--depthLimit == 0)
- @throw [OFOutOfRangeException exception];
-
- /*
- * Don't use capacity! For data and strings, this is safe, as we can
- * check if we still have enough bytes left. For an array however, we
- * can't know this, as every child can be more than one byte.
- */
- *object = [OFMutableArray array];
-
- for (size_t i = 0; i < count; i++) {
- id child;
-
- pool = objc_autoreleasePoolPush();
-
- pos += parseObject(buffer + pos, length - pos, &child,
- depthLimit);
-
- [*object addObject: child];
-
- objc_autoreleasePoolPop(pool);
- }
-
- return pos;
-}
-
-static size_t
-parseTable(const unsigned char *buffer, size_t length, id *object, size_t count,
- size_t depthLimit)
-{
- void *pool;
- size_t pos = 0;
-
- if (--depthLimit == 0)
- @throw [OFOutOfRangeException exception];
-
- /*
- * Don't use capacity! For data and strings, this is safe, as we can
- * check if we still have enough bytes left. For a dictionary however,
- * we can't know this, as every key / value can be more than one byte.
- */
- *object = [OFMutableDictionary dictionary];
-
- for (size_t i = 0; i < count; i++) {
- id key, value;
-
- pool = objc_autoreleasePoolPush();
-
- pos += parseObject(buffer + pos, length - pos, &key,
- depthLimit);
- pos += parseObject(buffer + pos, length - pos, &value,
- depthLimit);
-
- [*object setObject: value
- forKey: key];
-
- objc_autoreleasePoolPop(pool);
- }
-
- return pos;
-}
-
-static OFDate *
-createDate(OFData *data)
-{
- switch (data.count) {
- case 4: {
- uint32_t timestamp;
-
- memcpy(×tamp, data.items, 4);
- timestamp = OF_BSWAP32_IF_LE(timestamp);
-
- return [OFDate dateWithTimeIntervalSince1970: timestamp];
- }
- case 8: {
- uint64_t combined;
-
- memcpy(&combined, data.items, 8);
- combined = OF_BSWAP64_IF_LE(combined);
-
- return [OFDate dateWithTimeIntervalSince1970:
- (double)(combined & 0x3FFFFFFFF) +
- (double)(combined >> 34) / 1000000000];
- }
- case 12: {
- uint32_t nanoseconds;
- int64_t seconds;
-
- memcpy(&nanoseconds, data.items, 4);
- memcpy(&seconds, (char *)data.items + 4, 8);
-
- nanoseconds = OF_BSWAP32_IF_LE(nanoseconds);
- seconds = OF_BSWAP64_IF_LE(seconds);
-
- return [OFDate dateWithTimeIntervalSince1970:
- (double)seconds + (double)nanoseconds / 1000000000];
- }
- default:
- @throw [OFInvalidFormatException exception];
- }
-}
-
-static id
-createExtension(int8_t type, OFData *data)
-{
- switch (type) {
- case -1:
- return createDate(data);
- default:
- return [OFMessagePackExtension extensionWithType: type
- data: data];
- }
-}
-
-static size_t
-parseObject(const unsigned char *buffer, size_t length, id *object,
- size_t depthLimit)
-{
- size_t count;
- OFData *data;
-
- if (length < 1)
- @throw [OFTruncatedDataException exception];
-
- /* positive fixint */
- if ((buffer[0] & 0x80) == 0) {
- *object = [OFNumber numberWithUInt8: buffer[0] & 0x7F];
- return 1;
- }
- /* negative fixint */
- if ((buffer[0] & 0xE0) == 0xE0) {
- *object = [OFNumber numberWithInt8:
- ((int8_t)(buffer[0] & 0x1F)) - 32];
- return 1;
- }
-
- /* fixstr */
- if ((buffer[0] & 0xE0) == 0xA0) {
- count = buffer[0] & 0x1F;
-
- if (length < count + 1)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFString
- stringWithUTF8String: (const char *)buffer + 1
- length: count];
- return count + 1;
- }
-
- /* fixarray */
- if ((buffer[0] & 0xF0) == 0x90)
- return parseArray(buffer + 1, length - 1, object,
- buffer[0] & 0xF, depthLimit) + 1;
-
- /* fixmap */
- if ((buffer[0] & 0xF0) == 0x80)
- return parseTable(buffer + 1, length - 1, object,
- buffer[0] & 0xF, depthLimit) + 1;
-
- /* Prefix byte */
- switch (buffer[0]) {
- /* Unsigned integers */
- case 0xCC: /* uint8 */
- if (length < 2)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFNumber numberWithUInt8: buffer[1]];
- return 2;
- case 0xCD: /* uint 16 */
- if (length < 3)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFNumber numberWithUInt16: readUInt16(buffer + 1)];
- return 3;
- case 0xCE: /* uint 32 */
- if (length < 5)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFNumber numberWithUInt32: readUInt32(buffer + 1)];
- return 5;
- case 0xCF: /* uint 64 */
- if (length < 9)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFNumber numberWithUInt64: readUInt64(buffer + 1)];
- return 9;
- /* Signed integers */
- case 0xD0: /* int 8 */
- if (length < 2)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFNumber numberWithInt8: buffer[1]];
- return 2;
- case 0xD1: /* int 16 */
- if (length < 3)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFNumber numberWithInt16: readUInt16(buffer + 1)];
- return 3;
- case 0xD2: /* int 32 */
- if (length < 5)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFNumber numberWithInt32: readUInt32(buffer + 1)];
- return 5;
- case 0xD3: /* int 64 */
- if (length < 9)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFNumber numberWithInt64: readUInt64(buffer + 1)];
- return 9;
- /* Floating point */
- case 0xCA:; /* float 32 */
- float f;
-
- if (length < 5)
- @throw [OFTruncatedDataException exception];
-
- memcpy(&f, buffer + 1, 4);
-
- *object = [OFNumber numberWithFloat: OF_BSWAP_FLOAT_IF_LE(f)];
- return 5;
- case 0xCB:; /* float 64 */
- double d;
-
- if (length < 9)
- @throw [OFTruncatedDataException exception];
-
- memcpy(&d, buffer + 1, 8);
-
- *object = [OFNumber numberWithDouble: OF_BSWAP_DOUBLE_IF_LE(d)];
- return 9;
- /* nil */
- case 0xC0:
- *object = [OFNull null];
- return 1;
- /* false */
- case 0xC2:
- *object = [OFNumber numberWithBool: false];
- return 1;
- /* true */
- case 0xC3:
- *object = [OFNumber numberWithBool: true];
- return 1;
- /* Data */
- case 0xC4: /* bin 8 */
- if (length < 2)
- @throw [OFTruncatedDataException exception];
-
- count = buffer[1];
-
- if (length < count + 2)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFData dataWithItems: buffer + 2
- count: count];
-
- return count + 2;
- case 0xC5: /* bin 16 */
- if (length < 3)
- @throw [OFTruncatedDataException exception];
-
- count = readUInt16(buffer + 1);
-
- if (length < count + 3)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFData dataWithItems: buffer + 3
- count: count];
-
- return count + 3;
- case 0xC6: /* bin 32 */
- if (length < 5)
- @throw [OFTruncatedDataException exception];
-
- count = readUInt32(buffer + 1);
-
- if (length < count + 5)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFData dataWithItems: buffer + 5
- count: count];
-
- return count + 5;
- /* Extensions */
- case 0xC7: /* ext 8 */
- if (length < 3)
- @throw [OFTruncatedDataException exception];
-
- count = buffer[1];
-
- if (length < count + 3)
- @throw [OFTruncatedDataException exception];
-
- data = [[OFData alloc] initWithItems: buffer + 3
- count: count];
- @try {
- *object = createExtension(buffer[2], data);
- } @finally {
- [data release];
- }
-
- return count + 3;
- case 0xC8: /* ext 16 */
- if (length < 4)
- @throw [OFTruncatedDataException exception];
-
- count = readUInt16(buffer + 1);
-
- if (length < count + 4)
- @throw [OFTruncatedDataException exception];
-
- data = [[OFData alloc] initWithItems: buffer + 4
- count: count];
- @try {
- *object = createExtension(buffer[3], data);
- } @finally {
- [data release];
- }
-
- return count + 4;
- case 0xC9: /* ext 32 */
- if (length < 6)
- @throw [OFTruncatedDataException exception];
-
- count = readUInt32(buffer + 1);
-
- if (length < count + 6)
- @throw [OFTruncatedDataException exception];
-
- data = [[OFData alloc] initWithItems: buffer + 6
- count: count];
- @try {
- *object = createExtension(buffer[5], data);
- } @finally {
- [data release];
- }
-
- return count + 6;
- case 0xD4: /* fixext 1 */
- if (length < 3)
- @throw [OFTruncatedDataException exception];
-
- data = [[OFData alloc] initWithItems: buffer + 2
- count: 1];
- @try {
- *object = createExtension(buffer[1], data);
- } @finally {
- [data release];
- }
-
- return 3;
- case 0xD5: /* fixext 2 */
- if (length < 4)
- @throw [OFTruncatedDataException exception];
-
- data = [[OFData alloc] initWithItems: buffer + 2
- count: 2];
- @try {
- *object = createExtension(buffer[1], data);
- } @finally {
- [data release];
- }
-
- return 4;
- case 0xD6: /* fixext 4 */
- if (length < 6)
- @throw [OFTruncatedDataException exception];
-
- data = [[OFData alloc] initWithItems: buffer + 2
- count: 4];
- @try {
- *object = createExtension(buffer[1], data);
- } @finally {
- [data release];
- }
-
- return 6;
- case 0xD7: /* fixext 8 */
- if (length < 10)
- @throw [OFTruncatedDataException exception];
-
- data = [[OFData alloc] initWithItems: buffer + 2
- count: 8];
- @try {
- *object = createExtension(buffer[1], data);
- } @finally {
- [data release];
- }
-
- return 10;
- case 0xD8: /* fixext 16 */
- if (length < 18)
- @throw [OFTruncatedDataException exception];
-
- data = [[OFData alloc] initWithItems: buffer + 2
- count: 16];
- @try {
- *object = createExtension(buffer[1], data);
- } @finally {
- [data release];
- }
-
- return 18;
- /* Strings */
- case 0xD9: /* str 8 */
- if (length < 2)
- @throw [OFTruncatedDataException exception];
-
- count = buffer[1];
-
- if (length < count + 2)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFString
- stringWithUTF8String: (const char *)buffer + 2
- length: count];
- return count + 2;
- case 0xDA: /* str 16 */
- if (length < 3)
- @throw [OFTruncatedDataException exception];
-
- count = readUInt16(buffer + 1);
-
- if (length < count + 3)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFString
- stringWithUTF8String: (const char *)buffer + 3
- length: count];
- return count + 3;
- case 0xDB: /* str 32 */
- if (length < 5)
- @throw [OFTruncatedDataException exception];
-
- count = readUInt32(buffer + 1);
-
- if (length < count + 5)
- @throw [OFTruncatedDataException exception];
-
- *object = [OFString
- stringWithUTF8String: (const char *)buffer + 5
- length: count];
- return count + 5;
- /* Arrays */
- case 0xDC: /* array 16 */
- if (length < 3)
- @throw [OFTruncatedDataException exception];
-
- return parseArray(buffer + 3, length - 3, object,
- readUInt16(buffer + 1), depthLimit) + 3;
- case 0xDD: /* array 32 */
- if (length < 5)
- @throw [OFTruncatedDataException exception];
-
- return parseArray(buffer + 5, length - 5, object,
- readUInt32(buffer + 1), depthLimit) + 5;
- /* Maps */
- case 0xDE: /* map 16 */
- if (length < 3)
- @throw [OFTruncatedDataException exception];
-
- return parseTable(buffer + 3, length - 3, object,
- readUInt16(buffer + 1), depthLimit) + 3;
- case 0xDF: /* map 32 */
- if (length < 5)
- @throw [OFTruncatedDataException exception];
-
- return parseTable(buffer + 5, length - 5, object,
- readUInt32(buffer + 1), depthLimit) + 5;
- default:
- @throw [OFInvalidFormatException exception];
- }
-}
-
-@implementation OFData (MessagePackValue)
-- (id)messagePackValue
-{
- return [self messagePackValueWithDepthLimit: 32];
-}
-
-- (id)messagePackValueWithDepthLimit: (size_t)depthLimit
-{
- void *pool = objc_autoreleasePoolPush();
- size_t count = self.count;
- id object;
-
- if (self.itemSize != 1)
- @throw [OFInvalidArgumentException exception];
-
- if (parseObject(self.items, count, &object, depthLimit) != count)
- @throw [OFInvalidFormatException exception];
-
- [object retain];
-
- objc_autoreleasePoolPop(pool);
-
- return [object autorelease];
-}
-@end
Index: src/OFData.h
==================================================================
--- src/OFData.h
+++ src/OFData.h
@@ -325,8 +325,8 @@
@end
OF_ASSUME_NONNULL_END
#import "OFMutableData.h"
-#import "OFData+ASN1DERValue.h"
+#import "OFData+ASN1DERParsing.h"
#import "OFData+CryptoHashing.h"
-#import "OFData+MessagePackValue.h"
+#import "OFData+MessagePackParsing.h"
Index: src/OFData.m
==================================================================
--- src/OFData.m
+++ src/OFData.m
@@ -46,13 +46,13 @@
/* References for static linking */
void
_references_to_categories_of_OFData(void)
{
- _OFData_ASN1DERValue_reference = 1;
+ _OFData_ASN1DERParsing_reference = 1;
_OFData_CryptoHashing_reference = 1;
- _OFData_MessagePackValue_reference = 1;
+ _OFData_MessagePackParsing_reference = 1;
}
@implementation OFData
@synthesize itemSize = _itemSize;
@@ -182,19 +182,19 @@
#ifdef OF_HAVE_FILES
- (instancetype)initWithContentsOfFile: (OFString *)path
{
char *buffer = NULL;
- uintmax_t size;
+ unsigned long long size;
@try {
OFFile *file;
size = [[OFFileManager defaultManager]
attributesOfItemAtPath: path].fileSize;
-# if UINTMAX_MAX > SIZE_MAX
+# if ULLONG_MAX > SIZE_MAX
if (size > SIZE_MAX)
@throw [OFOutOfRangeException exception];
# endif
if ((buffer = malloc((size_t)size)) == NULL)
Index: src/OFDate.m
==================================================================
--- src/OFDate.m
+++ src/OFDate.m
@@ -485,21 +485,33 @@
return [self initWithTimeIntervalSince1970: seconds];
}
- (instancetype)initWithSerialization: (OFXMLElement *)element
{
- void *pool = objc_autoreleasePoolPush();
of_time_interval_t seconds;
- if (![element.name isEqual: @"OFDate"] ||
- ![element.namespace isEqual: OF_SERIALIZATION_NS])
- @throw [OFInvalidArgumentException exception];
-
- seconds = OF_BSWAP_DOUBLE_IF_LE(OF_INT_TO_DOUBLE_RAW(OF_BSWAP64_IF_LE(
- element.hexadecimalValue)));
-
- objc_autoreleasePoolPop(pool);
+ @try {
+ void *pool = objc_autoreleasePoolPush();
+ unsigned long long value;
+
+ if (![element.name isEqual: @"OFDate"] ||
+ ![element.namespace isEqual: OF_SERIALIZATION_NS])
+ @throw [OFInvalidArgumentException exception];
+
+ value = [element unsignedLongLongValueWithBase: 16];
+
+ if (value > UINT64_MAX)
+ @throw [OFOutOfRangeException exception];
+
+ seconds = OF_BSWAP_DOUBLE_IF_LE(OF_INT_TO_DOUBLE_RAW(
+ OF_BSWAP64_IF_LE(value)));
+
+ objc_autoreleasePoolPop(pool);
+ } @catch (id e) {
+ [self release];
+ @throw e;
+ }
return [self initWithTimeIntervalSince1970: seconds];
}
- (bool)isEqual: (id)object
Index: src/OFFileManager.h
==================================================================
--- src/OFFileManager.h
+++ src/OFFileManager.h
@@ -576,11 +576,11 @@
/*!
* @brief The @ref of_file_attribute_key_size key from the dictionary.
*
* Raises an @ref OFUndefinedKeyException if the key is missing.
*/
-@property (readonly, nonatomic) uintmax_t fileSize;
+@property (readonly, nonatomic) unsigned long long fileSize;
/*!
* @brief The @ref of_file_attribute_key_type key from the dictionary.
*
* Raises an @ref OFUndefinedKeyException if the key is missing.
@@ -591,25 +591,25 @@
* @brief The @ref of_file_attribute_key_posix_permissions key from the
* dictionary.
*
* Raises an @ref OFUndefinedKeyException if the key is missing.
*/
-@property (readonly, nonatomic) uint16_t filePOSIXPermissions;
+@property (readonly, nonatomic) unsigned long filePOSIXPermissions;
/*!
* @brief The @ref of_file_attribute_key_posix_uid key from the dictionary.
*
* Raises an @ref OFUndefinedKeyException if the key is missing.
*/
-@property (readonly, nonatomic) uint32_t filePOSIXUID;
+@property (readonly, nonatomic) unsigned long filePOSIXUID;
/*!
* @brief The @ref of_file_attribute_key_posix_gid key from the dictionary.
*
* Raises an @ref OFUndefinedKeyException if the key is missing.
*/
-@property (readonly, nonatomic) uint32_t filePOSIXGID;
+@property (readonly, nonatomic) unsigned long filePOSIXGID;
/*!
* @brief The @ref of_file_attribute_key_owner key from the dictionary.
*
* Raises an @ref OFUndefinedKeyException if the key is missing.
Index: src/OFFileManager.m
==================================================================
--- src/OFFileManager.m
+++ src/OFFileManager.m
@@ -936,37 +936,37 @@
return OF_RETAIN_COUNT_MAX;
}
@end
@implementation OFDictionary (FileAttributes)
-- (uintmax_t)fileSize
+- (unsigned long long)fileSize
{
return [attributeForKeyOrException(self, of_file_attribute_key_size)
- uIntMaxValue];
+ unsignedLongLongValue];
}
- (of_file_type_t)fileType
{
return attributeForKeyOrException(self, of_file_attribute_key_type);
}
-- (uint16_t)filePOSIXPermissions
-{
- return [attributeForKeyOrException(self,
- of_file_attribute_key_posix_permissions) uInt16Value];
-}
-
-- (uint32_t)filePOSIXUID
-{
- return [attributeForKeyOrException(self,
- of_file_attribute_key_posix_uid) uInt32Value];
-}
-
-- (uint32_t)filePOSIXGID
-{
- return [attributeForKeyOrException(self,
- of_file_attribute_key_posix_gid) uInt32Value];
+- (unsigned long)filePOSIXPermissions
+{
+ return [attributeForKeyOrException(self,
+ of_file_attribute_key_posix_permissions) unsignedLongValue];
+}
+
+- (unsigned long)filePOSIXUID
+{
+ return [attributeForKeyOrException(self,
+ of_file_attribute_key_posix_uid) unsignedLongValue];
+}
+
+- (unsigned long)filePOSIXGID
+{
+ return [attributeForKeyOrException(self,
+ of_file_attribute_key_posix_gid) unsignedLongValue];
}
- (OFString *)fileOwner
{
return attributeForKeyOrException(self, of_file_attribute_key_owner);
Index: src/OFFileURLHandler.m
==================================================================
--- src/OFFileURLHandler.m
+++ src/OFFileURLHandler.m
@@ -409,13 +409,13 @@
static void
setOwnerAndGroupAttributes(of_mutable_file_attributes_t attributes,
of_stat_t *s)
{
#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER
- [attributes setObject: [NSNumber numberWithUInt16: s->st_uid]
+ [attributes setObject: [NSNumber numberWithUnsignedLong: s->st_uid]
forKey: of_file_attribute_key_posix_uid];
- [attributes setObject: [NSNumber numberWithUInt16: s->st_gid]
+ [attributes setObject: [NSNumber numberWithUnsignedLong: s->st_gid]
forKey: of_file_attribute_key_posix_gid];
# ifdef OF_HAVE_THREADS
[passwdMutex lock];
@try {
@@ -618,16 +618,16 @@
errNo: errno];
if (s.st_size < 0)
@throw [OFOutOfRangeException exception];
- [ret setObject: [NSNumber numberWithUIntMax: s.st_size]
+ [ret setObject: [NSNumber numberWithUnsignedLongLong: s.st_size]
forKey: of_file_attribute_key_size];
setTypeAttribute(ret, &s);
- [ret setObject: [NSNumber numberWithUInt16: s.st_mode & 07777]
+ [ret setObject: [NSNumber numberWithUnsignedLong: s.st_mode]
forKey: of_file_attribute_key_posix_permissions];
setOwnerAndGroupAttributes(ret, &s);
setDateAttributes(ret, &s);
@@ -758,11 +758,11 @@
- (void)of_setPOSIXPermissions: (OFNumber *)permissions
ofItemAtURL: (OFURL *)URL
attributes: (of_file_attributes_t)attributes OF_DIRECT
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
- uint16_t mode = permissions.uInt16Value & 0777;
+ mode_t mode = (mode_t)permissions.unsignedLongValue;
OFString *path = URL.fileSystemRepresentation;
int status;
# ifdef OF_WINDOWS
if ([OFSystemInfo isWindowsNT])
Index: src/OFHTTPClient.m
==================================================================
--- src/OFHTTPClient.m
+++ src/OFHTTPClient.m
@@ -77,11 +77,11 @@
@interface OFHTTPClientRequestBodyStream: OFStream
{
OFHTTPClientRequestHandler *_handler;
OFTCPSocket *_socket;
bool _chunked;
- uintmax_t _toWrite;
+ unsigned long long _toWrite;
bool _atEndOfStream;
}
- (instancetype)initWithHandler: (OFHTTPClientRequestHandler *)handler
socket: (OFTCPSocket *)sock;
@@ -91,11 +91,11 @@
@interface OFHTTPClientResponse: OFHTTPResponse
{
OFTCPSocket *_socket;
bool _hasContentLength, _chunked, _keepAlive;
bool _atEndOfStream, _setAtEndOfStream;
- intmax_t _toRead;
+ long long _toRead;
}
@property (nonatomic, setter=of_setKeepAlive:) bool of_keepAlive;
- (instancetype)initWithSocket: (OFTCPSocket *)sock;
@@ -443,10 +443,12 @@
}
}
- (bool)handleFirstLine: (OFString *)line
{
+ long long status;
+
/*
* It's possible that the write succeeds on a connection that is
* keep-alive, but the connection has already been closed by the remote
* end due to a timeout. In this case, we need to reconnect.
*/
@@ -462,11 +464,16 @@
_version = [[line substringWithRange: of_range(5, 3)] copy];
if (![_version isEqual: @"1.0"] && ![_version isEqual: @"1.1"])
@throw [OFUnsupportedVersionException
exceptionWithVersion: _version];
- _status = (int)[line substringWithRange: of_range(9, 3)].decimalValue;
+ status = [line substringWithRange: of_range(9, 3)].longLongValue;
+
+ if (status < 0 || status > 599)
+ @throw [OFInvalidServerReplyException exception];
+
+ _status = (int)status;
return true;
}
- (bool)handleServerHeader: (OFString *)line
@@ -711,11 +718,11 @@
port = 80;
}
URLPort = URL.port;
if (URLPort != nil)
- port = URLPort.uInt16Value;
+ port = URLPort.unsignedShortValue;
sock.delegate = self;
[sock asyncConnectToHost: URL.host
port: port];
} @catch (id e) {
@@ -730,11 +737,10 @@
{
self = [super init];
@try {
OFDictionary OF_GENERIC(OFString *, OFString *) *headers;
- intmax_t contentLength;
OFString *transferEncoding, *contentLengthString;
_handler = [handler retain];
_socket = [sock retain];
@@ -747,15 +753,11 @@
if (contentLengthString != nil) {
if (_chunked || contentLengthString.length == 0)
@throw [OFInvalidArgumentException
exception];
- contentLength = contentLengthString.decimalValue;
- if (contentLength < 0)
- @throw [OFOutOfRangeException exception];
-
- _toWrite = contentLength;
+ _toWrite = contentLengthString.unsignedLongLongValue;
} else if (!_chunked)
@throw [OFInvalidArgumentException exception];
} @catch (id e) {
[self release];
@throw e;
@@ -893,15 +895,17 @@
@throw [OFInvalidServerReplyException exception];
_hasContentLength = true;
@try {
- _toRead = contentLength.decimalValue;
+ unsigned long long toRead =
+ contentLength.unsignedLongLongValue;
- if (_toRead < 0)
- @throw [OFInvalidServerReplyException
- exception];
+ if (toRead > LLONG_MAX)
+ @throw [OFOutOfRangeException exception];
+
+ _toRead = (long long)toRead;
} @catch (OFInvalidFormatException *e) {
@throw [OFInvalidServerReplyException exception];
}
}
}
@@ -924,11 +928,11 @@
/* Content-Length */
if (!_chunked) {
size_t ret;
- if (length > (uintmax_t)_toRead)
+ if (length > (unsigned long long)_toRead)
length = (size_t)_toRead;
ret = [_socket readIntoBuffer: buffer
length: length];
@@ -979,11 +983,11 @@
if (_setAtEndOfStream && _toRead == 0)
_atEndOfStream = true;
return 0;
} else if (_toRead > 0) {
- if (length > (uintmax_t)_toRead)
+ if (length > (unsigned long long)_toRead)
length = (size_t)_toRead;
length = [_socket readIntoBuffer: buffer
length: length];
@@ -1024,12 +1028,17 @@
@throw [OFInvalidServerReplyException
exception];
}
@try {
- if ((_toRead = line.hexadecimalValue) < 0)
+ unsigned long long toRead =
+ [line unsignedLongLongValueWithBase: 16];
+
+ if (toRead > LLONG_MAX)
@throw [OFOutOfRangeException exception];
+
+ _toRead = (long long)toRead;
} @catch (OFInvalidFormatException *e) {
@throw [OFInvalidServerReplyException exception];
}
if (_toRead == 0) {
Index: src/OFHTTPCookie.m
==================================================================
--- src/OFHTTPCookie.m
+++ src/OFHTTPCookie.m
@@ -36,11 +36,11 @@
dateWithDateString: value
format: @"%a, %d %b %Y %H:%M:%S %z"];
cookie.expires = date;
} else if ([lowercaseName isEqual: @"max-age"]) {
OFDate *date = [OFDate dateWithTimeIntervalSinceNow:
- value.decimalValue];
+ value.unsignedLongLongValue];
cookie.expires = date;
} else if ([lowercaseName isEqual: @"domain"])
cookie.domain = value;
else if ([lowercaseName isEqual: @"path"])
cookie.path = value;
Index: src/OFHTTPRequest.m
==================================================================
--- src/OFHTTPRequest.m
+++ src/OFHTTPRequest.m
@@ -212,20 +212,20 @@
- (void)setProtocolVersionString: (OFString *)string
{
void *pool = objc_autoreleasePoolPush();
OFArray *components = [string componentsSeparatedByString: @"."];
- intmax_t major, minor;
+ unsigned long long major, minor;
of_http_request_protocol_version_t protocolVersion;
if (components.count != 2)
@throw [OFInvalidFormatException exception];
- major = [components.firstObject decimalValue];
- minor = [components.lastObject decimalValue];
+ major = [components.firstObject unsignedLongLongValue];
+ minor = [components.lastObject unsignedLongLongValue];
- if (major < 0 || major > UINT8_MAX || minor < 0 || minor > UINT8_MAX)
+ if (major > UINT8_MAX || minor > UINT8_MAX)
@throw [OFOutOfRangeException exception];
protocolVersion.major = (uint8_t)major;
protocolVersion.minor = (uint8_t)minor;
Index: src/OFHTTPResponse.m
==================================================================
--- src/OFHTTPResponse.m
+++ src/OFHTTPResponse.m
@@ -269,20 +269,20 @@
- (void)setProtocolVersionString: (OFString *)string
{
void *pool = objc_autoreleasePoolPush();
OFArray *components = [string componentsSeparatedByString: @"."];
- intmax_t major, minor;
+ unsigned long long major, minor;
of_http_request_protocol_version_t protocolVersion;
if (components.count != 2)
@throw [OFInvalidFormatException exception];
- major = [components.firstObject decimalValue];
- minor = [components.lastObject decimalValue];
+ major = [components.firstObject unsignedLongLongValue];
+ minor = [components.lastObject unsignedLongLongValue];
- if (major < 0 || major > UINT8_MAX || minor < 0 || minor > UINT8_MAX)
+ if (major > UINT8_MAX || minor > UINT8_MAX)
@throw [OFOutOfRangeException exception];
protocolVersion.major = (uint8_t)major;
protocolVersion.minor = (uint8_t)minor;
@@ -304,11 +304,11 @@
}
- (OFString *)stringWithEncoding: (of_string_encoding_t)encoding
{
void *pool = objc_autoreleasePoolPush();
- OFString *contentType, *contentLength, *ret;
+ OFString *contentType, *contentLengthString, *ret;
OFData *data;
if (encoding == OF_STRING_ENCODING_AUTODETECT &&
(contentType = [_headers objectForKey: @"Content-Type"]) != nil)
encoding = encodingForContentType(contentType);
@@ -316,13 +316,21 @@
if (encoding == OF_STRING_ENCODING_AUTODETECT)
encoding = OF_STRING_ENCODING_UTF_8;
data = [self readDataUntilEndOfStream];
- if ((contentLength = [_headers objectForKey: @"Content-Length"]) != nil)
- if (data.count != (size_t)contentLength.decimalValue)
+ contentLengthString = [_headers objectForKey: @"Content-Length"];
+ if (contentLengthString != nil) {
+ unsigned long long contentLength =
+ contentLengthString.unsignedLongLongValue;
+
+ if (contentLength > SIZE_MAX)
+ @throw [OFOutOfRangeException exception];
+
+ if (data.count != (size_t)contentLength)
@throw [OFTruncatedDataException exception];
+ }
ret = [[OFString alloc] initWithCString: (char *)data.items
encoding: encoding
length: data.count];
Index: src/OFHTTPServer.m
==================================================================
--- src/OFHTTPServer.m
+++ src/OFHTTPServer.m
@@ -103,17 +103,17 @@
OF_DIRECT_MEMBERS
@interface OFHTTPServerRequestBodyStream: OFStream
{
OFStreamSocket *_socket;
bool _chunked;
- intmax_t _toRead;
+ long long _toRead;
bool _atEndOfStream, _setAtEndOfStream;
}
- (instancetype)initWithSocket: (OFStreamSocket *)sock
chunked: (bool)chunked
- contentLength: (uintmax_t)contentLength;
+ contentLength: (unsigned long long)contentLength;
@end
#ifdef OF_HAVE_THREADS
OF_DIRECT_MEMBERS
@interface OFHTTPServerThread: OFThread
@@ -413,25 +413,22 @@
if (line.length == 0) {
bool chunked = [[_headers objectForKey: @"Transfer-Encoding"]
isEqual: @"chunked"];
OFString *contentLengthString =
[_headers objectForKey: @"Content-Length"];
- intmax_t contentLength = 0;
+ unsigned long long contentLength = 0;
if (contentLengthString != nil) {
if (chunked || contentLengthString.length == 0)
return [self sendErrorAndClose: 400];
@try {
contentLength =
- contentLengthString.decimalValue;
+ contentLengthString.unsignedLongLongValue;
} @catch (OFInvalidFormatException *e) {
return [self sendErrorAndClose: 400];
}
-
- if (contentLength < 0)
- return [self sendErrorAndClose: 400];
}
if (chunked || contentLengthString != nil) {
[_requestBody release];
_requestBody = nil;
@@ -480,12 +477,13 @@
of_range(0, pos)] retain];
@try {
of_range_t range =
of_range(pos + 1, value.length - pos - 1);
- intmax_t portTmp = [value
- substringWithRange: range].decimalValue;
+ unsigned long long portTmp =
+ [value substringWithRange: range]
+ .unsignedLongLongValue;
if (portTmp < 1 || portTmp > UINT16_MAX)
return [self sendErrorAndClose: 400];
_port = (uint16_t)portTmp;
@@ -543,11 +541,11 @@
URL = [OFMutableURL URL];
URL.scheme = @"http";
URL.host = _host;
if (_port != 80)
- URL.port = [OFNumber numberWithUInt16: _port];
+ URL.port = [OFNumber numberWithUnsignedShort: _port];
if ((pos = [_path rangeOfString: @"?"].location) != OF_NOT_FOUND) {
OFString *path, *query;
path = [_path substringWithRange: of_range(0, pos)];
@@ -583,18 +581,21 @@
@end
@implementation OFHTTPServerRequestBodyStream
- (instancetype)initWithSocket: (OFStreamSocket *)sock
chunked: (bool)chunked
- contentLength: (uintmax_t)contentLength
+ contentLength: (unsigned long long)contentLength
{
self = [super init];
@try {
+ if (contentLength > LLONG_MAX)
+ @throw [OFOutOfRangeException exception];
+
_socket = [sock retain];
_chunked = chunked;
- _toRead = contentLength;
+ _toRead = (long long)contentLength;
if (_chunked && _toRead > 0)
@throw [OFInvalidArgumentException exception];
} @catch (id e) {
[self release];
@@ -631,11 +632,11 @@
/* Content-Length */
if (!_chunked) {
size_t ret;
- if (length > (uintmax_t)_toRead)
+ if (length > (unsigned long long)_toRead)
length = (size_t)_toRead;
ret = [_socket readIntoBuffer: buffer
length: length];
@@ -680,11 +681,11 @@
if (_setAtEndOfStream && _toRead == 0)
_atEndOfStream = true;
return 0;
} else if (_toRead > 0) {
- if (length > (uintmax_t)_toRead)
+ if (length > (unsigned long long)_toRead)
length = (size_t)_toRead;
length = [_socket readIntoBuffer: buffer
length: length];
@@ -696,10 +697,11 @@
return length;
} else {
void *pool = objc_autoreleasePoolPush();
OFString *line;
of_range_t range;
+ unsigned long long toRead;
@try {
line = [_socket tryReadLine];
} @catch (OFInvalidEncodingException *e) {
@throw [OFInvalidFormatException exception];
@@ -723,12 +725,14 @@
@throw [OFTruncatedDataException exception];
else
@throw [OFInvalidFormatException exception];
}
- if ((_toRead = line.hexadecimalValue) < 0)
+ toRead = [line unsignedLongLongValueWithBase: 16];
+ if (toRead > LLONG_MAX)
@throw [OFOutOfRangeException exception];
+ _toRead = (long long)toRead;
if (_toRead == 0) {
_setAtEndOfStream = true;
_toRead = -2;
}
Index: src/OFINICategory.h
==================================================================
--- src/OFINICategory.h
+++ src/OFINICategory.h
@@ -79,12 +79,12 @@
* @param key The key for which the integer value should be returned
* @param defaultValue The value to return if the key does not exist
* @return The integer value for the specified key or the specified default
* value if it does not exist
*/
-- (intmax_t)integerForKey: (OFString *)key
- defaultValue: (intmax_t)defaultValue;
+- (long long)integerForKey: (OFString *)key
+ defaultValue: (long long)defaultValue;
/*!
* @brief Returns the bool value for the specified key or the specified default
* value if it does not exist.
*
@@ -161,11 +161,11 @@
* the first key/value pair found is changed.
*
* @param integer The integer to which the value of the key should be set
* @param key The key for which the new value should be set
*/
-- (void)setInteger: (intmax_t)integer
+- (void)setInteger: (long long)integer
forKey: (OFString *)key;
/*!
* @brief Sets the value of the specified key to the specified bool.
*
Index: src/OFINICategory.m
==================================================================
--- src/OFINICategory.m
+++ src/OFINICategory.m
@@ -207,24 +207,21 @@
}
return defaultValue;
}
-- (intmax_t)integerForKey: (OFString *)key
- defaultValue: (intmax_t)defaultValue
+- (long long)integerForKey: (OFString *)key
+ defaultValue: (long long)defaultValue
{
void *pool = objc_autoreleasePoolPush();
OFString *value = [self stringForKey: key
defaultValue: nil];
- intmax_t ret;
-
- if (value != nil) {
- if ([value hasPrefix: @"0x"] || [value hasPrefix: @"$"])
- ret = value.hexadecimalValue;
- else
- ret = value.decimalValue;
- } else
+ long long ret;
+
+ if (value != nil)
+ ret = [value longLongValueWithBase: 0];
+ else
ret = defaultValue;
objc_autoreleasePoolPop(pool);
return ret;
@@ -352,16 +349,16 @@
}
objc_autoreleasePoolPop(pool);
}
-- (void)setInteger: (intmax_t)integer
+- (void)setInteger: (long long)integer
forKey: (OFString *)key
{
void *pool = objc_autoreleasePoolPush();
- [self setString: [OFString stringWithFormat: @"%jd", integer]
+ [self setString: [OFString stringWithFormat: @"%lld", integer]
forKey: key];
objc_autoreleasePoolPop(pool);
}
Index: src/OFINIFileSettings.m
==================================================================
--- src/OFINIFileSettings.m
+++ src/OFINIFileSettings.m
@@ -86,11 +86,11 @@
forKey: key];
objc_autoreleasePoolPop(pool);
}
-- (void)setInteger: (intmax_t)integer
+- (void)setInteger: (long long)integer
forPath: (OFString *)path
{
void *pool = objc_autoreleasePoolPush();
OFString *category, *key;
@@ -184,16 +184,16 @@
[ret retain];
objc_autoreleasePoolPop(pool);
return [ret autorelease];
}
-- (intmax_t)integerForPath: (OFString *)path
- defaultValue: (intmax_t)defaultValue
+- (long long)integerForPath: (OFString *)path
+ defaultValue: (long long)defaultValue
{
void *pool = objc_autoreleasePoolPush();
OFString *category, *key;
- intmax_t ret;
+ long long ret;
[self of_getCategory: &category
andKey: &key
forPath: path];
Index: src/OFLHAArchiveEntry.m
==================================================================
--- src/OFLHAArchiveEntry.m
+++ src/OFLHAArchiveEntry.m
@@ -125,11 +125,11 @@
mode = OF_BSWAP16_IF_BE(mode);
[entry->_mode release];
entry->_mode = nil;
- entry->_mode = [[OFNumber alloc] initWithUInt16: mode];
+ entry->_mode = [[OFNumber alloc] initWithUnsignedShort: mode];
}
static void
parseGIDUIDExtension(OFLHAArchiveEntry *entry, OFData *extension,
of_string_encoding_t encoding)
@@ -149,12 +149,12 @@
entry->_GID = nil;
[entry->_UID release];
entry->_UID = nil;
- entry->_GID = [[OFNumber alloc] initWithUInt16: GID];
- entry->_UID = [[OFNumber alloc] initWithUInt16: UID];
+ entry->_GID = [[OFNumber alloc] initWithUnsignedShort: GID];
+ entry->_UID = [[OFNumber alloc] initWithUnsignedShort: UID];
}
static void
parseGroupExtension(OFLHAArchiveEntry *entry, OFData *extension,
of_string_encoding_t encoding)
@@ -653,11 +653,11 @@
tmp16 = OF_BSWAP16_IF_BE(5);
[data addItems: &tmp16
count: sizeof(tmp16)];
[data addItem: "\x50"];
- tmp16 = OF_BSWAP16_IF_BE(_mode.uInt16Value);
+ tmp16 = OF_BSWAP16_IF_BE(_mode.unsignedShortValue);
[data addItems: &tmp16
count: sizeof(tmp16)];
}
if (_UID != nil || _GID != nil) {
@@ -667,15 +667,15 @@
tmp16 = OF_BSWAP16_IF_BE(7);
[data addItems: &tmp16
count: sizeof(tmp16)];
[data addItem: "\x51"];
- tmp16 = OF_BSWAP16_IF_BE(_GID.uInt16Value);
+ tmp16 = OF_BSWAP16_IF_BE(_GID.unsignedShortValue);
[data addItems: &tmp16
count: sizeof(tmp16)];
- tmp16 = OF_BSWAP16_IF_BE(_UID.uInt16Value);
+ tmp16 = OF_BSWAP16_IF_BE(_UID.unsignedShortValue);
[data addItems: &tmp16
count: sizeof(tmp16)];
}
if (_group != nil) {
@@ -759,11 +759,11 @@
- (OFString *)description
{
void *pool = objc_autoreleasePoolPush();
OFString *mode = (_mode == nil ? nil
- : [OFString stringWithFormat: @"%" PRIo16, _mode.uInt16Value]);
+ : [OFString stringWithFormat: @"%ho", _mode.unsignedShortValue]);
OFString *extensions = [_extensions.description
stringByReplacingOccurrencesOfString: @"\n"
withString: @"\n\t"];
OFString *ret = [OFString stringWithFormat:
@"<%@:\n"
Index: src/OFLocale.m
==================================================================
--- src/OFLocale.m
+++ src/OFLocale.m
@@ -213,12 +213,13 @@
compare: second] != OF_ORDERED_ASCENDING];
else if ([token isEqual: @"+"])
var = [OFNumber numberWithDouble:
[first doubleValue] + [second doubleValue]];
else if ([token isEqual: @"%"])
- var = [OFNumber numberWithIntMax:
- [first intMaxValue] % [second intMaxValue]];
+ var = [OFNumber numberWithLongLong:
+ [first longLongValue] %
+ [second longLongValue]];
else if ([token isEqual: @"&&"])
var = [OFNumber numberWithBool:
[first boolValue] && [second boolValue]];
else if ([token isEqual: @"||"])
var = [OFNumber numberWithBool:
@@ -236,11 +237,12 @@
if ([token isEqual: @"!"])
var = [OFNumber numberWithBool:
![first boolValue]];
else if ([token isEqual: @"is_real"])
var = [OFNumber numberWithBool:
- [first doubleValue] != [first intMaxValue]];
+ ([first doubleValue] !=
+ [first longLongValue])];
else
OF_ENSURE(0);
[stack replaceObjectAtIndex: stackSize - 1
withObject: var];
@@ -508,11 +510,12 @@
pool = objc_autoreleasePoolPush();
mapPath = [path stringByAppendingPathComponent: @"languages.json"];
@try {
- map = [[OFString stringWithContentsOfFile: mapPath] JSONValue];
+ map = [[OFString stringWithContentsOfFile: mapPath]
+ objectByParsingJSON];
} @catch (OFOpenItemFailedException *e) {
objc_autoreleasePoolPop(pool);
return;
}
@@ -532,12 +535,12 @@
}
languageFile = [path stringByAppendingPathComponent:
[languageFile stringByAppendingString: @".json"]];
- [_localizedStrings addObject:
- [[OFString stringWithContentsOfFile: languageFile] JSONValue]];
+ [_localizedStrings addObject: [[OFString stringWithContentsOfFile:
+ languageFile] objectByParsingJSON]];
objc_autoreleasePoolPop(pool);
}
#endif
Index: src/OFMutableTarArchiveEntry.h
==================================================================
--- src/OFMutableTarArchiveEntry.h
+++ src/OFMutableTarArchiveEntry.h
@@ -36,26 +36,26 @@
@property (readwrite, copy, nonatomic) OFString *fileName;
/*!
* @brief The mode of the entry.
*/
-@property (readwrite, nonatomic) uint32_t mode;
+@property (readwrite, nonatomic) unsigned long mode;
/*!
* @brief The UID of the owner.
*/
-@property (readwrite, nonatomic) uint32_t UID;
+@property (readwrite, nonatomic) unsigned long UID;
/*!
* @brief The GID of the group.
*/
-@property (readwrite, nonatomic) uint32_t GID;
+@property (readwrite, nonatomic) unsigned long GID;
/*!
* @brief The size of the file.
*/
-@property (readwrite, nonatomic) uint64_t size;
+@property (readwrite, nonatomic) unsigned long long size;
/*!
* @brief The date of the last modification of the file.
*/
@property (readwrite, retain, nonatomic) OFDate *modificationDate;
@@ -84,20 +84,20 @@
@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *group;
/*!
* @brief The device major (if the file is a device).
*/
-@property (readwrite, nonatomic) uint32_t deviceMajor;
+@property (readwrite, nonatomic) unsigned long deviceMajor;
/*!
* @brief The device major (if the file is a device).
*/
-@property (readwrite, nonatomic) uint32_t deviceMinor;
+@property (readwrite, nonatomic) unsigned long deviceMinor;
/*!
* @brief Converts the OFMutableTarArchiveEntry to an immutable
* OFTarArchiveEntry.
*/
- (void)makeImmutable;
@end
OF_ASSUME_NONNULL_END
Index: src/OFMutableTarArchiveEntry.m
==================================================================
--- src/OFMutableTarArchiveEntry.m
+++ src/OFMutableTarArchiveEntry.m
@@ -39,26 +39,26 @@
OFString *old = _fileName;
_fileName = [fileName copy];
[old release];
}
-- (void)setMode: (uint32_t)mode
+- (void)setMode: (unsigned long)mode
{
_mode = mode;
}
-- (void)setUID: (uint32_t)UID
+- (void)setUID: (unsigned long)UID
{
_UID = UID;
}
-- (void)setGID: (uint32_t)GID
+- (void)setGID: (unsigned long)GID
{
_GID = GID;
}
-- (void)setSize: (uint64_t)size
+- (void)setSize: (unsigned long long)size
{
_size = size;
}
- (void)setModificationDate: (OFDate *)modificationDate
@@ -92,20 +92,20 @@
OFString *old = _group;
_group = [group copy];
[old release];
}
-- (void)setDeviceMajor: (uint32_t)deviceMajor
+- (void)setDeviceMajor: (unsigned long)deviceMajor
{
_deviceMajor = deviceMajor;
}
-- (void)setDeviceMinor: (uint32_t)deviceMinor
+- (void)setDeviceMinor: (unsigned long)deviceMinor
{
_deviceMinor = deviceMinor;
}
- (void)makeImmutable
{
object_setClass(self, [OFTarArchiveEntry class]);
}
@end
Index: src/OFNumber.h
==================================================================
--- src/OFNumber.h
+++ src/OFNumber.h
@@ -47,13 +47,13 @@
#endif
@interface OFNumber: OFValue
{
union of_number_value {
- double float_;
- intmax_t signed_;
- uintmax_t unsigned_;
+ double float_;
+ long long signed_;
+ unsigned long long unsigned_;
} _value;
enum of_number_type {
OF_NUMBER_TYPE_FLOAT = 1,
OF_NUMBER_TYPE_SIGNED,
OF_NUMBER_TYPE_UNSIGNED
@@ -114,85 +114,10 @@
/*!
* @brief The OFNumber as an `unsigned long long`.
*/
@property (readonly, nonatomic) unsigned long long unsignedLongLongValue;
-/*!
- * @brief The OFNumber as an `int8_t`.
- */
-@property (readonly, nonatomic) int8_t int8Value;
-
-/*!
- * @brief The OFNumber as an `int16_t`.
- */
-@property (readonly, nonatomic) int16_t int16Value;
-
-/*!
- * @brief The OFNumber as an `int32_t`.
- */
-@property (readonly, nonatomic) int32_t int32Value;
-
-/*!
- * @brief The OFNumber as an `int64_t`.
- */
-@property (readonly, nonatomic) int64_t int64Value;
-
-/*!
- * @brief The OFNumber as a `uint8_t`.
- */
-@property (readonly, nonatomic) uint8_t uInt8Value;
-
-/*!
- * @brief The OFNumber as a `uint16_t`.
- */
-@property (readonly, nonatomic) uint16_t uInt16Value;
-
-/*!
- * @brief The OFNumber as a `uint32_t`.
- */
-@property (readonly, nonatomic) uint32_t uInt32Value;
-
-/*!
- * @brief The OFNumber as a `uint64_t`.
- */
-@property (readonly, nonatomic) uint64_t uInt64Value;
-
-/*!
- * @brief The OFNumber as a `size_t`.
- */
-@property (readonly, nonatomic) size_t sizeValue;
-
-/*!
- * @brief The OFNumber as an `ssize_t`.
- */
-@property (readonly, nonatomic) ssize_t sSizeValue;
-
-/*!
- * @brief The OFNumber as an `intmax_t`.
- */
-@property (readonly, nonatomic) intmax_t intMaxValue;
-
-/*!
- * @brief The OFNumber as a `uintmax_t`.
- */
-@property (readonly, nonatomic) uintmax_t uIntMaxValue;
-
-/*!
- * @brief The OFNumber as a `ptrdiff_t`.
- */
-@property (readonly, nonatomic) ptrdiff_t ptrDiffValue;
-
-/*!
- * @brief The OFNumber as an `intptr_t`.
- */
-@property (readonly, nonatomic) intptr_t intPtrValue;
-
-/*!
- * @brief The OFNumber as a `uintptr_t`.
- */
-@property (readonly, nonatomic) uintptr_t uIntPtrValue;
-
/*!
* @brief The OFNumber as a `float`.
*/
@property (readonly, nonatomic) float floatValue;
@@ -218,230 +143,110 @@
#endif
/*!
* @brief Creates a new OFNumber with the specified `bool`.
*
- * @param bool_ A `bool` which the OFNumber should contain
+ * @param value The `bool` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithBool: (bool)bool_;
++ (instancetype)numberWithBool: (bool)value;
/*!
* @brief Creates a new OFNumber with the specified `signed char`.
*
- * @param sChar A `signed char` which the OFNumber should contain
+ * @param value The `signed char` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithChar: (signed char)sChar;
++ (instancetype)numberWithChar: (signed char)value;
/*!
* @brief Creates a new OFNumber with the specified `short`.
*
- * @param sShort A `short` which the OFNumber should contain
+ * @param value The `short` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithShort: (short)sShort;
++ (instancetype)numberWithShort: (short)value;
/*!
* @brief Creates a new OFNumber with the specified `int`.
*
- * @param sInt An `int` which the OFNumber should contain
+ * @param value The `int` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithInt: (int)sInt;
++ (instancetype)numberWithInt: (int)value;
/*!
* @brief Creates a new OFNumber with the specified `long`.
*
- * @param sLong A `long` which the OFNumber should contain
+ * @param value The `long` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithLong: (long)sLong;
++ (instancetype)numberWithLong: (long)value;
/*!
* @brief Creates a new OFNumber with the specified `long long`.
*
- * @param sLongLong A `long long` which the OFNumber should contain
+ * @param value The `long long` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithLongLong: (long long)sLongLong;
++ (instancetype)numberWithLongLong: (long long)value;
/*!
* @brief Creates a new OFNumber with the specified `unsigned char`.
*
- * @param uChar An `unsigned char` which the OFNumber should contain
+ * @param value The `unsigned char` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithUnsignedChar: (unsigned char)uChar;
++ (instancetype)numberWithUnsignedChar: (unsigned char)value;
/*!
* @brief Creates a new OFNumber with the specified `unsigned short`.
*
- * @param uShort An `unsigned short` which the OFNumber should contain
+ * @param value The `unsigned short` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithUnsignedShort: (unsigned short)uShort;
++ (instancetype)numberWithUnsignedShort: (unsigned short)value;
/*!
* @brief Creates a new OFNumber with the specified `unsigned int`.
*
- * @param uInt An `unsigned int` which the OFNumber should contain
+ * @param value The `unsigned int` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithUnsignedInt: (unsigned int)uInt;
++ (instancetype)numberWithUnsignedInt: (unsigned int)value;
/*!
* @brief Creates a new OFNumber with the specified `unsigned long`.
*
- * @param uLong An `unsigned long` which the OFNumber should contain
+ * @param value The `unsigned long` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithUnsignedLong: (unsigned long)uLong;
++ (instancetype)numberWithUnsignedLong: (unsigned long)value;
/*!
* @brief Creates a new OFNumber with the specified `unsigned long long`.
*
- * @param uLongLong An `unsigned long long` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithUnsignedLongLong: (unsigned long long)uLongLong;
-
-/*!
- * @brief Creates a new OFNumber with the specified `int8_t`.
- *
- * @param int8 An `int8_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithInt8: (int8_t)int8;
-
-/*!
- * @brief Creates a new OFNumber with the specified `int16_t`.
- *
- * @param int16 An `int16_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithInt16: (int16_t)int16;
-
-/*!
- * @brief Creates a new OFNumber with the specified `int32_t`.
- *
- * @param int32 An `int32_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithInt32: (int32_t)int32;
-
-/*!
- * @brief Creates a new OFNumber with the specified `int64_t`.
- *
- * @param int64 An `int64_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithInt64: (int64_t)int64;
-
-/*!
- * @brief Creates a new OFNumber with the specified `uint8_t`.
- *
- * @param uInt8 A `uint8_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithUInt8: (uint8_t)uInt8;
-
-/*!
- * @brief Creates a new OFNumber with the specified `uint16_t`.
- *
- * @param uInt16 A `uint16_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithUInt16: (uint16_t)uInt16;
-
-/*!
- * @brief Creates a new OFNumber with the specified `uint32_t`.
- *
- * @param uInt32 A `uint32_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithUInt32: (uint32_t)uInt32;
-
-/*!
- * @brief Creates a new OFNumber with the specified `uint64_t`.
- *
- * @param uInt64 A `uint64_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithUInt64: (uint64_t)uInt64;
-
-/*!
- * @brief Creates a new OFNumber with the specified `size_t`.
- *
- * @param size A `size_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithSize: (size_t)size;
-
-/*!
- * @brief Creates a new OFNumber with the specified `ssize_t`.
- *
- * @param sSize An `ssize_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithSSize: (ssize_t)sSize;
-
-/*!
- * @brief Creates a new OFNumber with the specified `intmax_t`.
- *
- * @param intMax An `intmax_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithIntMax: (intmax_t)intMax;
-
-/*!
- * @brief Creates a new OFNumber with the specified `uintmax_t`.
- *
- * @param uIntMax A `uintmax_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithUIntMax: (uintmax_t)uIntMax;
-
-/*!
- * @brief Creates a new OFNumber with the specified `ptrdiff_t`.
- *
- * @param ptrDiff A `ptrdiff_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithPtrDiff: (ptrdiff_t)ptrDiff;
-
-/*!
- * @brief Creates a new OFNumber with the specified `intptr_t`.
- *
- * @param intPtr An `intptr_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithIntPtr: (intptr_t)intPtr;
-
-/*!
- * @brief Creates a new OFNumber with the specified `uintptr_t`.
- *
- * @param uIntPtr A `uintptr_t` which the OFNumber should contain
- * @return A new autoreleased OFNumber
- */
-+ (instancetype)numberWithUIntPtr: (uintptr_t)uIntPtr;
+ * @param value The `unsigned long long` value which the OFNumber should contain
+ * @return A new autoreleased OFNumber
+ */
++ (instancetype)numberWithUnsignedLongLong: (unsigned long long)value;
/*!
* @brief Creates a new OFNumber with the specified `float`.
*
- * @param float_ A `float` which the OFNumber should contain
+ * @param value The `float` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithFloat: (float)float_;
++ (instancetype)numberWithFloat: (float)value;
/*!
* @brief Creates a new OFNumber with the specified `double`.
*
- * @param double_ A `double` which the OFNumber should contain
+ * @param value The `double` value which the OFNumber should contain
* @return A new autoreleased OFNumber
*/
-+ (instancetype)numberWithDouble: (double)double_;
++ (instancetype)numberWithDouble: (double)value;
- (instancetype)init OF_UNAVAILABLE;
#ifdef OF_HAVE_UNAVAILABLE
- (instancetype)initWithBytes: (const void *)bytes
objCType: (const char *)objCType OF_UNAVAILABLE;
@@ -454,253 +259,120 @@
#endif
/*!
* @brief Initializes an already allocated OFNumber with the specified `bool`.
*
- * @param bool_ A `bool` which the OFNumber should contain
+ * @param value The `bool` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithBool: (bool)bool_;
+- (instancetype)initWithBool: (bool)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified
* `signed char`.
*
- * @param sChar A `signed char` which the OFNumber should contain
+ * @param value The `signed char` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithChar: (signed char)sChar;
+- (instancetype)initWithChar: (signed char)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified `short`.
*
- * @param sShort A `short` which the OFNumber should contain
+ * @param value The `short` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithShort: (short)sShort;
+- (instancetype)initWithShort: (short)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified `int`.
*
- * @param sInt An `int` which the OFNumber should contain
+ * @param value The `int` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithInt: (int)sInt;
+- (instancetype)initWithInt: (int)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified `long`.
*
- * @param sLong A `long` which the OFNumber should contain
+ * @param value The `long` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithLong: (long)sLong;
+- (instancetype)initWithLong: (long)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified
* `long long`.
*
- * @param sLongLong A `long long` which the OFNumber should contain
+ * @param value The `long long` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithLongLong: (long long)sLongLong;
+- (instancetype)initWithLongLong: (long long)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified
* `unsigned char`.
*
- * @param uChar An `unsigned char` which the OFNumber should contain
+ * @param value The `unsigned char` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithUnsignedChar: (unsigned char)uChar;
+- (instancetype)initWithUnsignedChar: (unsigned char)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified
* `unsigned short`.
*
- * @param uShort An `unsigned short` which the OFNumber should contain
+ * @param value The `unsigned short` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithUnsignedShort: (unsigned short)uShort;
+- (instancetype)initWithUnsignedShort: (unsigned short)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified
* `unsigned int`.
*
- * @param uInt An `unsigned int` which the OFNumber should contain
+ * @param value The `unsigned int` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithUnsignedInt: (unsigned int)uInt;
+- (instancetype)initWithUnsignedInt: (unsigned int)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified
* `unsigned long`.
*
- * @param uLong An `unsigned long` which the OFNumber should contain
+ * @param value The `unsigned long` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithUnsignedLong: (unsigned long)uLong;
+- (instancetype)initWithUnsignedLong: (unsigned long)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified
* `unsigned long long`.
*
- * @param uLongLong An `unsigned long long` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithUnsignedLongLong: (unsigned long long)uLongLong;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified `int8_t`.
- *
- * @param int8 An `int8_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithInt8: (int8_t)int8;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `int16_t`.
- *
- * @param int16 An `int16_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithInt16: (int16_t)int16;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `int32_t`.
- *
- * @param int32 An `int32_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithInt32: (int32_t)int32;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `int64_t`.
- *
- * @param int64 An `int64_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithInt64: (int64_t)int64;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `uint8_t`.
- *
- * @param uInt8 A `uint8_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithUInt8: (uint8_t)uInt8;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `uint16_t`.
- *
- * @param uInt16 A `uint16_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithUInt16: (uint16_t)uInt16;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `uint32_t`.
- *
- * @param uInt32 A `uint32_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithUInt32: (uint32_t)uInt32;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `uint64_t`.
- *
- * @param uInt64 A `uint64_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithUInt64: (uint64_t)uInt64;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified `size_t`.
- *
- * @param size A `size_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithSize: (size_t)size;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `ssize_t`.
- *
- * @param sSize An `ssize_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithSSize: (ssize_t)sSize;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `intmax_t`.
- *
- * @param intMax An `intmax_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithIntMax: (intmax_t)intMax;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `uintmax_t`.
- *
- * @param uIntMax A `uintmax_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithUIntMax: (uintmax_t)uIntMax;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `ptrdiff_t`.
- *
- * @param ptrDiff A `ptrdiff_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithPtrDiff: (ptrdiff_t)ptrDiff;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `intptr_t`.
- *
- * @param intPtr An `intptr_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithIntPtr: (intptr_t)intPtr;
-
-/*!
- * @brief Initializes an already allocated OFNumber with the specified
- * `uintptr_t`.
- *
- * @param uIntPtr A `uintptr_t` which the OFNumber should contain
- * @return An initialized OFNumber
- */
-- (instancetype)initWithUIntPtr: (uintptr_t)uIntPtr;
+ * @param value The `unsigned long long` value which the OFNumber should contain
+ * @return An initialized OFNumber
+ */
+- (instancetype)initWithUnsignedLongLong: (unsigned long long)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified `float`.
*
- * @param float_ A `float` which the OFNumber should contain
+ * @param value The `float` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithFloat: (float)float_;
+- (instancetype)initWithFloat: (float)value;
/*!
* @brief Initializes an already allocated OFNumber with the specified `double`.
*
- * @param double_ A `double` which the OFNumber should contain
+ * @param value The `double` value which the OFNumber should contain
* @return An initialized OFNumber
*/
-- (instancetype)initWithDouble: (double)double_;
+- (instancetype)initWithDouble: (double)value;
@end
OF_ASSUME_NONNULL_END
#if !defined(NSINTEGER_DEFINED) && !__has_feature(modules)
/* Required for number literals to work */
@compatibility_alias NSNumber OFNumber;
#endif
Index: src/OFNumber.m
==================================================================
--- src/OFNumber.m
+++ src/OFNumber.m
@@ -45,324 +45,178 @@
static struct {
Class isa;
} placeholder;
-static OFNumberSingleton *zeroNumber, *oneNumber, *twoNumber;
-static OFNumberSingleton *trueNumber, *falseNumber;
-
-static void
-initZeroNumber(void)
-{
- zeroNumber = [[OFNumberSingleton alloc] initWithUnsignedChar: 0];
-}
-
-static void
-initOneNumber(void)
-{
- oneNumber = [[OFNumberSingleton alloc] initWithUnsignedChar: 1];
-}
-
-static void
-initTwoNumber(void)
-{
- twoNumber = [[OFNumberSingleton alloc] initWithUnsignedChar: 2];
-}
-
-static void
-initTrueNumber(void)
-{
- trueNumber = [[OFNumberSingleton alloc] initWithBool: true];
-}
-
-static void
-initFalseNumber(void)
-{
- falseNumber = [[OFNumberSingleton alloc] initWithBool: false];
-}
+#define SINGLETON(var, sel, val) \
+ static OFNumberSingleton *var; \
+ \
+ static void \
+ var##Init(void) \
+ { \
+ var = [[OFNumberSingleton alloc] sel val]; \
+ }
+SINGLETON(falseNumber, initWithBool:, false)
+SINGLETON(trueNumber, initWithBool:, true)
+SINGLETON(charZeroNumber, initWithChar:, 0)
+SINGLETON(shortZeroNumber, initWithShort:, 0)
+SINGLETON(intZeroNumber, initWithInt:, 0)
+SINGLETON(longZeroNumber, initWithLong:, 0)
+SINGLETON(longLongZeroNumber, initWithLongLong:, 0)
+SINGLETON(unsignedCharZeroNumber, initWithUnsignedChar:, 0)
+SINGLETON(unsignedShortZeroNumber, initWithUnsignedShort:, 0)
+SINGLETON(unsignedIntZeroNumber, initWithUnsignedInt:, 0)
+SINGLETON(unsignedLongZeroNumber, initWithUnsignedLong:, 0)
+SINGLETON(unsignedLongLongZeroNumber, initWithUnsignedLongLong:, 0)
+SINGLETON(floatZeroNumber, initWithFloat:, 0)
+SINGLETON(doubleZeroNumber, initWithDouble:, 0)
+#undef SINGLETON
@implementation OFNumberPlaceholder
-- (instancetype)initWithBool: (bool)bool_
+- (instancetype)initWithBool: (bool)value
{
- if (bool_) {
- static of_once_t once;
- of_once(&once, initTrueNumber);
+ if (value) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, trueNumberInit);
return (id)trueNumber;
} else {
- static of_once_t once;
- of_once(&once, initFalseNumber);
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, falseNumberInit);
return (id)falseNumber;
}
}
-- (instancetype)initWithChar: (signed char)sChar
-{
- if (sChar >= 0)
- return [self initWithUnsignedChar: sChar];
-
- return (id)[[OFNumber of_alloc] initWithChar: sChar];
-}
-
-- (instancetype)initWithShort: (short)sShort
-{
- if (sShort >= 0)
- return [self initWithUnsignedShort: sShort];
- if (sShort >= SCHAR_MIN)
- return [self initWithChar: (signed char)sShort];
-
- return (id)[[OFNumber of_alloc] initWithShort: sShort];
-}
-
-- (instancetype)initWithInt: (int)sInt
-{
- if (sInt >= 0)
- return [self initWithUnsignedInt: sInt];
- if (sInt >= SHRT_MIN)
- return [self initWithShort: (short)sInt];
-
- return (id)[[OFNumber of_alloc] initWithInt: sInt];
-}
-
-- (instancetype)initWithLong: (long)sLong
-{
- if (sLong >= 0)
- return [self initWithUnsignedLong: sLong];
- if (sLong >= INT_MIN)
- return [self initWithShort: (int)sLong];
-
- return (id)[[OFNumber of_alloc] initWithLong: sLong];
-}
-
-- (instancetype)initWithLongLong: (long long)sLongLong
-{
- if (sLongLong >= 0)
- return [self initWithUnsignedLongLong: sLongLong];
- if (sLongLong >= LONG_MIN)
- return [self initWithLong: (long)sLongLong];
-
- return (id)[[OFNumber of_alloc] initWithLongLong: sLongLong];
-}
-
-- (instancetype)initWithUnsignedChar: (unsigned char)uChar
-{
- switch (uChar) {
- case 0: {
- static of_once_t once = OF_ONCE_INIT;
- of_once(&once, initZeroNumber);
- return (id)zeroNumber;
- }
- case 1: {
- static of_once_t once = OF_ONCE_INIT;
- of_once(&once, initOneNumber);
- return (id)oneNumber;
- }
- case 2: {
- static of_once_t once = OF_ONCE_INIT;
- of_once(&once, initTwoNumber);
- return (id)twoNumber;
- }
- }
-
- return (id)[[OFNumber of_alloc] initWithUnsignedChar: uChar];
-}
-
-- (instancetype)initWithUnsignedShort: (unsigned short)uShort
-{
- if (uShort <= UCHAR_MAX)
- return [self initWithUnsignedChar: (unsigned char)uShort];
-
- return (id)[[OFNumber of_alloc] initWithUnsignedShort: uShort];
-}
-
-- (instancetype)initWithUnsignedInt: (unsigned int)uInt
-{
- if (uInt <= USHRT_MAX)
- return [self initWithUnsignedShort: (unsigned short)uInt];
-
- return (id)[[OFNumber of_alloc] initWithUnsignedInt: uInt];
-}
-
-- (instancetype)initWithUnsignedLong: (unsigned long)uLong
-{
- if (uLong <= UINT_MAX)
- return [self initWithUnsignedInt: (unsigned int)uLong];
-
- return (id)[[OFNumber of_alloc] initWithUnsignedLong: uLong];
-}
-
-- (instancetype)initWithUnsignedLongLong: (unsigned long long)uLongLong
-{
- if (uLongLong <= ULONG_MAX)
- return [self initWithUnsignedLong: (unsigned long)uLongLong];
-
- return (id)[[OFNumber of_alloc] initWithUnsignedLongLong: uLongLong];
-}
-
-- (instancetype)initWithInt8: (int8_t)int8
-{
- if (int8 >= 0)
- return [self initWithUInt8: int8];
-
- return (id)[[OFNumber of_alloc] initWithInt8: int8];
-}
-
-- (instancetype)initWithInt16: (int16_t)int16
-{
- if (int16 >= 0)
- return [self initWithUInt16: int16];
- if (int16 >= INT8_MIN)
- return [self initWithInt8: (int8_t)int16];
-
- return (id)[[OFNumber of_alloc] initWithInt16: int16];
-}
-
-- (instancetype)initWithInt32: (int32_t)int32
-{
- if (int32 >= 0)
- return [self initWithUInt32: int32];
- if (int32 >= INT16_MIN)
- return [self initWithInt16: (int16_t)int32];
-
- return (id)[[OFNumber of_alloc] initWithInt32: int32];
-}
-
-- (instancetype)initWithInt64: (int64_t)int64
-{
- if (int64 >= 0)
- return [self initWithUInt64: int64];
- if (int64 >= INT32_MIN)
- return [self initWithInt32: (int32_t)int64];
-
- return (id)[[OFNumber of_alloc] initWithInt64: int64];
-}
-
-- (instancetype)initWithUInt8: (uint8_t)uInt8
-{
- return (id)[[OFNumber of_alloc] initWithUInt8: uInt8];
-}
-
-- (instancetype)initWithUInt16: (uint16_t)uInt16
-{
- if (uInt16 <= UINT8_MAX)
- return [self initWithUInt8: (uint8_t)uInt16];
-
- return (id)[[OFNumber of_alloc] initWithUInt16: uInt16];
-}
-
-- (instancetype)initWithUInt32: (uint32_t)uInt32
-{
- if (uInt32 <= UINT16_MAX)
- return [self initWithUInt16: (uint16_t)uInt32];
-
- return (id)[[OFNumber of_alloc] initWithUInt32: uInt32];
-}
-
-- (instancetype)initWithUInt64: (uint64_t)uInt64
-{
- if (uInt64 <= UINT32_MAX)
- return [self initWithUInt32: (uint32_t)uInt64];
-
- return (id)[[OFNumber of_alloc] initWithUInt64: uInt64];
-}
-
-- (instancetype)initWithSize: (size_t)size
-{
- if (size <= ULONG_MAX)
- return [self initWithUnsignedLong: (unsigned long)size];
-
- return (id)[[OFNumber of_alloc] initWithSize: size];
-}
-
-- (instancetype)initWithSSize: (ssize_t)sSize
-{
- if (sSize >= 0)
- return [self initWithSize: sSize];
- if (sSize <= LONG_MIN)
- return [self initWithLong: (long)sSize];
-
- return (id)[[OFNumber of_alloc] initWithSSize: sSize];
-}
-
-- (instancetype)initWithIntMax: (intmax_t)intMax
-{
- if (intMax >= 0)
- return [self initWithUIntMax: intMax];
- if (intMax <= LLONG_MIN)
- return [self initWithLongLong: (long long)intMax];
-
- return (id)[[OFNumber of_alloc] initWithIntMax: intMax];
-}
-
-- (instancetype)initWithUIntMax: (uintmax_t)uIntMax
-{
- if (uIntMax <= ULLONG_MAX)
- return [self initWithUnsignedLongLong:
- (unsigned long long)uIntMax];
-
- return (id)[[OFNumber of_alloc] initWithUIntMax: uIntMax];
-}
-
-#ifdef __clang__
-/*
- * This warning should probably not exist at all, as it prevents checking
- * whether one type fits into another in a portable way.
- */
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
-#endif
-
-- (instancetype)initWithPtrDiff: (ptrdiff_t)ptrDiff
-{
- if (ptrDiff >= LLONG_MIN && ptrDiff <= LLONG_MAX)
- return [self initWithLongLong: (long long)ptrDiff];
-
- return (id)[[OFNumber of_alloc] initWithPtrDiff: ptrDiff];
-}
-
-- (instancetype)initWithIntPtr: (intptr_t)intPtr
-{
- if (intPtr >= 0)
- return [self initWithUIntPtr: intPtr];
- if (intPtr >= LLONG_MIN)
- return [self initWithLongLong: (long long)intPtr];
-
- return (id)[[OFNumber of_alloc] initWithIntPtr: intPtr];
-}
-
-- (instancetype)initWithUIntPtr: (uintptr_t)uIntPtr
-{
- if (uIntPtr <= ULLONG_MAX)
- return [self initWithUnsignedLongLong:
- (unsigned long long)uIntPtr];
-
- return (id)[[OFNumber of_alloc] initWithUIntPtr: uIntPtr];
-}
-
-#ifdef __clang__
-# pragma clang diagnostic pop
-#endif
-
-- (instancetype)initWithFloat: (float)float_
-{
- if (float_ == (uintmax_t)float_)
- return [self initWithUIntMax: (uintmax_t)float_];
- if (float_ == (intmax_t)float_)
- return [self initWithIntMax: (intmax_t)float_];
-
- return (id)[[OFNumber of_alloc] initWithFloat: float_];
-}
-
-- (instancetype)initWithDouble: (double)double_
-{
- if (double_ == (uintmax_t)double_)
- return [self initWithUIntMax: (uintmax_t)double_];
- if (double_ == (intmax_t)double_)
- return [self initWithIntMax: (intmax_t)double_];
- if (double_ == (float)double_)
- return [self initWithFloat: (float)double_];
-
- return (id)[[OFNumber of_alloc] initWithDouble: double_];
+- (instancetype)initWithChar: (signed char)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, charZeroNumberInit);
+ return (id)charZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithChar: value];
+}
+
+- (instancetype)initWithShort: (short)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, shortZeroNumberInit);
+ return (id)shortZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithShort: value];
+}
+
+- (instancetype)initWithInt: (int)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, intZeroNumberInit);
+ return (id)intZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithInt: value];
+}
+
+- (instancetype)initWithLong: (long)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, longZeroNumberInit);
+ return (id)longZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithLong: value];
+}
+
+- (instancetype)initWithLongLong: (long long)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, longLongZeroNumberInit);
+ return (id)longLongZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithLongLong: value];
+}
+
+- (instancetype)initWithUnsignedChar: (unsigned char)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, unsignedCharZeroNumberInit);
+ return (id)unsignedCharZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithUnsignedChar: value];
+}
+
+- (instancetype)initWithUnsignedShort: (unsigned short)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, unsignedShortZeroNumberInit);
+ return (id)unsignedShortZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithUnsignedShort: value];
+}
+
+- (instancetype)initWithUnsignedInt: (unsigned int)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, unsignedIntZeroNumberInit);
+ return (id)unsignedIntZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithUnsignedInt: value];
+}
+
+- (instancetype)initWithUnsignedLong: (unsigned long)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, unsignedLongZeroNumberInit);
+ return (id)unsignedLongZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithUnsignedLong: value];
+}
+
+- (instancetype)initWithUnsignedLongLong: (unsigned long long)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, unsignedLongLongZeroNumberInit);
+ return (id)unsignedLongLongZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithUnsignedLongLong: value];
+}
+
+- (instancetype)initWithFloat: (float)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, floatZeroNumberInit);
+ return (id)floatZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithFloat: value];
+}
+
+- (instancetype)initWithDouble: (double)value
+{
+ if (value == 0) {
+ static of_once_t once = OF_ONCE_INIT;
+ of_once(&once, doubleZeroNumberInit);
+ return (id)doubleZeroNumber;
+ }
+
+ return (id)[[OFNumber of_alloc] initWithDouble: value];
}
- (instancetype)initWithSerialization: (OFXMLElement *)element
{
return (id)[[OFNumber of_alloc] initWithSerialization: element];
@@ -408,457 +262,250 @@
return (id)&placeholder;
return [super alloc];
}
-+ (instancetype)numberWithBool: (bool)bool_
-{
- return [[[self alloc] initWithBool: bool_] autorelease];
-}
-
-+ (instancetype)numberWithChar: (signed char)sChar
-{
- return [[[self alloc] initWithChar: sChar] autorelease];
-}
-
-+ (instancetype)numberWithShort: (short)sShort
-{
- return [[[self alloc] initWithShort: sShort] autorelease];
-}
-
-+ (instancetype)numberWithInt: (int)sInt
-{
- return [[[self alloc] initWithInt: sInt] autorelease];
-}
-
-+ (instancetype)numberWithLong: (long)sLong
-{
- return [[[self alloc] initWithLong: sLong] autorelease];
-}
-
-+ (instancetype)numberWithLongLong: (long long)sLongLong
-{
- return [[[self alloc] initWithLongLong: sLongLong] autorelease];
-}
-
-+ (instancetype)numberWithUnsignedChar: (unsigned char)uChar
-{
- return [[[self alloc] initWithUnsignedChar: uChar] autorelease];
-}
-
-+ (instancetype)numberWithUnsignedShort: (unsigned short)uShort
-{
- return [[[self alloc] initWithUnsignedShort: uShort] autorelease];
-}
-
-+ (instancetype)numberWithUnsignedInt: (unsigned int)uInt
-{
- return [[[self alloc] initWithUnsignedInt: uInt] autorelease];
-}
-
-+ (instancetype)numberWithUnsignedLong: (unsigned long)uLong
-{
- return [[[self alloc] initWithUnsignedLong: uLong] autorelease];
-}
-
-+ (instancetype)numberWithUnsignedLongLong: (unsigned long long)uLongLong
-{
- return [[[self alloc] initWithUnsignedLongLong: uLongLong] autorelease];
-}
-
-+ (instancetype)numberWithInt8: (int8_t)int8
-{
- return [[[self alloc] initWithInt8: int8] autorelease];
-}
-
-+ (instancetype)numberWithInt16: (int16_t)int16
-{
- return [[[self alloc] initWithInt16: int16] autorelease];
-}
-
-+ (instancetype)numberWithInt32: (int32_t)int32
-{
- return [[[self alloc] initWithInt32: int32] autorelease];
-}
-
-+ (instancetype)numberWithInt64: (int64_t)int64
-{
- return [[[self alloc] initWithInt64: int64] autorelease];
-}
-
-+ (instancetype)numberWithUInt8: (uint8_t)uInt8
-{
- return [[[self alloc] initWithUInt8: uInt8] autorelease];
-}
-
-+ (instancetype)numberWithUInt16: (uint16_t)uInt16
-{
- return [[[self alloc] initWithUInt16: uInt16] autorelease];
-}
-
-+ (instancetype)numberWithUInt32: (uint32_t)uInt32
-{
- return [[[self alloc] initWithUInt32: uInt32] autorelease];
-}
-
-+ (instancetype)numberWithUInt64: (uint64_t)uInt64
-{
- return [[[self alloc] initWithUInt64: uInt64] autorelease];
-}
-
-+ (instancetype)numberWithSize: (size_t)size
-{
- return [[[self alloc] initWithSize: size] autorelease];
-}
-
-+ (instancetype)numberWithSSize: (ssize_t)sSize
-{
- return [[[self alloc] initWithSSize: sSize] autorelease];
-}
-
-+ (instancetype)numberWithIntMax: (intmax_t)intMax
-{
- return [[[self alloc] initWithIntMax: intMax] autorelease];
-}
-
-+ (instancetype)numberWithUIntMax: (uintmax_t)uIntMax
-{
- return [[[self alloc] initWithUIntMax: uIntMax] autorelease];
-}
-
-+ (instancetype)numberWithPtrDiff: (ptrdiff_t)ptrDiff
-{
- return [[[self alloc] initWithPtrDiff: ptrDiff] autorelease];
-}
-
-+ (instancetype)numberWithIntPtr: (intptr_t)intPtr
-{
- return [[[self alloc] initWithIntPtr: intPtr] autorelease];
-}
-
-+ (instancetype)numberWithUIntPtr: (uintptr_t)uIntPtr
-{
- return [[[self alloc] initWithUIntPtr: uIntPtr] autorelease];
-}
-
-+ (instancetype)numberWithFloat: (float)float_
-{
- return [[[self alloc] initWithFloat: float_] autorelease];
-}
-
-+ (instancetype)numberWithDouble: (double)double_
-{
- return [[[self alloc] initWithDouble: double_] autorelease];
++ (instancetype)numberWithBool: (bool)value
+{
+ return [[[self alloc] initWithBool: value] autorelease];
+}
+
++ (instancetype)numberWithChar: (signed char)value
+{
+ return [[[self alloc] initWithChar: value] autorelease];
+}
+
++ (instancetype)numberWithShort: (short)value
+{
+ return [[[self alloc] initWithShort: value] autorelease];
+}
+
++ (instancetype)numberWithInt: (int)value
+{
+ return [[[self alloc] initWithInt: value] autorelease];
+}
+
++ (instancetype)numberWithLong: (long)value
+{
+ return [[[self alloc] initWithLong: value] autorelease];
+}
+
++ (instancetype)numberWithLongLong: (long long)value
+{
+ return [[[self alloc] initWithLongLong: value] autorelease];
+}
+
++ (instancetype)numberWithUnsignedChar: (unsigned char)value
+{
+ return [[[self alloc] initWithUnsignedChar: value] autorelease];
+}
+
++ (instancetype)numberWithUnsignedShort: (unsigned short)value
+{
+ return [[[self alloc] initWithUnsignedShort: value] autorelease];
+}
+
++ (instancetype)numberWithUnsignedInt: (unsigned int)value
+{
+ return [[[self alloc] initWithUnsignedInt: value] autorelease];
+}
+
++ (instancetype)numberWithUnsignedLong: (unsigned long)value
+{
+ return [[[self alloc] initWithUnsignedLong: value] autorelease];
+}
+
++ (instancetype)numberWithUnsignedLongLong: (unsigned long long)value
+{
+ return [[[self alloc] initWithUnsignedLongLong: value] autorelease];
+}
+
++ (instancetype)numberWithFloat: (float)value
+{
+ return [[[self alloc] initWithFloat: value] autorelease];
+}
+
++ (instancetype)numberWithDouble: (double)value
+{
+ return [[[self alloc] initWithDouble: value] autorelease];
}
- (instancetype)init
{
OF_INVALID_INIT_METHOD
}
-- (instancetype)initWithBool: (bool)bool_
+- (instancetype)initWithBool: (bool)value
{
self = [super init];
- _value.unsigned_ = bool_;
+ _value.unsigned_ = value;
_type = OF_NUMBER_TYPE_UNSIGNED;
_typeEncoding = @encode(bool);
return self;
}
-- (instancetype)initWithChar: (signed char)sChar
+- (instancetype)initWithChar: (signed char)value
{
self = [super init];
- _value.signed_ = sChar;
+ _value.signed_ = value;
_type = OF_NUMBER_TYPE_SIGNED;
_typeEncoding = @encode(signed char);
return self;
}
-- (instancetype)initWithShort: (short)sShort
+- (instancetype)initWithShort: (short)value
{
self = [super init];
- _value.signed_ = sShort;
+ _value.signed_ = value;
_type = OF_NUMBER_TYPE_SIGNED;
_typeEncoding = @encode(short);
return self;
}
-- (instancetype)initWithInt: (int)sInt
+- (instancetype)initWithInt: (int)value
{
self = [super init];
- _value.signed_ = sInt;
+ _value.signed_ = value;
_type = OF_NUMBER_TYPE_SIGNED;
_typeEncoding = @encode(int);
return self;
}
-- (instancetype)initWithLong: (long)sLong
+- (instancetype)initWithLong: (long)value
{
self = [super init];
- _value.signed_ = sLong;
+ _value.signed_ = value;
_type = OF_NUMBER_TYPE_SIGNED;
_typeEncoding = @encode(long);
return self;
}
-- (instancetype)initWithLongLong: (long long)sLongLong
+- (instancetype)initWithLongLong: (long long)value
{
self = [super init];
- _value.signed_ = sLongLong;
+ _value.signed_ = value;
_type = OF_NUMBER_TYPE_SIGNED;
_typeEncoding = @encode(long long);
return self;
}
-- (instancetype)initWithUnsignedChar: (unsigned char)uChar
+- (instancetype)initWithUnsignedChar: (unsigned char)value
{
self = [super init];
- _value.unsigned_ = uChar;
+ _value.unsigned_ = value;
_type = OF_NUMBER_TYPE_UNSIGNED;
_typeEncoding = @encode(unsigned long);
return self;
}
-- (instancetype)initWithUnsignedShort: (unsigned short)uShort
+- (instancetype)initWithUnsignedShort: (unsigned short)value
{
self = [super init];
- _value.unsigned_ = uShort;
+ _value.unsigned_ = value;
_type = OF_NUMBER_TYPE_UNSIGNED;
_typeEncoding = @encode(unsigned short);
return self;
}
-- (instancetype)initWithUnsignedInt: (unsigned int)uInt
+- (instancetype)initWithUnsignedInt: (unsigned int)value
{
self = [super init];
- _value.unsigned_ = uInt;
+ _value.unsigned_ = value;
_type = OF_NUMBER_TYPE_UNSIGNED;
_typeEncoding = @encode(unsigned int);
return self;
}
-- (instancetype)initWithUnsignedLong: (unsigned long)uLong
+- (instancetype)initWithUnsignedLong: (unsigned long)value
{
self = [super init];
- _value.unsigned_ = uLong;
+ _value.unsigned_ = value;
_type = OF_NUMBER_TYPE_UNSIGNED;
_typeEncoding = @encode(unsigned long);
return self;
}
-- (instancetype)initWithUnsignedLongLong: (unsigned long long)uLongLong
+- (instancetype)initWithUnsignedLongLong: (unsigned long long)value
{
self = [super init];
- _value.unsigned_ = uLongLong;
+ _value.unsigned_ = value;
_type = OF_NUMBER_TYPE_UNSIGNED;
_typeEncoding = @encode(unsigned long long);
return self;
}
-- (instancetype)initWithInt8: (int8_t)int8
-{
- self = [super init];
-
- _value.signed_ = int8;
- _type = OF_NUMBER_TYPE_SIGNED;
- _typeEncoding = @encode(int8_t);
-
- return self;
-}
-
-- (instancetype)initWithInt16: (int16_t)int16
-{
- self = [super init];
-
- _value.signed_ = int16;
- _type = OF_NUMBER_TYPE_SIGNED;
- _typeEncoding = @encode(int16_t);
-
- return self;
-}
-
-- (instancetype)initWithInt32: (int32_t)int32
-{
- self = [super init];
-
- _value.signed_ = int32;
- _type = OF_NUMBER_TYPE_SIGNED;
- _typeEncoding = @encode(int32_t);
-
- return self;
-}
-
-- (instancetype)initWithInt64: (int64_t)int64
-{
- self = [super init];
-
- _value.signed_ = int64;
- _type = OF_NUMBER_TYPE_SIGNED;
- _typeEncoding = @encode(int64_t);
-
- return self;
-}
-
-- (instancetype)initWithUInt8: (uint8_t)uInt8
-{
- self = [super init];
-
- _value.unsigned_ = uInt8;
- _type = OF_NUMBER_TYPE_UNSIGNED;
- _typeEncoding = @encode(uint8_t);
-
- return self;
-}
-
-- (instancetype)initWithUInt16: (uint16_t)uInt16
-{
- self = [super init];
-
- _value.unsigned_ = uInt16;
- _type = OF_NUMBER_TYPE_UNSIGNED;
- _typeEncoding = @encode(uint16_t);
-
- return self;
-}
-
-- (instancetype)initWithUInt32: (uint32_t)uInt32
-{
- self = [super init];
-
- _value.unsigned_ = uInt32;
- _type = OF_NUMBER_TYPE_UNSIGNED;
- _typeEncoding = @encode(uint32_t);
-
- return self;
-}
-
-- (instancetype)initWithUInt64: (uint64_t)uInt64
-{
- self = [super init];
-
- _value.unsigned_ = uInt64;
- _type = OF_NUMBER_TYPE_UNSIGNED;
- _typeEncoding = @encode(uint64_t);
-
- return self;
-}
-
-- (instancetype)initWithSize: (size_t)size
-{
- self = [super init];
-
- _value.unsigned_ = size;
- _type = OF_NUMBER_TYPE_UNSIGNED;
- _typeEncoding = @encode(size_t);
-
- return self;
-}
-
-- (instancetype)initWithSSize: (ssize_t)sSize
-{
- self = [super init];
-
- _value.signed_ = sSize;
- _type = OF_NUMBER_TYPE_SIGNED;
- _typeEncoding = @encode(ssize_t);
-
- return self;
-}
-
-- (instancetype)initWithIntMax: (intmax_t)intMax
-{
- self = [super init];
-
- _value.signed_ = intMax;
- _type = OF_NUMBER_TYPE_SIGNED;
- _typeEncoding = @encode(intmax_t);
-
- return self;
-}
-
-- (instancetype)initWithUIntMax: (uintmax_t)uIntMax
-{
- self = [super init];
-
- _value.unsigned_ = uIntMax;
- _type = OF_NUMBER_TYPE_UNSIGNED;
- _typeEncoding = @encode(uintmax_t);
-
- return self;
-}
-
-- (instancetype)initWithPtrDiff: (ptrdiff_t)ptrDiff
-{
- self = [super init];
-
- _value.signed_ = ptrDiff;
+- (instancetype)initWithPtrDiff: (ptrdiff_t)value
+{
+ self = [super init];
+
+ _value.signed_ = value;
_type = OF_NUMBER_TYPE_SIGNED;
_typeEncoding = @encode(ptrdiff_t);
return self;
}
-- (instancetype)initWithIntPtr: (intptr_t)intPtr
+- (instancetype)initWithIntPtr: (intptr_t)value
{
self = [super init];
- _value.signed_ = intPtr;
+ _value.signed_ = value;
_type = OF_NUMBER_TYPE_SIGNED;
_typeEncoding = @encode(intptr_t);
return self;
}
-- (instancetype)initWithUIntPtr: (uintptr_t)uIntPtr
+- (instancetype)initWithUIntPtr: (uintptr_t)value
{
self = [super init];
- _value.unsigned_ = uIntPtr;
+ _value.unsigned_ = value;
_type = OF_NUMBER_TYPE_UNSIGNED;
_typeEncoding = @encode(uintptr_t);
return self;
}
-- (instancetype)initWithFloat: (float)float_
+- (instancetype)initWithFloat: (float)value
{
self = [super init];
- _value.float_ = float_;
+ _value.float_ = value;
_type = OF_NUMBER_TYPE_FLOAT;
_typeEncoding = @encode(float);
return self;
}
-- (instancetype)initWithDouble: (double)double_
+- (instancetype)initWithDouble: (double)value
{
self = [super init];
- _value.float_ = double_;
+ _value.float_ = value;
_type = OF_NUMBER_TYPE_FLOAT;
_typeEncoding = @encode(double);
return self;
}
@@ -883,22 +530,24 @@
self = [self initWithBool: true];
else if ([stringValue isEqual: @"false"])
self = [self initWithBool: false];
else
@throw [OFInvalidArgumentException exception];
- } else if ([typeString isEqual: @"float"])
+ } else if ([typeString isEqual: @"float"]) {
+ unsigned long long value =
+ [element unsignedLongLongValueWithBase: 16];
+
+ if (value > UINT64_MAX)
+ @throw [OFOutOfRangeException exception];
+
self = [self initWithDouble: OF_BSWAP_DOUBLE_IF_LE(
- OF_INT_TO_DOUBLE_RAW(OF_BSWAP64_IF_LE(
- (uint64_t)element.hexadecimalValue)))];
- else if ([typeString isEqual: @"signed"])
- self = [self initWithIntMax: element.doubleValue];
+ OF_INT_TO_DOUBLE_RAW(OF_BSWAP64_IF_LE(value)))];
+ } else if ([typeString isEqual: @"signed"])
+ self = [self initWithLongLong: element.longLongValue];
else if ([typeString isEqual: @"unsigned"])
- /*
- * FIXME: This will fail if the value is bigger than
- * INTMAX_MAX!
- */
- self = [self initWithUIntMax: element.decimalValue];
+ self = [self initWithUnsignedLongLong:
+ element.unsignedLongLongValue];
else
@throw [OFInvalidArgumentException exception];
objc_autoreleasePoolPop(pool);
} @catch (id e) {
@@ -1011,85 +660,10 @@
- (unsigned long long)unsignedLongLongValue
{
RETURN_AS(unsigned long long)
}
-- (int8_t)int8Value
-{
- RETURN_AS(int8_t)
-}
-
-- (int16_t)int16Value
-{
- RETURN_AS(int16_t)
-}
-
-- (int32_t)int32Value
-{
- RETURN_AS(int32_t)
-}
-
-- (int64_t)int64Value
-{
- RETURN_AS(int64_t)
-}
-
-- (uint8_t)uInt8Value
-{
- RETURN_AS(uint8_t)
-}
-
-- (uint16_t)uInt16Value
-{
- RETURN_AS(uint16_t)
-}
-
-- (uint32_t)uInt32Value
-{
- RETURN_AS(uint32_t)
-}
-
-- (uint64_t)uInt64Value
-{
- RETURN_AS(uint64_t)
-}
-
-- (size_t)sizeValue
-{
- RETURN_AS(size_t)
-}
-
-- (ssize_t)sSizeValue
-{
- RETURN_AS(ssize_t)
-}
-
-- (intmax_t)intMaxValue
-{
- RETURN_AS(intmax_t)
-}
-
-- (uintmax_t)uIntMaxValue
-{
- RETURN_AS(uintmax_t)
-}
-
-- (ptrdiff_t)ptrDiffValue
-{
- RETURN_AS(ptrdiff_t)
-}
-
-- (intptr_t)intPtrValue
-{
- RETURN_AS(intptr_t)
-}
-
-- (uintptr_t)uIntPtrValue
-{
- RETURN_AS(uintptr_t)
-}
-
- (float)floatValue
{
RETURN_AS(float)
}
@@ -1124,13 +698,13 @@
return (value1 == value2);
}
if (_type == OF_NUMBER_TYPE_SIGNED ||
number->_type == OF_NUMBER_TYPE_SIGNED)
- return (number.intMaxValue == self.intMaxValue);
+ return (number.longLongValue == self.longLongValue);
- return (number.uIntMaxValue == self.uIntMaxValue);
+ return (number.unsignedLongLongValue == self.unsignedLongLongValue);
}
- (of_comparison_result_t)compare: (id )object
{
OFNumber *number;
@@ -1151,22 +725,22 @@
return OF_ORDERED_ASCENDING;
return OF_ORDERED_SAME;
} else if (_type == OF_NUMBER_TYPE_SIGNED ||
number->_type == OF_NUMBER_TYPE_SIGNED) {
- intmax_t int1 = self.intMaxValue;
- intmax_t int2 = number.intMaxValue;
+ long long int1 = self.longLongValue;
+ long long int2 = number.longLongValue;
if (int1 > int2)
return OF_ORDERED_DESCENDING;
if (int1 < int2)
return OF_ORDERED_ASCENDING;
return OF_ORDERED_SAME;
} else {
- uintmax_t uint1 = self.uIntMaxValue;
- uintmax_t uint2 = number.uIntMaxValue;
+ unsigned long long uint1 = self.unsignedLongLongValue;
+ unsigned long long uint2 = number.unsignedLongLongValue;
if (uint1 > uint2)
return OF_ORDERED_DESCENDING;
if (uint1 < uint2)
return OF_ORDERED_ASCENDING;
@@ -1190,25 +764,17 @@
d = OF_BSWAP_DOUBLE_IF_BE(self.doubleValue);
for (uint_fast8_t i = 0; i < sizeof(double); i++)
OF_HASH_ADD(hash, ((char *)&d)[i]);
- } else if (type == OF_NUMBER_TYPE_SIGNED) {
- intmax_t v = self.intMaxValue * -1;
-
- while (v != 0) {
- OF_HASH_ADD(hash, v & 0xFF);
- v >>= 8;
- }
-
- OF_HASH_ADD(hash, 1);
- } else if (type == OF_NUMBER_TYPE_UNSIGNED) {
- uintmax_t v = self.uIntMaxValue;
-
- while (v != 0) {
- OF_HASH_ADD(hash, v & 0xFF);
- v >>= 8;
+ } else if (type == OF_NUMBER_TYPE_SIGNED ||
+ type == OF_NUMBER_TYPE_UNSIGNED) {
+ unsigned long long value = self.unsignedLongLongValue;
+
+ while (value != 0) {
+ OF_HASH_ADD(hash, value & 0xFF);
+ value >>= 8;
}
} else
@throw [OFInvalidFormatException exception];
OF_HASH_FINALIZE(hash);
@@ -1231,13 +797,13 @@
if (*_typeEncoding == 'B')
return (_value.unsigned_ ? @"true" : @"false");
if (_type == OF_NUMBER_TYPE_FLOAT)
return [OFString stringWithFormat: @"%g", _value.float_];
if (_type == OF_NUMBER_TYPE_SIGNED)
- return [OFString stringWithFormat: @"%jd", _value.signed_];
+ return [OFString stringWithFormat: @"%lld", _value.signed_];
if (_type == OF_NUMBER_TYPE_UNSIGNED)
- return [OFString stringWithFormat: @"%ju", _value.unsigned_];
+ return [OFString stringWithFormat: @"%llu", _value.unsigned_];
@throw [OFInvalidFormatException exception];
}
- (OFXMLElement *)XMLElementBySerializing
@@ -1337,11 +903,11 @@
[data addItem: &type];
[data addItems: &tmp
count: sizeof(tmp)];
} else if (_type == OF_NUMBER_TYPE_SIGNED) {
- intmax_t value = self.intMaxValue;
+ long long value = self.longLongValue;
if (value >= -32 && value < 0) {
uint8_t tmp = 0xE0 | ((uint8_t)(value - 32) & 0x1F);
data = [OFMutableData dataWithItems: &tmp
@@ -1386,11 +952,11 @@
[data addItems: &tmp
count: sizeof(tmp)];
} else
@throw [OFOutOfRangeException exception];
} else if (_type == OF_NUMBER_TYPE_UNSIGNED) {
- uintmax_t value = self.uIntMaxValue;
+ unsigned long long value = self.unsignedLongLongValue;
if (value <= 127) {
uint8_t tmp = ((uint8_t)value & 0x7F);
data = [OFMutableData dataWithItems: &tmp
Index: src/OFSettings.h
==================================================================
--- src/OFSettings.h
+++ src/OFSettings.h
@@ -81,11 +81,11 @@
* @brief Sets the specified path to the specified integer.
*
* @param integer The integer to set
* @param path The path to store the integer at
*/
-- (void)setInteger: (intmax_t)integer
+- (void)setInteger: (long long)integer
forPath: (OFString *)path;
/*!
* @brief Sets the specified path to the specified bool.
*
@@ -148,12 +148,12 @@
*
* @param path The path for which the integer value should be returned
* @param defaultValue The default value to return if the path does not exist
* @return The integer value of the specified path
*/
-- (intmax_t)integerForPath: (OFString *)path
- defaultValue: (intmax_t)defaultValue;
+- (long long)integerForPath: (OFString *)path
+ defaultValue: (long long)defaultValue;
/*!
* @brief Returns the bool for the specified path, or the default value if the
* path does not exist.
*
Index: src/OFSettings.m
==================================================================
--- src/OFSettings.m
+++ src/OFSettings.m
@@ -68,11 +68,11 @@
forPath: (OFString *)path
{
OF_UNRECOGNIZED_SELECTOR
}
-- (void)setInteger: (intmax_t)integer
+- (void)setInteger: (long long)integer
forPath: (OFString *)path
{
OF_UNRECOGNIZED_SELECTOR
}
@@ -110,12 +110,12 @@
defaultValue: (OFString *)defaultValue
{
OF_UNRECOGNIZED_SELECTOR
}
-- (intmax_t)integerForPath: (OFString *)path
- defaultValue: (intmax_t)defaultValue
+- (long long)integerForPath: (OFString *)path
+ defaultValue: (long long)defaultValue
{
OF_UNRECOGNIZED_SELECTOR
}
- (bool)boolForPath: (OFString *)path
ADDED src/OFString+JSONParsing.h
Index: src/OFString+JSONParsing.h
==================================================================
--- src/OFString+JSONParsing.h
+++ src/OFString+JSONParsing.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019, 2020
+ * Jonathan Schleifer
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#import "OFString.h"
+
+OF_ASSUME_NONNULL_BEGIN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int _OFString_JSONParsing_reference;
+#ifdef __cplusplus
+}
+#endif
+
+@interface OFString (JSONParsing)
+/*!
+ * @brief The string interpreted as JSON and parsed as an object.
+ *
+ * @note This also allows parsing JSON5, an extension of JSON. See
+ * http://json5.org/ for more details.
+ *
+ * @warning Although not specified by the JSON specification, this can also
+ * return primitives like strings and numbers. The rationale behind
+ * this is that most JSON parsers allow JSON data just consisting of a
+ * single primitive, leading to real world JSON files sometimes only
+ * consisting of a single primitive. Therefore, you should not make any
+ * assumptions about the object returned by this method if you don't
+ * want your program to terminate due to a message not understood, but
+ * instead check the returned object using @ref isKindOfClass:.
+ */
+@property (readonly, nonatomic) id objectByParsingJSON;
+
+/*!
+ * @brief Creates an object from the JSON value of the string.
+ *
+ * @note This also allows parsing JSON5, an extension of JSON. See
+ * http://json5.org/ for more details.
+ *
+ * @warning Although not specified by the JSON specification, this can also
+ * return primitives like strings and numbers. The rationale behind
+ * this is that most JSON parsers allow JSON data just consisting of a
+ * single primitive, leading to real world JSON files sometimes only
+ * consisting of a single primitive. Therefore, you should not make any
+ * assumptions about the object returned by this method if you don't
+ * want your program to terminate due to a message not understood, but
+ * instead check the returned object using @ref isKindOfClass:.
+ *
+ * @param depthLimit The maximum depth the parser should accept (defaults to 32
+ * if not specified, 0 means no limit (insecure!))
+ *
+ * @return An object
+ */
+- (id)objectByParsingJSONWithDepthLimit: (size_t)depthLimit;
+@end
+
+OF_ASSUME_NONNULL_END
ADDED src/OFString+JSONParsing.m
Index: src/OFString+JSONParsing.m
==================================================================
--- src/OFString+JSONParsing.m
+++ src/OFString+JSONParsing.m
@@ -0,0 +1,675 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019, 2020
+ * Jonathan Schleifer
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include
+
+#include
+
+#import "OFString+JSONParsing.h"
+#import "OFArray.h"
+#import "OFDictionary.h"
+#import "OFNumber.h"
+#import "OFNull.h"
+
+#import "OFInvalidJSONException.h"
+
+int _OFString_JSONParsing_reference;
+
+static id nextObject(const char **pointer, const char *stop, size_t *line,
+ size_t depthLimit);
+
+static void
+skipWhitespaces(const char **pointer, const char *stop, size_t *line)
+{
+ while (*pointer < stop && (**pointer == ' ' || **pointer == '\t' ||
+ **pointer == '\r' || **pointer == '\n')) {
+ if (**pointer == '\n')
+ (*line)++;
+
+ (*pointer)++;
+ }
+}
+
+static void
+skipComment(const char **pointer, const char *stop, size_t *line)
+{
+ if (**pointer != '/')
+ return;
+
+ if (*pointer + 1 >= stop)
+ return;
+
+ (*pointer)++;
+
+ if (**pointer == '*') {
+ bool lastIsAsterisk = false;
+
+ (*pointer)++;
+
+ while (*pointer < stop) {
+ if (lastIsAsterisk && **pointer == '/') {
+ (*pointer)++;
+ return;
+ }
+
+ lastIsAsterisk = (**pointer == '*');
+
+ if (**pointer == '\n')
+ (*line)++;
+
+ (*pointer)++;
+ }
+ } else if (**pointer == '/') {
+ (*pointer)++;
+
+ while (*pointer < stop) {
+ if (**pointer == '\r' || **pointer == '\n') {
+ (*pointer)++;
+ (*line)++;
+ return;
+ }
+
+ (*pointer)++;
+ }
+ } else
+ (*pointer)--;
+}
+
+static void
+skipWhitespacesAndComments(const char **pointer, const char *stop, size_t *line)
+{
+ const char *old = NULL;
+
+ while (old != *pointer) {
+ old = *pointer;
+
+ skipWhitespaces(pointer, stop, line);
+ skipComment(pointer, stop, line);
+ }
+}
+
+static inline of_char16_t
+parseUnicodeEscape(const char *pointer, const char *stop)
+{
+ of_char16_t ret = 0;
+
+ if (pointer + 5 >= stop)
+ return 0xFFFF;
+
+ if (pointer[0] != '\\' || pointer[1] != 'u')
+ return 0xFFFF;
+
+ for (uint8_t i = 0; i < 4; i++) {
+ char c = pointer[i + 2];
+ ret <<= 4;
+
+ if (c >= '0' && c <= '9')
+ ret |= c - '0';
+ else if (c >= 'a' && c <= 'f')
+ ret |= c + 10 - 'a';
+ else if (c >= 'A' && c <= 'F')
+ ret |= c + 10 - 'A';
+ else
+ return 0xFFFF;
+ }
+
+ if (ret == 0)
+ return 0xFFFF;
+
+ return ret;
+}
+
+static inline OFString *
+parseString(const char **pointer, const char *stop, size_t *line)
+{
+ char *buffer;
+ size_t i = 0;
+ char delimiter = **pointer;
+
+ if (++(*pointer) + 1 >= stop)
+ return nil;
+
+ if ((buffer = malloc(stop - *pointer)) == NULL)
+ return nil;
+
+ while (*pointer < stop) {
+ /* Parse escape codes */
+ if (**pointer == '\\') {
+ if (++(*pointer) >= stop) {
+ free(buffer);
+ return nil;
+ }
+
+ switch (**pointer) {
+ case '"':
+ case '\\':
+ case '/':
+ buffer[i++] = **pointer;
+ (*pointer)++;
+ break;
+ case 'b':
+ buffer[i++] = '\b';
+ (*pointer)++;
+ break;
+ case 'f':
+ buffer[i++] = '\f';
+ (*pointer)++;
+ break;
+ case 'n':
+ buffer[i++] = '\n';
+ (*pointer)++;
+ break;
+ case 'r':
+ buffer[i++] = '\r';
+ (*pointer)++;
+ break;
+ case 't':
+ buffer[i++] = '\t';
+ (*pointer)++;
+ break;
+ /* Parse Unicode escape sequence */
+ case 'u':;
+ of_char16_t c1, c2;
+ of_unichar_t c;
+ size_t l;
+
+ c1 = parseUnicodeEscape(*pointer - 1, stop);
+ if (c1 == 0xFFFF) {
+ free(buffer);
+ return nil;
+ }
+
+ /* Low surrogate */
+ if ((c1 & 0xFC00) == 0xDC00) {
+ free(buffer);
+ return nil;
+ }
+
+ /* Normal character */
+ if ((c1 & 0xFC00) != 0xD800) {
+ l = of_string_utf8_encode(c1,
+ buffer + i);
+ if (l == 0) {
+ free(buffer);
+ return nil;
+ }
+
+ i += l;
+ *pointer += 5;
+
+ break;
+ }
+
+ /*
+ * If we are still here, we only got one UTF-16
+ * surrogate and now need to get the other one
+ * in order to produce UTF-8 and not CESU-8.
+ */
+ c2 = parseUnicodeEscape(*pointer + 5, stop);
+ if (c2 == 0xFFFF) {
+ free(buffer);
+ return nil;
+ }
+
+ c = (((c1 & 0x3FF) << 10) |
+ (c2 & 0x3FF)) + 0x10000;
+
+ l = of_string_utf8_encode(c, buffer + i);
+ if (l == 0) {
+ free(buffer);
+ return nil;
+ }
+
+ i += l;
+ *pointer += 11;
+
+ break;
+ case '\r':
+ (*pointer)++;
+
+ if (*pointer < stop && **pointer == '\n') {
+ (*pointer)++;
+ (*line)++;
+ }
+
+ break;
+ case '\n':
+ (*pointer)++;
+ (*line)++;
+ break;
+ default:
+ free(buffer);
+ return nil;
+ }
+ /* End of string found */
+ } else if (**pointer == delimiter) {
+ OFString *ret;
+
+ @try {
+ ret = [OFString stringWithUTF8String: buffer
+ length: i];
+ } @finally {
+ free(buffer);
+ }
+
+ (*pointer)++;
+
+ return ret;
+ /* Newlines in strings are disallowed */
+ } else if (**pointer == '\n' || **pointer == '\r') {
+ (*line)++;
+ free(buffer);
+ return nil;
+ } else {
+ buffer[i++] = **pointer;
+ (*pointer)++;
+ }
+ }
+
+ free(buffer);
+ return nil;
+}
+
+static inline OFString *
+parseIdentifier(const char **pointer, const char *stop)
+{
+ char *buffer;
+ size_t i = 0;
+
+ if ((buffer = malloc(stop - *pointer)) == NULL)
+ return nil;
+
+ while (*pointer < stop) {
+ if ((**pointer >= 'a' && **pointer <= 'z') ||
+ (**pointer >= 'A' && **pointer <= 'Z') ||
+ (**pointer >= '0' && **pointer <= '9') ||
+ **pointer == '_' || **pointer == '$' ||
+ (**pointer & 0x80)) {
+ buffer[i++] = **pointer;
+ (*pointer)++;
+ } else if (**pointer == '\\') {
+ of_char16_t c1, c2;
+ of_unichar_t c;
+ size_t l;
+
+ if (++(*pointer) >= stop || **pointer != 'u') {
+ free(buffer);
+ return nil;
+ }
+
+ c1 = parseUnicodeEscape(*pointer - 1, stop);
+ if (c1 == 0xFFFF) {
+ free(buffer);
+ return nil;
+ }
+
+ /* Low surrogate */
+ if ((c1 & 0xFC00) == 0xDC00) {
+ free(buffer);
+ return nil;
+ }
+
+ /* Normal character */
+ if ((c1 & 0xFC00) != 0xD800) {
+ l = of_string_utf8_encode(c1, buffer + i);
+ if (l == 0) {
+ free(buffer);
+ return nil;
+ }
+
+ i += l;
+ *pointer += 5;
+
+ continue;
+ }
+
+ /*
+ * If we are still here, we only got one UTF-16
+ * surrogate and now need to get the other one in order
+ * to produce UTF-8 and not CESU-8.
+ */
+ c2 = parseUnicodeEscape(*pointer + 5, stop);
+ if (c2 == 0xFFFF) {
+ free(buffer);
+ return nil;
+ }
+
+ c = (((c1 & 0x3FF) << 10) | (c2 & 0x3FF)) + 0x10000;
+
+ l = of_string_utf8_encode(c, buffer + i);
+ if (l == 0) {
+ free(buffer);
+ return nil;
+ }
+
+ i += l;
+ *pointer += 11;
+ } else {
+ OFString *ret;
+
+ if (i == 0 || (buffer[0] >= '0' && buffer[0] <= '9')) {
+ free(buffer);
+ return nil;
+ }
+
+ @try {
+ ret = [OFString stringWithUTF8String: buffer
+ length: i];
+ } @finally {
+ free(buffer);
+ }
+
+ return ret;
+ }
+ }
+
+ /*
+ * It is never possible to end with an identifier, thus we should never
+ * reach stop.
+ */
+ return nil;
+}
+
+static inline OFMutableArray *
+parseArray(const char **pointer, const char *stop, size_t *line,
+ size_t depthLimit)
+{
+ OFMutableArray *array = [OFMutableArray array];
+
+ if (++(*pointer) >= stop)
+ return nil;
+
+ if (--depthLimit == 0)
+ return nil;
+
+ while (**pointer != ']') {
+ id object;
+
+ skipWhitespacesAndComments(pointer, stop, line);
+ if (*pointer >= stop)
+ return nil;
+
+ if (**pointer == ']')
+ break;
+
+ if (**pointer == ',') {
+ (*pointer)++;
+ skipWhitespacesAndComments(pointer, stop, line);
+
+ if (*pointer >= stop || **pointer != ']')
+ return nil;
+
+ break;
+ }
+
+ object = nextObject(pointer, stop, line, depthLimit);
+ if (object == nil)
+ return nil;
+
+ [array addObject: object];
+
+ skipWhitespacesAndComments(pointer, stop, line);
+ if (*pointer >= stop)
+ return nil;
+
+ if (**pointer == ',') {
+ (*pointer)++;
+ skipWhitespacesAndComments(pointer, stop, line);
+
+ if (*pointer >= stop)
+ return nil;
+ } else if (**pointer != ']')
+ return nil;
+ }
+
+ (*pointer)++;
+
+ return array;
+}
+
+static inline OFMutableDictionary *
+parseDictionary(const char **pointer, const char *stop, size_t *line,
+ size_t depthLimit)
+{
+ OFMutableDictionary *dictionary = [OFMutableDictionary dictionary];
+
+ if (++(*pointer) >= stop)
+ return nil;
+
+ if (--depthLimit == 0)
+ return nil;
+
+ while (**pointer != '}') {
+ OFString *key;
+ id object;
+
+ skipWhitespacesAndComments(pointer, stop, line);
+ if (*pointer >= stop)
+ return nil;
+
+ if (**pointer == '}')
+ break;
+
+ if (**pointer == ',') {
+ (*pointer)++;
+ skipWhitespacesAndComments(pointer, stop, line);
+
+ if (*pointer >= stop || **pointer != '}')
+ return nil;
+
+ break;
+ }
+
+ skipWhitespacesAndComments(pointer, stop, line);
+ if (*pointer + 1 >= stop)
+ return nil;
+
+ if ((**pointer >= 'a' && **pointer <= 'z') ||
+ (**pointer >= 'A' && **pointer <= 'Z') ||
+ **pointer == '_' || **pointer == '$' || **pointer == '\\')
+ key = parseIdentifier(pointer, stop);
+ else
+ key = nextObject(pointer, stop, line, depthLimit);
+
+ if (![key isKindOfClass: [OFString class]])
+ return nil;
+
+ skipWhitespacesAndComments(pointer, stop, line);
+ if (*pointer + 1 >= stop || **pointer != ':')
+ return nil;
+
+ (*pointer)++;
+
+ object = nextObject(pointer, stop, line, depthLimit);
+ if (object == nil)
+ return nil;
+
+ [dictionary setObject: object
+ forKey: key];
+
+ skipWhitespacesAndComments(pointer, stop, line);
+ if (*pointer >= stop)
+ return nil;
+
+ if (**pointer == ',') {
+ (*pointer)++;
+ skipWhitespacesAndComments(pointer, stop, line);
+
+ if (*pointer >= stop)
+ return nil;
+ } else if (**pointer != '}')
+ return nil;
+ }
+
+ (*pointer)++;
+
+ return dictionary;
+}
+
+static inline OFNumber *
+parseNumber(const char **pointer, const char *stop, size_t *line)
+{
+ bool isNegative = (*pointer < stop && (*pointer)[0] == '-');
+ bool hasDecimal = false;
+ size_t i;
+ OFString *string;
+ OFNumber *number;
+
+ for (i = 0; *pointer + i < stop; i++) {
+ if ((*pointer)[i] == '.')
+ hasDecimal = true;
+
+ if ((*pointer)[i] == ' ' || (*pointer)[i] == '\t' ||
+ (*pointer)[i] == '\r' || (*pointer)[i] == '\n' ||
+ (*pointer)[i] == ',' || (*pointer)[i] == ']' ||
+ (*pointer)[i] == '}') {
+ if ((*pointer)[i] == '\n')
+ (*line)++;
+
+ break;
+ }
+ }
+
+ string = [[OFString alloc] initWithUTF8String: *pointer
+ length: i];
+ *pointer += i;
+
+ @try {
+ if (hasDecimal)
+ number = [OFNumber numberWithDouble:
+ string.doubleValue];
+ else if ([string isEqual: @"Infinity"])
+ number = [OFNumber numberWithDouble: INFINITY];
+ else if ([string isEqual: @"-Infinity"])
+ number = [OFNumber numberWithDouble: -INFINITY];
+ else if (isNegative)
+ number = [OFNumber numberWithLongLong:
+ [string longLongValueWithBase: 0]];
+ else
+ number = [OFNumber numberWithUnsignedLongLong:
+ [string unsignedLongLongValueWithBase: 0]];
+ } @finally {
+ [string release];
+ }
+
+ return number;
+}
+
+static id
+nextObject(const char **pointer, const char *stop, size_t *line,
+ size_t depthLimit)
+{
+ skipWhitespacesAndComments(pointer, stop, line);
+
+ if (*pointer >= stop)
+ return nil;
+
+ switch (**pointer) {
+ case '"':
+ case '\'':
+ return parseString(pointer, stop, line);
+ case '[':
+ return parseArray(pointer, stop, line, depthLimit);
+ case '{':
+ return parseDictionary(pointer, stop, line, depthLimit);
+ case 't':
+ if (*pointer + 3 >= stop)
+ return nil;
+
+ if (memcmp(*pointer, "true", 4) != 0)
+ return nil;
+
+ (*pointer) += 4;
+
+ return [OFNumber numberWithBool: true];
+ case 'f':
+ if (*pointer + 4 >= stop)
+ return nil;
+
+ if (memcmp(*pointer, "false", 5) != 0)
+ return nil;
+
+ (*pointer) += 5;
+
+ return [OFNumber numberWithBool: false];
+ case 'n':
+ if (*pointer + 3 >= stop)
+ return nil;
+
+ if (memcmp(*pointer, "null", 4) != 0)
+ return nil;
+
+ (*pointer) += 4;
+
+ return [OFNull null];
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '+':
+ case '-':
+ case '.':
+ case 'I':
+ return parseNumber(pointer, stop, line);
+ default:
+ return nil;
+ }
+}
+
+@implementation OFString (JSONParsing)
+- (id)objectByParsingJSON
+{
+ return [self objectByParsingJSONWithDepthLimit: 32];
+}
+
+- (id)objectByParsingJSONWithDepthLimit: (size_t)depthLimit
+{
+ void *pool = objc_autoreleasePoolPush();
+ const char *pointer = self.UTF8String;
+ const char *stop = pointer + self.UTF8StringLength;
+ id object;
+ size_t line = 1;
+
+#ifdef __clang_analyzer__
+ assert(pointer != NULL);
+#endif
+
+ object = nextObject(&pointer, stop, &line, depthLimit);
+ skipWhitespacesAndComments(&pointer, stop, &line);
+
+ if (pointer < stop || object == nil)
+ @throw [OFInvalidJSONException exceptionWithString: self
+ line: line];
+
+ [object retain];
+
+ objc_autoreleasePoolPop(pool);
+
+ return [object autorelease];
+}
+@end
DELETED src/OFString+JSONValue.h
Index: src/OFString+JSONValue.h
==================================================================
--- src/OFString+JSONValue.h
+++ src/OFString+JSONValue.h
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
- * 2018, 2019, 2020
- * Jonathan Schleifer
- *
- * All rights reserved.
- *
- * This file is part of ObjFW. It may be distributed under the terms of the
- * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
- * the packaging of this file.
- *
- * Alternatively, it may be distributed under the terms of the GNU General
- * Public License, either version 2 or 3, which can be found in the file
- * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
- * file.
- */
-
-#import "OFString.h"
-
-OF_ASSUME_NONNULL_BEGIN
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern int _OFString_JSONValue_reference;
-#ifdef __cplusplus
-}
-#endif
-
-@interface OFString (JSONValue)
-/*!
- * @brief The string interpreted as JSON and parsed as an object.
- *
- * @note This also allows parsing JSON5, an extension of JSON. See
- * http://json5.org/ for more details.
- *
- * @warning Although not specified by the JSON specification, this can also
- * return primitives like strings and numbers. The rationale behind
- * this is that most JSON parsers allow JSON data just consisting of a
- * single primitive, leading to real world JSON files sometimes only
- * consisting of a single primitive. Therefore, you should not make any
- * assumptions about the object returned by this method if you don't
- * want your program to terminate due to a message not understood, but
- * instead check the returned object using @ref isKindOfClass:.
- */
-@property (readonly, nonatomic) id JSONValue;
-
-/*!
- * @brief Creates an object from the JSON value of the string.
- *
- * @note This also allows parsing JSON5, an extension of JSON. See
- * http://json5.org/ for more details.
- *
- * @warning Although not specified by the JSON specification, this can also
- * return primitives like strings and numbers. The rationale behind
- * this is that most JSON parsers allow JSON data just consisting of a
- * single primitive, leading to real world JSON files sometimes only
- * consisting of a single primitive. Therefore, you should not make any
- * assumptions about the object returned by this method if you don't
- * want your program to terminate due to a message not understood, but
- * instead check the returned object using @ref isKindOfClass:.
- *
- * @param depthLimit The maximum depth the parser should accept (defaults to 32
- * if not specified, 0 means no limit (insecure!))
- *
- * @return An object
- */
-- (id)JSONValueWithDepthLimit: (size_t)depthLimit;
-@end
-
-OF_ASSUME_NONNULL_END
DELETED src/OFString+JSONValue.m
Index: src/OFString+JSONValue.m
==================================================================
--- src/OFString+JSONValue.m
+++ src/OFString+JSONValue.m
@@ -1,675 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
- * 2018, 2019, 2020
- * Jonathan Schleifer
- *
- * All rights reserved.
- *
- * This file is part of ObjFW. It may be distributed under the terms of the
- * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
- * the packaging of this file.
- *
- * Alternatively, it may be distributed under the terms of the GNU General
- * Public License, either version 2 or 3, which can be found in the file
- * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
- * file.
- */
-
-#include "config.h"
-
-#include
-#include
-
-#include
-
-#include
-
-#import "OFString+JSONValue.h"
-#import "OFArray.h"
-#import "OFDictionary.h"
-#import "OFNumber.h"
-#import "OFNull.h"
-
-#import "OFInvalidJSONException.h"
-
-int _OFString_JSONValue_reference;
-
-static id nextObject(const char **pointer, const char *stop, size_t *line,
- size_t depthLimit);
-
-static void
-skipWhitespaces(const char **pointer, const char *stop, size_t *line)
-{
- while (*pointer < stop && (**pointer == ' ' || **pointer == '\t' ||
- **pointer == '\r' || **pointer == '\n')) {
- if (**pointer == '\n')
- (*line)++;
-
- (*pointer)++;
- }
-}
-
-static void
-skipComment(const char **pointer, const char *stop, size_t *line)
-{
- if (**pointer != '/')
- return;
-
- if (*pointer + 1 >= stop)
- return;
-
- (*pointer)++;
-
- if (**pointer == '*') {
- bool lastIsAsterisk = false;
-
- (*pointer)++;
-
- while (*pointer < stop) {
- if (lastIsAsterisk && **pointer == '/') {
- (*pointer)++;
- return;
- }
-
- lastIsAsterisk = (**pointer == '*');
-
- if (**pointer == '\n')
- (*line)++;
-
- (*pointer)++;
- }
- } else if (**pointer == '/') {
- (*pointer)++;
-
- while (*pointer < stop) {
- if (**pointer == '\r' || **pointer == '\n') {
- (*pointer)++;
- (*line)++;
- return;
- }
-
- (*pointer)++;
- }
- } else
- (*pointer)--;
-}
-
-static void
-skipWhitespacesAndComments(const char **pointer, const char *stop, size_t *line)
-{
- const char *old = NULL;
-
- while (old != *pointer) {
- old = *pointer;
-
- skipWhitespaces(pointer, stop, line);
- skipComment(pointer, stop, line);
- }
-}
-
-static inline of_char16_t
-parseUnicodeEscape(const char *pointer, const char *stop)
-{
- of_char16_t ret = 0;
-
- if (pointer + 5 >= stop)
- return 0xFFFF;
-
- if (pointer[0] != '\\' || pointer[1] != 'u')
- return 0xFFFF;
-
- for (uint8_t i = 0; i < 4; i++) {
- char c = pointer[i + 2];
- ret <<= 4;
-
- if (c >= '0' && c <= '9')
- ret |= c - '0';
- else if (c >= 'a' && c <= 'f')
- ret |= c + 10 - 'a';
- else if (c >= 'A' && c <= 'F')
- ret |= c + 10 - 'A';
- else
- return 0xFFFF;
- }
-
- if (ret == 0)
- return 0xFFFF;
-
- return ret;
-}
-
-static inline OFString *
-parseString(const char **pointer, const char *stop, size_t *line)
-{
- char *buffer;
- size_t i = 0;
- char delimiter = **pointer;
-
- if (++(*pointer) + 1 >= stop)
- return nil;
-
- if ((buffer = malloc(stop - *pointer)) == NULL)
- return nil;
-
- while (*pointer < stop) {
- /* Parse escape codes */
- if (**pointer == '\\') {
- if (++(*pointer) >= stop) {
- free(buffer);
- return nil;
- }
-
- switch (**pointer) {
- case '"':
- case '\\':
- case '/':
- buffer[i++] = **pointer;
- (*pointer)++;
- break;
- case 'b':
- buffer[i++] = '\b';
- (*pointer)++;
- break;
- case 'f':
- buffer[i++] = '\f';
- (*pointer)++;
- break;
- case 'n':
- buffer[i++] = '\n';
- (*pointer)++;
- break;
- case 'r':
- buffer[i++] = '\r';
- (*pointer)++;
- break;
- case 't':
- buffer[i++] = '\t';
- (*pointer)++;
- break;
- /* Parse Unicode escape sequence */
- case 'u':;
- of_char16_t c1, c2;
- of_unichar_t c;
- size_t l;
-
- c1 = parseUnicodeEscape(*pointer - 1, stop);
- if (c1 == 0xFFFF) {
- free(buffer);
- return nil;
- }
-
- /* Low surrogate */
- if ((c1 & 0xFC00) == 0xDC00) {
- free(buffer);
- return nil;
- }
-
- /* Normal character */
- if ((c1 & 0xFC00) != 0xD800) {
- l = of_string_utf8_encode(c1,
- buffer + i);
- if (l == 0) {
- free(buffer);
- return nil;
- }
-
- i += l;
- *pointer += 5;
-
- break;
- }
-
- /*
- * If we are still here, we only got one UTF-16
- * surrogate and now need to get the other one
- * in order to produce UTF-8 and not CESU-8.
- */
- c2 = parseUnicodeEscape(*pointer + 5, stop);
- if (c2 == 0xFFFF) {
- free(buffer);
- return nil;
- }
-
- c = (((c1 & 0x3FF) << 10) |
- (c2 & 0x3FF)) + 0x10000;
-
- l = of_string_utf8_encode(c, buffer + i);
- if (l == 0) {
- free(buffer);
- return nil;
- }
-
- i += l;
- *pointer += 11;
-
- break;
- case '\r':
- (*pointer)++;
-
- if (*pointer < stop && **pointer == '\n') {
- (*pointer)++;
- (*line)++;
- }
-
- break;
- case '\n':
- (*pointer)++;
- (*line)++;
- break;
- default:
- free(buffer);
- return nil;
- }
- /* End of string found */
- } else if (**pointer == delimiter) {
- OFString *ret;
-
- @try {
- ret = [OFString stringWithUTF8String: buffer
- length: i];
- } @finally {
- free(buffer);
- }
-
- (*pointer)++;
-
- return ret;
- /* Newlines in strings are disallowed */
- } else if (**pointer == '\n' || **pointer == '\r') {
- (*line)++;
- free(buffer);
- return nil;
- } else {
- buffer[i++] = **pointer;
- (*pointer)++;
- }
- }
-
- free(buffer);
- return nil;
-}
-
-static inline OFString *
-parseIdentifier(const char **pointer, const char *stop)
-{
- char *buffer;
- size_t i = 0;
-
- if ((buffer = malloc(stop - *pointer)) == NULL)
- return nil;
-
- while (*pointer < stop) {
- if ((**pointer >= 'a' && **pointer <= 'z') ||
- (**pointer >= 'A' && **pointer <= 'Z') ||
- (**pointer >= '0' && **pointer <= '9') ||
- **pointer == '_' || **pointer == '$' ||
- (**pointer & 0x80)) {
- buffer[i++] = **pointer;
- (*pointer)++;
- } else if (**pointer == '\\') {
- of_char16_t c1, c2;
- of_unichar_t c;
- size_t l;
-
- if (++(*pointer) >= stop || **pointer != 'u') {
- free(buffer);
- return nil;
- }
-
- c1 = parseUnicodeEscape(*pointer - 1, stop);
- if (c1 == 0xFFFF) {
- free(buffer);
- return nil;
- }
-
- /* Low surrogate */
- if ((c1 & 0xFC00) == 0xDC00) {
- free(buffer);
- return nil;
- }
-
- /* Normal character */
- if ((c1 & 0xFC00) != 0xD800) {
- l = of_string_utf8_encode(c1, buffer + i);
- if (l == 0) {
- free(buffer);
- return nil;
- }
-
- i += l;
- *pointer += 5;
-
- continue;
- }
-
- /*
- * If we are still here, we only got one UTF-16
- * surrogate and now need to get the other one in order
- * to produce UTF-8 and not CESU-8.
- */
- c2 = parseUnicodeEscape(*pointer + 5, stop);
- if (c2 == 0xFFFF) {
- free(buffer);
- return nil;
- }
-
- c = (((c1 & 0x3FF) << 10) | (c2 & 0x3FF)) + 0x10000;
-
- l = of_string_utf8_encode(c, buffer + i);
- if (l == 0) {
- free(buffer);
- return nil;
- }
-
- i += l;
- *pointer += 11;
- } else {
- OFString *ret;
-
- if (i == 0 || (buffer[0] >= '0' && buffer[0] <= '9')) {
- free(buffer);
- return nil;
- }
-
- @try {
- ret = [OFString stringWithUTF8String: buffer
- length: i];
- } @finally {
- free(buffer);
- }
-
- return ret;
- }
- }
-
- /*
- * It is never possible to end with an identifier, thus we should never
- * reach stop.
- */
- return nil;
-}
-
-static inline OFMutableArray *
-parseArray(const char **pointer, const char *stop, size_t *line,
- size_t depthLimit)
-{
- OFMutableArray *array = [OFMutableArray array];
-
- if (++(*pointer) >= stop)
- return nil;
-
- if (--depthLimit == 0)
- return nil;
-
- while (**pointer != ']') {
- id object;
-
- skipWhitespacesAndComments(pointer, stop, line);
- if (*pointer >= stop)
- return nil;
-
- if (**pointer == ']')
- break;
-
- if (**pointer == ',') {
- (*pointer)++;
- skipWhitespacesAndComments(pointer, stop, line);
-
- if (*pointer >= stop || **pointer != ']')
- return nil;
-
- break;
- }
-
- object = nextObject(pointer, stop, line, depthLimit);
- if (object == nil)
- return nil;
-
- [array addObject: object];
-
- skipWhitespacesAndComments(pointer, stop, line);
- if (*pointer >= stop)
- return nil;
-
- if (**pointer == ',') {
- (*pointer)++;
- skipWhitespacesAndComments(pointer, stop, line);
-
- if (*pointer >= stop)
- return nil;
- } else if (**pointer != ']')
- return nil;
- }
-
- (*pointer)++;
-
- return array;
-}
-
-static inline OFMutableDictionary *
-parseDictionary(const char **pointer, const char *stop, size_t *line,
- size_t depthLimit)
-{
- OFMutableDictionary *dictionary = [OFMutableDictionary dictionary];
-
- if (++(*pointer) >= stop)
- return nil;
-
- if (--depthLimit == 0)
- return nil;
-
- while (**pointer != '}') {
- OFString *key;
- id object;
-
- skipWhitespacesAndComments(pointer, stop, line);
- if (*pointer >= stop)
- return nil;
-
- if (**pointer == '}')
- break;
-
- if (**pointer == ',') {
- (*pointer)++;
- skipWhitespacesAndComments(pointer, stop, line);
-
- if (*pointer >= stop || **pointer != '}')
- return nil;
-
- break;
- }
-
- skipWhitespacesAndComments(pointer, stop, line);
- if (*pointer + 1 >= stop)
- return nil;
-
- if ((**pointer >= 'a' && **pointer <= 'z') ||
- (**pointer >= 'A' && **pointer <= 'Z') ||
- **pointer == '_' || **pointer == '$' || **pointer == '\\')
- key = parseIdentifier(pointer, stop);
- else
- key = nextObject(pointer, stop, line, depthLimit);
-
- if (![key isKindOfClass: [OFString class]])
- return nil;
-
- skipWhitespacesAndComments(pointer, stop, line);
- if (*pointer + 1 >= stop || **pointer != ':')
- return nil;
-
- (*pointer)++;
-
- object = nextObject(pointer, stop, line, depthLimit);
- if (object == nil)
- return nil;
-
- [dictionary setObject: object
- forKey: key];
-
- skipWhitespacesAndComments(pointer, stop, line);
- if (*pointer >= stop)
- return nil;
-
- if (**pointer == ',') {
- (*pointer)++;
- skipWhitespacesAndComments(pointer, stop, line);
-
- if (*pointer >= stop)
- return nil;
- } else if (**pointer != '}')
- return nil;
- }
-
- (*pointer)++;
-
- return dictionary;
-}
-
-static inline OFNumber *
-parseNumber(const char **pointer, const char *stop, size_t *line)
-{
- bool isHex = (*pointer + 1 < stop && (*pointer)[1] == 'x');
- bool hasDecimal = false;
- size_t i;
- OFString *string;
- OFNumber *number;
-
- for (i = 0; *pointer + i < stop; i++) {
- if ((*pointer)[i] == '.')
- hasDecimal = true;
-
- if ((*pointer)[i] == ' ' || (*pointer)[i] == '\t' ||
- (*pointer)[i] == '\r' || (*pointer)[i] == '\n' ||
- (*pointer)[i] == ',' || (*pointer)[i] == ']' ||
- (*pointer)[i] == '}') {
- if ((*pointer)[i] == '\n')
- (*line)++;
-
- break;
- }
- }
-
- string = [[OFString alloc] initWithUTF8String: *pointer
- length: i];
- *pointer += i;
-
- @try {
- if (hasDecimal)
- number = [OFNumber numberWithDouble:
- string.doubleValue];
- else if (isHex)
- number = [OFNumber numberWithIntMax:
- string.hexadecimalValue];
- else if ([string isEqual: @"Infinity"])
- number = [OFNumber numberWithDouble: INFINITY];
- else if ([string isEqual: @"-Infinity"])
- number = [OFNumber numberWithDouble: -INFINITY];
- else
- number = [OFNumber numberWithIntMax:
- string.decimalValue];
- } @finally {
- [string release];
- }
-
- return number;
-}
-
-static id
-nextObject(const char **pointer, const char *stop, size_t *line,
- size_t depthLimit)
-{
- skipWhitespacesAndComments(pointer, stop, line);
-
- if (*pointer >= stop)
- return nil;
-
- switch (**pointer) {
- case '"':
- case '\'':
- return parseString(pointer, stop, line);
- case '[':
- return parseArray(pointer, stop, line, depthLimit);
- case '{':
- return parseDictionary(pointer, stop, line, depthLimit);
- case 't':
- if (*pointer + 3 >= stop)
- return nil;
-
- if (memcmp(*pointer, "true", 4) != 0)
- return nil;
-
- (*pointer) += 4;
-
- return [OFNumber numberWithBool: true];
- case 'f':
- if (*pointer + 4 >= stop)
- return nil;
-
- if (memcmp(*pointer, "false", 5) != 0)
- return nil;
-
- (*pointer) += 5;
-
- return [OFNumber numberWithBool: false];
- case 'n':
- if (*pointer + 3 >= stop)
- return nil;
-
- if (memcmp(*pointer, "null", 4) != 0)
- return nil;
-
- (*pointer) += 4;
-
- return [OFNull null];
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '+':
- case '-':
- case '.':
- case 'I':
- return parseNumber(pointer, stop, line);
- default:
- return nil;
- }
-}
-
-@implementation OFString (JSONValue)
-- (id)JSONValue
-{
- return [self JSONValueWithDepthLimit: 32];
-}
-
-- (id)JSONValueWithDepthLimit: (size_t)depthLimit
-{
- void *pool = objc_autoreleasePoolPush();
- const char *pointer = self.UTF8String;
- const char *stop = pointer + self.UTF8StringLength;
- id object;
- size_t line = 1;
-
-#ifdef __clang_analyzer__
- assert(pointer != NULL);
-#endif
-
- object = nextObject(&pointer, stop, &line, depthLimit);
- skipWhitespacesAndComments(&pointer, stop, &line);
-
- if (pointer < stop || object == nil)
- @throw [OFInvalidJSONException exceptionWithString: self
- line: line];
-
- [object retain];
-
- objc_autoreleasePoolPop(pool);
-
- return [object autorelease];
-}
-@end
ADDED src/OFString+PropertyListParsing.h
Index: src/OFString+PropertyListParsing.h
==================================================================
--- src/OFString+PropertyListParsing.h
+++ src/OFString+PropertyListParsing.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019, 2020
+ * Jonathan Schleifer
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#import "OFString.h"
+
+OF_ASSUME_NONNULL_BEGIN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int _OFString_PropertyListParsing_reference;
+#ifdef __cplusplus
+}
+#endif
+
+@interface OFString (PropertyListParsing)
+/*!
+ * @brief The string interpreted as a property list and parsed as an object.
+ *
+ * @note This only supports XML property lists!
+ */
+@property (readonly, nonatomic) id objectByParsingPropertyList;
+@end
+
+OF_ASSUME_NONNULL_END
ADDED src/OFString+PropertyListParsing.m
Index: src/OFString+PropertyListParsing.m
==================================================================
--- src/OFString+PropertyListParsing.m
+++ src/OFString+PropertyListParsing.m
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019, 2020
+ * Jonathan Schleifer
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#include "config.h"
+
+#import "OFString+PropertyListParsing.h"
+#import "OFArray.h"
+#import "OFData.h"
+#import "OFDate.h"
+#import "OFDictionary.h"
+#import "OFNumber.h"
+#import "OFXMLAttribute.h"
+#import "OFXMLElement.h"
+
+#import "OFInvalidFormatException.h"
+#import "OFUnsupportedVersionException.h"
+
+int _OFString_PropertyListParsing_reference;
+
+static id parseElement(OFXMLElement *element);
+
+static OFArray *
+parseArrayElement(OFXMLElement *element)
+{
+ OFMutableArray *ret = [OFMutableArray array];
+ void *pool = objc_autoreleasePoolPush();
+
+ for (OFXMLElement *child in element.elements)
+ [ret addObject: parseElement(child)];
+
+ [ret makeImmutable];
+
+ objc_autoreleasePoolPop(pool);
+
+ return ret;
+}
+
+static OFDictionary *
+parseDictElement(OFXMLElement *element)
+{
+ OFMutableDictionary *ret = [OFMutableDictionary dictionary];
+ void *pool = objc_autoreleasePoolPush();
+ OFArray OF_GENERIC(OFXMLElement *) *children = element.elements;
+ OFEnumerator OF_GENERIC(OFXMLElement *) *enumerator;
+ OFXMLElement *key, *object;
+
+ if (children.count % 2 != 0)
+ @throw [OFInvalidFormatException exception];
+
+ enumerator = [children objectEnumerator];
+ while ((key = [enumerator nextObject]) &&
+ (object = [enumerator nextObject])) {
+ if (key.namespace != nil || key.attributes.count != 0 ||
+ ![key.name isEqual: @"key"])
+ @throw [OFInvalidFormatException exception];
+
+ [ret setObject: parseElement(object)
+ forKey: key.stringValue];
+ }
+
+ [ret makeImmutable];
+
+ objc_autoreleasePoolPop(pool);
+
+ return ret;
+}
+
+static OFString *
+parseStringElement(OFXMLElement *element)
+{
+ return element.stringValue;
+}
+
+static OFData *
+parseDataElement(OFXMLElement *element)
+{
+ return [OFData dataWithBase64EncodedString: element.stringValue];
+}
+
+static OFDate *
+parseDateElement(OFXMLElement *element)
+{
+ return [OFDate dateWithDateString: element.stringValue
+ format: @"%Y-%m-%dT%H:%M:%SZ"];
+}
+
+static OFNumber *
+parseTrueElement(OFXMLElement *element)
+{
+ if (element.children.count != 0)
+ @throw [OFInvalidFormatException exception];
+
+ return [OFNumber numberWithBool: true];
+}
+
+static OFNumber *
+parseFalseElement(OFXMLElement *element)
+{
+ if (element.children.count != 0)
+ @throw [OFInvalidFormatException exception];
+
+ return [OFNumber numberWithBool: false];
+}
+
+static OFNumber *
+parseRealElement(OFXMLElement *element)
+{
+ return [OFNumber numberWithDouble: element.doubleValue];
+}
+
+static OFNumber *
+parseIntegerElement(OFXMLElement *element)
+{
+ void *pool = objc_autoreleasePoolPush();
+ OFString *stringValue;
+ OFNumber *ret;
+
+ stringValue = element.stringValue.stringByDeletingEnclosingWhitespaces;
+
+ if ([stringValue hasPrefix: @"-"])
+ ret = [OFNumber numberWithLongLong: stringValue.longLongValue];
+ else
+ ret = [OFNumber numberWithUnsignedLongLong:
+ stringValue.unsignedLongLongValue];
+
+ [ret retain];
+
+ objc_autoreleasePoolPop(pool);
+
+ return [ret autorelease];
+}
+
+static id
+parseElement(OFXMLElement *element)
+{
+ OFString *elementName;
+
+ if (element.namespace != nil || element.attributes.count != 0)
+ @throw [OFInvalidFormatException exception];
+
+ elementName = element.name;
+
+ if ([elementName isEqual: @"array"])
+ return parseArrayElement(element);
+ else if ([elementName isEqual: @"dict"])
+ return parseDictElement(element);
+ else if ([elementName isEqual: @"string"])
+ return parseStringElement(element);
+ else if ([elementName isEqual: @"data"])
+ return parseDataElement(element);
+ else if ([elementName isEqual: @"date"])
+ return parseDateElement(element);
+ else if ([elementName isEqual: @"true"])
+ return parseTrueElement(element);
+ else if ([elementName isEqual: @"false"])
+ return parseFalseElement(element);
+ else if ([elementName isEqual: @"real"])
+ return parseRealElement(element);
+ else if ([elementName isEqual: @"integer"])
+ return parseIntegerElement(element);
+ else
+ @throw [OFInvalidFormatException exception];
+}
+
+@implementation OFString (PropertyListParsing)
+- (id)objectByParsingPropertyList
+{
+ void *pool = objc_autoreleasePoolPush();
+ OFXMLElement *rootElement = [OFXMLElement elementWithXMLString: self];
+ OFXMLAttribute *versionAttribute;
+ OFArray OF_GENERIC(OFXMLElement *) *elements;
+ id ret;
+
+ if (![rootElement.name isEqual: @"plist"] ||
+ rootElement.namespace != nil)
+ @throw [OFInvalidFormatException exception];
+
+ versionAttribute = [rootElement attributeForName: @"version"];
+
+ if (versionAttribute == nil)
+ @throw [OFInvalidFormatException exception];
+
+ if (![versionAttribute.stringValue isEqual: @"1.0"])
+ @throw [OFUnsupportedVersionException
+ exceptionWithVersion: [versionAttribute stringValue]];
+
+ elements = rootElement.elements;
+
+ if (elements.count != 1)
+ @throw [OFInvalidFormatException exception];
+
+ ret = parseElement(elements.firstObject);
+
+ [ret retain];
+ objc_autoreleasePoolPop(pool);
+ return [ret autorelease];
+}
+@end
DELETED src/OFString+PropertyListValue.h
Index: src/OFString+PropertyListValue.h
==================================================================
--- src/OFString+PropertyListValue.h
+++ src/OFString+PropertyListValue.h
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
- * 2018, 2019, 2020
- * Jonathan Schleifer
- *
- * All rights reserved.
- *
- * This file is part of ObjFW. It may be distributed under the terms of the
- * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
- * the packaging of this file.
- *
- * Alternatively, it may be distributed under the terms of the GNU General
- * Public License, either version 2 or 3, which can be found in the file
- * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
- * file.
- */
-
-#import "OFString.h"
-
-OF_ASSUME_NONNULL_BEGIN
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern int _OFString_PropertyListValue_reference;
-#ifdef __cplusplus
-}
-#endif
-
-@interface OFString (PropertyListValue)
-/*!
- * @brief The string interpreted as a property list and parsed as an object.
- *
- * @note This only supports XML property lists!
- */
-@property (readonly, nonatomic) id propertyListValue;
-@end
-
-OF_ASSUME_NONNULL_END
DELETED src/OFString+PropertyListValue.m
Index: src/OFString+PropertyListValue.m
==================================================================
--- src/OFString+PropertyListValue.m
+++ src/OFString+PropertyListValue.m
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
- * 2018, 2019, 2020
- * Jonathan Schleifer
- *
- * All rights reserved.
- *
- * This file is part of ObjFW. It may be distributed under the terms of the
- * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
- * the packaging of this file.
- *
- * Alternatively, it may be distributed under the terms of the GNU General
- * Public License, either version 2 or 3, which can be found in the file
- * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
- * file.
- */
-
-#include "config.h"
-
-#import "OFString+PropertyListValue.h"
-#import "OFArray.h"
-#import "OFData.h"
-#import "OFDate.h"
-#import "OFDictionary.h"
-#import "OFNumber.h"
-#import "OFXMLAttribute.h"
-#import "OFXMLElement.h"
-
-#import "OFInvalidFormatException.h"
-#import "OFUnsupportedVersionException.h"
-
-int _OFString_PropertyListValue_reference;
-
-static id parseElement(OFXMLElement *element);
-
-static OFArray *
-parseArrayElement(OFXMLElement *element)
-{
- OFMutableArray *ret = [OFMutableArray array];
- void *pool = objc_autoreleasePoolPush();
-
- for (OFXMLElement *child in element.elements)
- [ret addObject: parseElement(child)];
-
- [ret makeImmutable];
-
- objc_autoreleasePoolPop(pool);
-
- return ret;
-}
-
-static OFDictionary *
-parseDictElement(OFXMLElement *element)
-{
- OFMutableDictionary *ret = [OFMutableDictionary dictionary];
- void *pool = objc_autoreleasePoolPush();
- OFArray OF_GENERIC(OFXMLElement *) *children = element.elements;
- OFEnumerator OF_GENERIC(OFXMLElement *) *enumerator;
- OFXMLElement *key, *object;
-
- if (children.count % 2 != 0)
- @throw [OFInvalidFormatException exception];
-
- enumerator = [children objectEnumerator];
- while ((key = [enumerator nextObject]) &&
- (object = [enumerator nextObject])) {
- if (key.namespace != nil || key.attributes.count != 0 ||
- ![key.name isEqual: @"key"])
- @throw [OFInvalidFormatException exception];
-
- [ret setObject: parseElement(object)
- forKey: key.stringValue];
- }
-
- [ret makeImmutable];
-
- objc_autoreleasePoolPop(pool);
-
- return ret;
-}
-
-static OFString *
-parseStringElement(OFXMLElement *element)
-{
- return element.stringValue;
-}
-
-static OFData *
-parseDataElement(OFXMLElement *element)
-{
- return [OFData dataWithBase64EncodedString: element.stringValue];
-}
-
-static OFDate *
-parseDateElement(OFXMLElement *element)
-{
- return [OFDate dateWithDateString: element.stringValue
- format: @"%Y-%m-%dT%H:%M:%SZ"];
-}
-
-static OFNumber *
-parseTrueElement(OFXMLElement *element)
-{
- if (element.children.count != 0)
- @throw [OFInvalidFormatException exception];
-
- return [OFNumber numberWithBool: true];
-}
-
-static OFNumber *
-parseFalseElement(OFXMLElement *element)
-{
- if (element.children.count != 0)
- @throw [OFInvalidFormatException exception];
-
- return [OFNumber numberWithBool: false];
-}
-
-static OFNumber *
-parseRealElement(OFXMLElement *element)
-{
- return [OFNumber numberWithDouble: element.doubleValue];
-}
-
-static OFNumber *
-parseIntegerElement(OFXMLElement *element)
-{
- return [OFNumber numberWithIntMax: element.decimalValue];
-}
-
-static id
-parseElement(OFXMLElement *element)
-{
- OFString *elementName;
-
- if (element.namespace != nil || element.attributes.count != 0)
- @throw [OFInvalidFormatException exception];
-
- elementName = element.name;
-
- if ([elementName isEqual: @"array"])
- return parseArrayElement(element);
- else if ([elementName isEqual: @"dict"])
- return parseDictElement(element);
- else if ([elementName isEqual: @"string"])
- return parseStringElement(element);
- else if ([elementName isEqual: @"data"])
- return parseDataElement(element);
- else if ([elementName isEqual: @"date"])
- return parseDateElement(element);
- else if ([elementName isEqual: @"true"])
- return parseTrueElement(element);
- else if ([elementName isEqual: @"false"])
- return parseFalseElement(element);
- else if ([elementName isEqual: @"real"])
- return parseRealElement(element);
- else if ([elementName isEqual: @"integer"])
- return parseIntegerElement(element);
- else
- @throw [OFInvalidFormatException exception];
-}
-
-@implementation OFString (PropertyListValue)
-- (id)propertyListValue
-{
- void *pool = objc_autoreleasePoolPush();
- OFXMLElement *rootElement = [OFXMLElement elementWithXMLString: self];
- OFXMLAttribute *versionAttribute;
- OFArray OF_GENERIC(OFXMLElement *) *elements;
- id ret;
-
- if (![rootElement.name isEqual: @"plist"] ||
- rootElement.namespace != nil)
- @throw [OFInvalidFormatException exception];
-
- versionAttribute = [rootElement attributeForName: @"version"];
-
- if (versionAttribute == nil)
- @throw [OFInvalidFormatException exception];
-
- if (![versionAttribute.stringValue isEqual: @"1.0"])
- @throw [OFUnsupportedVersionException
- exceptionWithVersion: [versionAttribute stringValue]];
-
- elements = rootElement.elements;
-
- if (elements.count != 1)
- @throw [OFInvalidFormatException exception];
-
- ret = parseElement(elements.firstObject);
-
- [ret retain];
- objc_autoreleasePoolPop(pool);
- return [ret autorelease];
-}
-@end
Index: src/OFString+Serialization.m
==================================================================
--- src/OFString+Serialization.m
+++ src/OFString+Serialization.m
@@ -50,11 +50,11 @@
version = [root attributeForName: @"version"].stringValue;
if (version == nil)
@throw [OFInvalidArgumentException exception];
- if (version.decimalValue != 1)
+ if (version.unsignedLongLongValue != 1)
@throw [OFUnsupportedVersionException
exceptionWithVersion: version];
elements = [root elementsForNamespace: OF_SERIALIZATION_NS];
Index: src/OFString.h
==================================================================
--- src/OFString.h
+++ src/OFString.h
@@ -169,47 +169,34 @@
* specified by Unicode!
*/
@property (readonly, nonatomic) OFString *capitalizedString;
/*!
- * @brief The decimal value of the string as an `intmax_t`.
+ * @brief The decimal value of the string as a `long long`.
*
* Leading and trailing whitespaces are ignored.
*
* If the string contains any non-number characters, an
* @ref OFInvalidFormatException is thrown.
*
- * If the number is too big to fit into an `intmax_t`, an
+ * If the number is too big to fit into a `long long`, an
* @ref OFOutOfRangeException is thrown.
*/
-@property (readonly, nonatomic) intmax_t decimalValue;
+@property (readonly, nonatomic) long long longLongValue;
/*!
- * @brief The hexadecimal value of the string as an `uintmax_t`.
+ * @brief The decimal value of the string as an `unsigned long long`.
*
* Leading and trailing whitespaces are ignored.
*
* If the string contains any non-number characters, an
* @ref OFInvalidFormatException is thrown.
*
- * If the number is too big to fit into an `uintmax_t`, an
- * @ref OFOutOfRangeException is thrown.
- */
-@property (readonly, nonatomic) uintmax_t hexadecimalValue;
-
-/*!
- * @brief The octal value of the string as an `uintmax_t`.
- *
- * Leading and trailing whitespaces are ignored.
- *
- * If the string contains any non-number characters, an
- * @ref OFInvalidFormatException is thrown.
- *
- * If the number is too big to fit into an `uintmax_t`, an
- * @ref OFOutOfRangeException is thrown.
- */
-@property (readonly, nonatomic) uintmax_t octalValue;
+ * If the number is too big to fit into an `unsigned long long`, an
+ * @ref OFOutOfRangeException is thrown.
+ */
+@property (readonly, nonatomic) unsigned long long unsignedLongLongValue;
/*!
* @brief The float value of the string as a float.
*
* If the string contains any non-number characters, an
@@ -1023,10 +1010,49 @@
* @param range The range of the substring
* @return The substring as a new autoreleased OFString
*/
- (OFString *)substringWithRange: (of_range_t)range;
+/*!
+ * @brief The value of the string in the specified base as a `long long`.
+ *
+ * Leading and trailing whitespaces are ignored.
+ *
+ * If the string contains any non-number characters, an
+ * @ref OFInvalidFormatException is thrown.
+ *
+ * If the number is too big to fit into a `long long`, an
+ * @ref OFOutOfRangeException is thrown.
+ *
+ * @param base The base to use. If the base is 0, base 16 is assumed if the
+ * string starts with 0x (after stripping white spaces). If the
+ * string starts with 0, base 8 is assumed. Otherwise, base 10 is
+ * assumed.
+ * @return The value of the string in the specified base
+ */
+- (long long)longLongValueWithBase: (int)base;
+
+/*!
+ * @brief The value of the string in the specified base as an
+ * `unsigned long long`.
+ *
+ * Leading and trailing whitespaces are ignored.
+ *
+ * If the string contains any non-number characters, an
+ * @ref OFInvalidFormatException is thrown.
+ *
+ * If the number is too big to fit into an `unsigned long long`, an
+ * @ref OFOutOfRangeException is thrown.
+ *
+ * @param base The base to use. If the base is 0, base 16 is assumed if the
+ * string starts with 0x (after stripping white spaces). If the
+ * string starts with 0, base 8 is assumed. Otherwise, base 10 is
+ * assumed.
+ * @return The value of the string in the specified base
+ */
+- (unsigned long long)unsignedLongLongValueWithBase: (int)base;
+
/*!
* @brief Creates a new string by appending another string.
*
* @param string The string to append
* @return A new, autoreleased OFString with the specified string appended
@@ -1252,15 +1278,15 @@
#include "OFConstantString.h"
#include "OFMutableString.h"
#ifdef __OBJC__
# import "OFString+CryptoHashing.h"
-# import "OFString+JSONValue.h"
+# import "OFString+JSONParsing.h"
# ifdef OF_HAVE_FILES
# import "OFString+PathAdditions.h"
# endif
-# import "OFString+PropertyListValue.h"
+# import "OFString+PropertyListParsing.h"
# import "OFString+Serialization.h"
# import "OFString+URLEncoding.h"
# import "OFString+XMLEscaping.h"
# import "OFString+XMLUnescaping.h"
#endif
Index: src/OFString.m
==================================================================
--- src/OFString.m
+++ src/OFString.m
@@ -15,10 +15,11 @@
* file.
*/
#include "config.h"
+#include
#include
#include
#include
#include
#include
@@ -124,15 +125,15 @@
/* References for static linking */
void
_references_to_categories_of_OFString(void)
{
_OFString_CryptoHashing_reference = 1;
- _OFString_JSONValue_reference = 1;
+ _OFString_JSONParsing_reference = 1;
#ifdef OF_HAVE_FILES
_OFString_PathAdditions_reference = 1;
#endif
- _OFString_PropertyListValue_reference = 1;
+ _OFString_PropertyListParsing_reference = 1;
_OFString_Serialization_reference = 1;
_OFString_URLEncoding_reference = 1;
_OFString_XMLEscaping_reference = 1;
_OFString_XMLUnescaping_reference = 1;
}
@@ -988,11 +989,11 @@
- (instancetype)initWithContentsOfFile: (OFString *)path
encoding: (of_string_encoding_t)encoding
{
char *tmp;
- uintmax_t fileSize;
+ unsigned long long fileSize;
@try {
void *pool = objc_autoreleasePoolPush();
OFFile *file = nil;
@@ -1006,11 +1007,11 @@
errNo: e.errNo];
}
objc_autoreleasePoolPop(pool);
-# if UINTMAX_MAX > SIZE_MAX
+# if ULLONG_MAX > SIZE_MAX
if (fileSize > SIZE_MAX)
@throw [OFOutOfRangeException exception];
#endif
/*
@@ -2311,183 +2312,88 @@
objc_autoreleasePoolPop(pool);
return array;
}
-- (intmax_t)decimalValue
+- (long long)longLongValue
+{
+ return [self longLongValueWithBase: 10];
+}
+
+- (long long)longLongValueWithBase: (int)base
{
void *pool = objc_autoreleasePoolPush();
- const of_unichar_t *characters = self.characters;
- size_t i = 0, length = self.length;
- intmax_t value = 0;
- bool expectWhitespace = false;
-
- while (length > 0 && of_ascii_isspace(*characters)) {
- characters++;
- length--;
- }
-
- if (length == 0) {
- objc_autoreleasePoolPop(pool);
- return 0;
- }
-
- if (characters[0] == '-' || characters[0] == '+')
- i++;
-
- for (; i < length; i++) {
- if (expectWhitespace) {
- if (of_ascii_isspace(characters[i]))
- continue;
-
- @throw [OFInvalidFormatException exception];
- }
-
- if (characters[i] >= '0' && characters[i] <= '9') {
- if (INTMAX_MAX / 10 < value ||
- INTMAX_MAX - value * 10 < characters[i] - '0')
- @throw [OFOutOfRangeException exception];
-
- value = (value * 10) + (characters[i] - '0');
- } else if (of_ascii_isspace(characters[i]))
- expectWhitespace = true;
- else
- @throw [OFInvalidFormatException exception];
- }
-
- if (characters[0] == '-')
- value *= -1;
+ const char *UTF8String = self.UTF8String;
+ char *endPointer = NULL;
+ long long value;
+
+ errno = 0;
+ value = strtoll(UTF8String, &endPointer, base);
+
+ if ((value == LLONG_MIN || value == LLONG_MAX) && errno == ERANGE)
+ @throw [OFOutOfRangeException exception];
+
+ /* Check if there are any invalid chars left */
+ if (endPointer != NULL)
+ for (; *endPointer != '\0'; endPointer++)
+ /* Use isspace since strtoll uses the same. */
+ if (!isspace((unsigned char)*endPointer))
+ @throw [OFInvalidFormatException exception];
objc_autoreleasePoolPop(pool);
return value;
}
-- (uintmax_t)hexadecimalValue
-{
- void *pool = objc_autoreleasePoolPush();
- const of_unichar_t *characters = self.characters;
- size_t i = 0, length = self.length;
- uintmax_t value = 0;
- bool expectWhitespace = false, foundValue = false;
-
- while (length > 0 && of_ascii_isspace(*characters)) {
- characters++;
- length--;
- }
-
- if (length == 0) {
- objc_autoreleasePoolPop(pool);
- return 0;
- }
-
- if (length >= 2 && characters[0] == '0' && characters[1] == 'x')
- i = 2;
- else if (length >= 1 && (characters[0] == 'x' || characters[0] == '$'))
- i = 1;
-
- for (; i < length; i++) {
- uintmax_t newValue;
-
- if (expectWhitespace) {
- if (of_ascii_isspace(characters[i]))
- continue;
-
- @throw [OFInvalidFormatException exception];
- }
-
- if (characters[i] >= '0' && characters[i] <= '9') {
- newValue = (value << 4) | (characters[i] - '0');
- foundValue = true;
- } else if (characters[i] >= 'A' && characters[i] <= 'F') {
- newValue = (value << 4) | (characters[i] - 'A' + 10);
- foundValue = true;
- } else if (characters[i] >= 'a' && characters[i] <= 'f') {
- newValue = (value << 4) | (characters[i] - 'a' + 10);
- foundValue = true;
- } else if (characters[i] == 'h' ||
- of_ascii_isspace(characters[i])) {
- expectWhitespace = true;
- continue;
- } else
- @throw [OFInvalidFormatException exception];
-
- if (newValue < value)
- @throw [OFOutOfRangeException exception];
-
- value = newValue;
- }
-
- if (!foundValue)
- @throw [OFInvalidFormatException exception];
-
- objc_autoreleasePoolPop(pool);
-
- return value;
-}
-
-- (uintmax_t)octalValue
-{
- void *pool = objc_autoreleasePoolPush();
- const of_unichar_t *characters = self.characters;
- size_t i = 0, length = self.length;
- uintmax_t value = 0;
- bool expectWhitespace = false;
-
- while (length > 0 && of_ascii_isspace(*characters)) {
- characters++;
- length--;
- }
-
- if (length == 0) {
- objc_autoreleasePoolPop(pool);
- return 0;
- }
-
- for (; i < length; i++) {
- uintmax_t newValue;
-
- if (expectWhitespace) {
- if (of_ascii_isspace(characters[i]))
- continue;
-
- @throw [OFInvalidFormatException exception];
- }
-
- if (characters[i] >= '0' && characters[i] <= '7')
- newValue = (value << 3) | (characters[i] - '0');
- else if (of_ascii_isspace(characters[i])) {
- expectWhitespace = true;
- continue;
- } else
- @throw [OFInvalidFormatException exception];
-
- if (newValue < value)
- @throw [OFOutOfRangeException exception];
-
- value = newValue;
- }
+- (unsigned long long)unsignedLongLongValue
+{
+ return [self unsignedLongLongValueWithBase: 10];
+}
+
+- (unsigned long long)unsignedLongLongValueWithBase: (int)base
+{
+ void *pool = objc_autoreleasePoolPush();
+ const char *UTF8String = self.UTF8String;
+ char *endPointer = NULL;
+ unsigned long long value;
+
+ /* Use isspace since strtoull uses the same. */
+ while (isspace((unsigned char)*UTF8String))
+ UTF8String++;
+
+ if (*UTF8String == '-')
+ @throw [OFInvalidFormatException exception];
+
+ errno = 0;
+ value = strtoull(UTF8String, &endPointer, base);
+
+ if (value == ULLONG_MAX && errno == ERANGE)
+ @throw [OFOutOfRangeException exception];
+
+ /* Check if there are any invalid chars left */
+ if (endPointer != NULL)
+ for (; *endPointer != '\0'; endPointer++)
+ /* Use isspace since strtoull uses the same. */
+ if (!isspace((unsigned char)*endPointer))
+ @throw [OFInvalidFormatException exception];
objc_autoreleasePoolPop(pool);
return value;
}
- (float)floatValue
{
void *pool = objc_autoreleasePoolPush();
-
-#if defined(OF_AMIGAOS_M68K) || defined(OF_MORPHOS)
OFString *stripped = self.stringByDeletingEnclosingWhitespaces;
if ([stripped caseInsensitiveCompare: @"INF"] == OF_ORDERED_SAME ||
[stripped caseInsensitiveCompare: @"INFINITY"] == OF_ORDERED_SAME)
return INFINITY;
if ([stripped caseInsensitiveCompare: @"-INF"] == OF_ORDERED_SAME ||
[stripped caseInsensitiveCompare: @"-INFINITY"] == OF_ORDERED_SAME)
return -INFINITY;
-#endif
#ifdef HAVE_STRTOF_L
const char *UTF8String = self.UTF8String;
#else
/*
@@ -2500,23 +2406,25 @@
withString: decimalPoint].UTF8String;
#endif
char *endPointer = NULL;
float value;
- while (of_ascii_isspace(*UTF8String))
- UTF8String++;
-
+ errno = 0;
#ifdef HAVE_STRTOF_L
value = strtof_l(UTF8String, &endPointer, cLocale);
#else
value = strtof(UTF8String, &endPointer);
#endif
+
+ if (value == HUGE_VALF && errno == ERANGE)
+ @throw [OFOutOfRangeException exception];
/* Check if there are any invalid chars left */
if (endPointer != NULL)
for (; *endPointer != '\0'; endPointer++)
- if (!of_ascii_isspace(*endPointer))
+ /* Use isspace since strtof uses the same. */
+ if (!isspace((unsigned char)*endPointer))
@throw [OFInvalidFormatException exception];
objc_autoreleasePoolPop(pool);
return value;
@@ -2523,21 +2431,18 @@
}
- (double)doubleValue
{
void *pool = objc_autoreleasePoolPush();
-
-#if defined(OF_AMIGAOS_M68K) || defined(OF_MORPHOS)
OFString *stripped = self.stringByDeletingEnclosingWhitespaces;
if ([stripped caseInsensitiveCompare: @"INF"] == OF_ORDERED_SAME ||
[stripped caseInsensitiveCompare: @"INFINITY"] == OF_ORDERED_SAME)
return INFINITY;
if ([stripped caseInsensitiveCompare: @"-INF"] == OF_ORDERED_SAME ||
[stripped caseInsensitiveCompare: @"-INFINITY"] == OF_ORDERED_SAME)
return -INFINITY;
-#endif
#ifdef HAVE_STRTOD_L
const char *UTF8String = self.UTF8String;
#else
/*
@@ -2550,23 +2455,25 @@
withString: decimalPoint].UTF8String;
#endif
char *endPointer = NULL;
double value;
- while (of_ascii_isspace(*UTF8String))
- UTF8String++;
-
+ errno = 0;
#ifdef HAVE_STRTOD_L
value = strtod_l(UTF8String, &endPointer, cLocale);
#else
value = strtod(UTF8String, &endPointer);
#endif
+ if (value == HUGE_VAL && errno == ERANGE)
+ @throw [OFOutOfRangeException exception];
+
/* Check if there are any invalid chars left */
if (endPointer != NULL)
for (; *endPointer != '\0'; endPointer++)
- if (!of_ascii_isspace(*endPointer))
+ /* Use isspace since strtod uses the same. */
+ if (!isspace((unsigned char)*endPointer))
@throw [OFInvalidFormatException exception];
objc_autoreleasePoolPop(pool);
return value;
Index: src/OFSystemInfo.m
==================================================================
--- src/OFSystemInfo.m
+++ src/OFSystemInfo.m
@@ -150,11 +150,11 @@
void *pool = objc_autoreleasePoolPush();
@try {
OFDictionary *propertyList = [OFString stringWithContentsOfFile:
@"/System/Library/CoreServices/SystemVersion.plist"]
- .propertyListValue;
+ .objectByParsingPropertyList;
operatingSystemVersion = [[propertyList
objectForKey: @"ProductVersion"] copy];
} @finally {
objc_autoreleasePoolPop(pool);
Index: src/OFTarArchiveEntry.h
==================================================================
--- src/OFTarArchiveEntry.h
+++ src/OFTarArchiveEntry.h
@@ -51,18 +51,18 @@
* @brief A class which represents an entry of a tar archive.
*/
@interface OFTarArchiveEntry: OFObject
{
OFString *_fileName;
- uint32_t _mode;
- uint64_t _size;
- uint32_t _UID, _GID;
+ unsigned long _mode;
+ unsigned long long _size;
+ unsigned long _UID, _GID;
OFDate *_modificationDate;
of_tar_archive_entry_type_t _type;
OFString *_Nullable _targetFileName;
OFString *_Nullable _owner, *_Nullable _group;
- uint32_t _deviceMajor, _deviceMinor;
+ unsigned long _deviceMajor, _deviceMinor;
OF_RESERVE_IVARS(4)
}
/*!
* @brief The file name of the entry.
@@ -70,26 +70,26 @@
@property (readonly, copy, nonatomic) OFString *fileName;
/*!
* @brief The mode of the entry.
*/
-@property (readonly, nonatomic) uint32_t mode;
+@property (readonly, nonatomic) unsigned long mode;
/*!
* @brief The UID of the owner.
*/
-@property (readonly, nonatomic) uint32_t UID;
+@property (readonly, nonatomic) unsigned long UID;
/*!
* @brief The GID of the group.
*/
-@property (readonly, nonatomic) uint32_t GID;
+@property (readonly, nonatomic) unsigned long GID;
/*!
* @brief The size of the file.
*/
-@property (readonly, nonatomic) uint64_t size;
+@property (readonly, nonatomic) unsigned long long size;
/*!
* @brief The date of the last modification of the file.
*/
@property (readonly, retain, nonatomic) OFDate *modificationDate;
@@ -118,16 +118,16 @@
@property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *group;
/*!
* @brief The device major (if the file is a device).
*/
-@property (readonly, nonatomic) uint32_t deviceMajor;
+@property (readonly, nonatomic) unsigned long deviceMajor;
/*!
* @brief The device major (if the file is a device).
*/
-@property (readonly, nonatomic) uint32_t deviceMinor;
+@property (readonly, nonatomic) unsigned long deviceMinor;
/*!
* @brief Creates a new OFTarArchiveEntry with the specified file name.
*
* @param fileName The file name for the OFTarArchiveEntry
Index: src/OFTarArchiveEntry.m
==================================================================
--- src/OFTarArchiveEntry.m
+++ src/OFTarArchiveEntry.m
@@ -51,24 +51,25 @@
for (size_t i = cStringLength; i < length; i++)
buffer[i] = '\0';
}
-static uintmax_t
-octalValueFromBuffer(const unsigned char *buffer, size_t length, uintmax_t max)
+static unsigned long long
+octalValueFromBuffer(const unsigned char *buffer, size_t length,
+ unsigned long long max)
{
- uintmax_t value = 0;
+ unsigned long long value = 0;
if (length == 0)
return 0;
if (buffer[0] == 0x80) {
for (size_t i = 1; i < length; i++)
value = (value << 8) | buffer[i];
} else
- value = stringFromBuffer(buffer, length,
- OF_STRING_ENCODING_ASCII).octalValue;
+ value = [stringFromBuffer(buffer, length,
+ OF_STRING_ENCODING_ASCII) unsignedLongLongValueWithBase: 8];
if (value > max)
@throw [OFOutOfRangeException exception];
return value;
@@ -93,22 +94,22 @@
@try {
void *pool = objc_autoreleasePoolPush();
OFString *targetFileName;
_fileName = [stringFromBuffer(header, 100, encoding) copy];
- _mode = (uint32_t)octalValueFromBuffer(
- header + 100, 8, UINT32_MAX);
- _UID = (uint32_t)octalValueFromBuffer(
- header + 108, 8, UINT32_MAX);
- _GID = (uint32_t)octalValueFromBuffer(
- header + 116, 8, UINT32_MAX);
- _size = (uint64_t)octalValueFromBuffer(
- header + 124, 12, UINT64_MAX);
+ _mode = (unsigned long)octalValueFromBuffer(
+ header + 100, 8, ULONG_MAX);
+ _UID = (unsigned long)octalValueFromBuffer(
+ header + 108, 8, ULONG_MAX);
+ _GID = (unsigned long)octalValueFromBuffer(
+ header + 116, 8, ULONG_MAX);
+ _size = (unsigned long long)octalValueFromBuffer(
+ header + 124, 12, ULLONG_MAX);
_modificationDate = [[OFDate alloc]
initWithTimeIntervalSince1970:
(of_time_interval_t)octalValueFromBuffer(
- header + 136, 12, UINTMAX_MAX)];
+ header + 136, 12, ULLONG_MAX)];
_type = header[156];
targetFileName = stringFromBuffer(header + 157, 100, encoding);
if (targetFileName.length > 0)
_targetFileName = [targetFileName copy];
@@ -122,14 +123,14 @@
_owner = [stringFromBuffer(header + 265, 32, encoding)
copy];
_group = [stringFromBuffer(header + 297, 32, encoding)
copy];
- _deviceMajor = (uint32_t)octalValueFromBuffer(
- header + 329, 8, UINT32_MAX);
- _deviceMinor = (uint32_t)octalValueFromBuffer(
- header + 337, 8, UINT32_MAX);
+ _deviceMajor = (unsigned long)octalValueFromBuffer(
+ header + 329, 8, ULONG_MAX);
+ _deviceMinor = (unsigned long)octalValueFromBuffer(
+ header + 337, 8, ULONG_MAX);
prefix = stringFromBuffer(header + 345, 155, encoding);
if (prefix.length > 0) {
OFString *fileName = [OFString
stringWithFormat: @"%@/%@",
@@ -206,26 +207,26 @@
- (OFString *)fileName
{
return _fileName;
}
-- (uint32_t)mode
+- (unsigned long)mode
{
return _mode;
}
-- (uint32_t)UID
+- (unsigned long)UID
{
return _UID;
}
-- (uint32_t)GID
+- (unsigned long)GID
{
return _GID;
}
-- (uint64_t)size
+- (unsigned long long)size
{
return _size;
}
- (OFDate *)modificationDate
@@ -251,16 +252,16 @@
- (OFString *)group
{
return _group;
}
-- (uint32_t)deviceMajor
+- (unsigned long)deviceMajor
{
return _deviceMajor;
}
-- (uint32_t)deviceMinor
+- (unsigned long)deviceMinor
{
return _deviceMinor;
}
- (OFString *)description
@@ -292,11 +293,11 @@
- (void)of_writeToStream: (OFStream *)stream
encoding: (of_string_encoding_t)encoding
{
unsigned char buffer[512];
- uint64_t modificationDate;
+ unsigned long long modificationDate;
uint16_t checksum = 0;
stringToBuffer(buffer, _fileName, 100, encoding);
stringToBuffer(buffer + 100,
[OFString stringWithFormat: @"%06" PRIo16 " ", _mode], 8,
@@ -310,11 +311,11 @@
stringToBuffer(buffer + 124,
[OFString stringWithFormat: @"%011" PRIo64 " ", _size], 12,
OF_STRING_ENCODING_ASCII);
modificationDate = _modificationDate.timeIntervalSince1970;
stringToBuffer(buffer + 136,
- [OFString stringWithFormat: @"%011" PRIo64 " ", modificationDate],
+ [OFString stringWithFormat: @"%011llo", modificationDate],
12, OF_STRING_ENCODING_ASCII);
/*
* During checksumming, the checksum field is expected to be set to 8
* spaces.
Index: src/OFURL.m
==================================================================
--- src/OFURL.m
+++ src/OFURL.m
@@ -486,16 +486,16 @@
portString = [OFString
stringWithUTF8String: tmp2
length: UTF8String - tmp2];
if (portString.length == 0 ||
- portString.decimalValue > 65535)
+ portString.unsignedLongLongValue > 65535)
@throw [OFInvalidFormatException
exception];
- _port = [[OFNumber alloc] initWithUInt16:
- (uint16_t)portString.decimalValue];
+ _port = [[OFNumber alloc] initWithUnsignedShort:
+ portString.unsignedLongLongValue];
} else if (*UTF8String != '\0')
@throw [OFInvalidFormatException exception];
isIPv6Host = true;
} else if ((tmp2 = strchr(UTF8String, ':')) != NULL) {
@@ -507,15 +507,15 @@
_URLEncodedHost = [[OFString alloc]
initWithUTF8String: UTF8String];
portString = [OFString stringWithUTF8String: tmp2];
- if (portString.decimalValue > 65535)
+ if (portString.unsignedLongLongValue > 65535)
@throw [OFInvalidFormatException exception];
- _port = [[OFNumber alloc] initWithUInt16:
- (uint16_t)portString.decimalValue];
+ _port = [[OFNumber alloc] initWithUnsignedShort:
+ portString.unsignedLongLongValue];
} else
_URLEncodedHost = [[OFString alloc]
initWithUTF8String: UTF8String];
if (!isIPv6Host)
Index: src/OFXMLNode.h
==================================================================
--- src/OFXMLNode.h
+++ src/OFXMLNode.h
@@ -39,18 +39,18 @@
* single child with the specified string value.
*/
@property (nonatomic, copy) OFString *stringValue;
/*!
- * @brief The contents of the receiver as a decimal value.
+ * @brief The contents of the receiver as a `long long` value.
*/
-@property (readonly, nonatomic) intmax_t decimalValue;
+@property (readonly, nonatomic) long long longLongValue;
/*!
- * @brief The contents of the receiver as a hexadecimal value.
+ * @brief The contents of the receiver as an `unsigned long long` value.
*/
-@property (readonly, nonatomic) uintmax_t hexadecimalValue;
+@property (readonly, nonatomic) unsigned long long unsignedLongLongValue;
/*!
* @brief The contents of the receiver as a float value.
*/
@property (readonly, nonatomic) float floatValue;
@@ -87,8 +87,34 @@
* @return An OFString representing the OFXMLNode as an XML string with
* indentation
*/
- (OFString *)XMLStringWithIndentation: (unsigned int)indentation
level: (unsigned int)level;
+
+/*!
+ * @brief The contents of the receiver as a `long long` value in the specified
+ * base.
+ *
+ * @param base The base to use. If the base is 0, base 16 is assumed if the
+ * string starts with 0x (after stripping white spaces). If the
+ * string starts with 0, base 8 is assumed. Otherwise, base 10 is
+ * assumed.
+ * @return The contents of the receiver as a `long long` value in the specified
+ * base
+ */
+- (long long)longLongValueWithBase: (int)base;
+
+/*!
+ * @brief The contents of the receiver as an `unsigned long long` value in the
+ * specified base.
+ *
+ * @param base The base to use. If the base is 0, base 16 is assumed if the
+ * string starts with 0x (after stripping white spaces). If the
+ * string starts with 0, base 8 is assumed. Otherwise, base 10 is
+ * assumed.
+ * @return The contents of the receiver as an `unsigned long long` value in the
+ * specified base
+ */
+- (unsigned long long)unsignedLongLongValueWithBase: (int)base;
@end
OF_ASSUME_NONNULL_END
Index: src/OFXMLNode.m
==================================================================
--- src/OFXMLNode.m
+++ src/OFXMLNode.m
@@ -44,18 +44,28 @@
- (void)setStringValue: (OFString *)stringValue
{
OF_UNRECOGNIZED_SELECTOR
}
-- (intmax_t)decimalValue
+- (long long)longLongValue
+{
+ return self.stringValue.longLongValue;
+}
+
+- (long long)longLongValueWithBase: (int)base
+{
+ return [self.stringValue longLongValueWithBase: base];
+}
+
+- (unsigned long long)unsignedLongLongValue
{
- return self.stringValue.decimalValue;
+ return self.stringValue.unsignedLongLongValue;
}
-- (uintmax_t)hexadecimalValue
+- (unsigned long long)unsignedLongLongValueWithBase: (int)base
{
- return self.stringValue.hexadecimalValue;
+ return [self.stringValue unsignedLongLongValueWithBase: base];
}
- (float)floatValue
{
return self.stringValue.floatValue;
Index: src/bridge/Info.plist.in
==================================================================
--- src/bridge/Info.plist.in
+++ src/bridge/Info.plist.in
@@ -5,11 +5,11 @@
CFBundleExecutable
ObjFWBridge
CFBundleName
ObjFWBridge
CFBundleIdentifier
- zone.heap.objfw.bridge
+ im.nil.objfw.bridge
CFBundleInfoDictionaryVersion
6.0
CFBundlePackageType
FMWK
CFBundleVersion
ADDED src/runtime/Info.plist.in
Index: src/runtime/Info.plist.in
==================================================================
--- src/runtime/Info.plist.in
+++ src/runtime/Info.plist.in
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleExecutable
+ ObjFWRT
+ CFBundleName
+ ObjFWRT
+ CFBundleIdentifier
+ im.nil.objfw.rt
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ FMWK
+ CFBundleVersion
+ @BUNDLE_VERSION@
+ CFBundleShortVersionString
+ @BUNDLE_SHORT_VERSION@
+ MinimumOSVersion
+ 9.0
+
+
Index: src/runtime/Makefile
==================================================================
--- src/runtime/Makefile
+++ src/runtime/Makefile
@@ -1,10 +1,11 @@
include ../../extra.mk
SUBDIRS = lookup-asm
SUBDIRS_AFTER = ${LINKLIB}
CLEAN = amiga-library-functable.inc inline.h
+DISTCLEAN = Info.plist
SHARED_LIB = ${OBJFWRT_SHARED_LIB}
STATIC_LIB = ${OBJFWRT_STATIC_LIB}
FRAMEWORK = ${OBJFWRT_FRAMEWORK}
AMIGA_LIB = ${OBJFWRT_AMIGA_LIB}
Index: src/socket.m
==================================================================
--- src/socket.m
+++ src/socket.m
@@ -374,22 +374,22 @@
@throw [OFInvalidFormatException exception];
addr = 0;
for (OFString *component in components) {
- intmax_t number;
+ unsigned long long number;
if (component.length == 0)
@throw [OFInvalidFormatException exception];
if ([component indexOfCharacterFromSet:
whitespaceCharacterSet] != OF_NOT_FOUND)
@throw [OFInvalidFormatException exception];
- number = component.decimalValue;
+ number = component.unsignedLongLongValue;
- if (number < 0 || number > UINT8_MAX)
+ if (number > UINT8_MAX)
@throw [OFInvalidFormatException exception];
addr = (addr << 8) | (number & 0xFF);
}
@@ -401,17 +401,17 @@
}
static uint16_t
parseIPv6Component(OFString *component)
{
- uintmax_t number;
+ unsigned long long number;
if ([component indexOfCharacterFromSet:
[OFCharacterSet whitespaceCharacterSet]] != OF_NOT_FOUND)
@throw [OFInvalidFormatException exception];
- number = component.hexadecimalValue;
+ number = [component unsignedLongLongValueWithBase: 16];
if (number > UINT16_MAX)
@throw [OFInvalidFormatException exception];
return (uint16_t)number;
Index: tests/Info.plist.in
==================================================================
--- tests/Info.plist.in
+++ tests/Info.plist.in
@@ -11,13 +11,13 @@
CFBundleInfoDictionaryVersion
6.0
CFBundlePackageType
APPL
CFBundleVersion
- @PACKAGE_VERSION@
+ @BUNDLE_VERSION@
CFBundleShortVersionString
- @PACKAGE_VERSION@
+ @BUNDLE_SHORT_VERSION@
LSRequiresIPhoneOS
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
Index: tests/Makefile
==================================================================
--- tests/Makefile
+++ tests/Makefile
@@ -9,12 +9,12 @@
DISTCLEAN = Info.plist
PROG_NOINST = tests${PROG_SUFFIX}
STATIC_LIB_NOINST = ${TESTS_STATIC_LIB}
SRCS = ForwardingTests.m \
+ OFASN1DERParsingTests.m \
OFASN1DERRepresentationTests.m \
- OFASN1DERValueTests.m \
OFArrayTests.m \
${OF_BLOCK_TESTS_M} \
OFCharacterSetTests.m \
OFDataTests.m \
OFDateTests.m \
ADDED tests/OFASN1DERParsingTests.m
Index: tests/OFASN1DERParsingTests.m
==================================================================
--- tests/OFASN1DERParsingTests.m
+++ tests/OFASN1DERParsingTests.m
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
+ * 2018, 2019, 2020
+ * Jonathan Schleifer
+ *
+ * All rights reserved.
+ *
+ * This file is part of ObjFW. It may be distributed under the terms of the
+ * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
+ * the packaging of this file.
+ *
+ * Alternatively, it may be distributed under the terms of the GNU General
+ * Public License, either version 2 or 3, which can be found in the file
+ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
+ * file.
+ */
+
+#include "config.h"
+
+#import "TestsAppDelegate.h"
+
+static OFString *module = @"OFData+ASN1DERParsing";
+
+@implementation TestsAppDelegate (OFASN1DERParsingTests)
+- (void)ASN1DERParsingTests
+{
+ void *pool = objc_autoreleasePoolPush();
+ OFASN1BitString *bitString;
+ OFArray *array;
+ OFSet *set;
+ OFEnumerator *enumerator;
+
+ /* Boolean */
+ TEST(@"Parsing of boolean",
+ ![[[OFData dataWithItems: "\x01\x01\x00"
+ count: 3] objectByParsingASN1DER]
+ booleanValue] &&
+ [[[OFData dataWithItems: "\x01\x01\xFF"
+ count: 3] objectByParsingASN1DER] booleanValue])
+
+ EXPECT_EXCEPTION(@"Detection of invalid boolean #1",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x01\x01\x01"
+ count: 3] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of invalid boolean #2",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x01\x02\x00\x00"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of invalid boolean #3",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x01\x00"
+ count: 2] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated boolean",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x01\x01"
+ count: 2] objectByParsingASN1DER])
+
+ /* Integer */
+ TEST(@"Parsing of integer",
+ [[[OFData dataWithItems: "\x02\x00"
+ count: 2] objectByParsingASN1DER]
+ longLongValue] == 0 &&
+ [[[OFData dataWithItems: "\x02\x01\x01"
+ count: 3] objectByParsingASN1DER]
+ longLongValue] == 1 &&
+ [[[OFData dataWithItems: "\x02\x02\x01\x04"
+ count: 4] objectByParsingASN1DER]
+ longLongValue] == 260 &&
+ [[[OFData dataWithItems: "\x02\x01\xFF"
+ count: 3] objectByParsingASN1DER]
+ longLongValue] == -1 &&
+ [[[OFData dataWithItems: "\x02\x03\xFF\x00\x00"
+ count: 5] objectByParsingASN1DER]
+ longLongValue] == -65536 &&
+ (unsigned long long)[[[OFData dataWithItems: "\x02\x09\x00\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF"
+ "\xFF"
+ count: 11]
+ objectByParsingASN1DER] longLongValue] == ULLONG_MAX)
+
+ EXPECT_EXCEPTION(@"Detection of invalid integer #1",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x02\x02\x00\x00"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of invalid integer #2",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x02\x02\x00\x7F"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of invalid integer #3",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x02\x02\xFF\x80"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of out of range integer",
+ OFOutOfRangeException,
+ [[OFData dataWithItems: "\x02\x09\x01"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ count: 11] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated integer",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x02\x02\x00"
+ count: 3] objectByParsingASN1DER])
+
+ /* Bit string */
+ TEST(@"Parsing of bit string",
+ (bitString = [[OFData dataWithItems: "\x03\x01\x00"
+ count: 3] objectByParsingASN1DER]) &&
+ [bitString.bitStringValue isEqual: [OFData dataWithItems: ""
+ count: 0]] &&
+ bitString.bitStringLength == 0 &&
+ (bitString = [[OFData dataWithItems: "\x03\x0D\x01Hello World\x80"
+ count: 15] objectByParsingASN1DER]) &&
+ [bitString.bitStringValue
+ isEqual: [OFData dataWithItems: "Hello World\x80"
+ count: 12]] &&
+ bitString.bitStringLength == 95 &&
+ (bitString = [[OFData dataWithItems: "\x03\x81\x80\x00xxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ count: 131] objectByParsingASN1DER]) &&
+ [bitString.bitStringValue
+ isEqual: [OFData dataWithItems: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxx"
+ count: 127]] &&
+ bitString.bitStringLength == 127 * 8)
+
+ EXPECT_EXCEPTION(@"Detection of invalid bit string #1",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x03\x00"
+ count: 2] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of invalid bit string #2",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x03\x01\x01"
+ count: 3] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of out of range bit string",
+ OFOutOfRangeException,
+ [[OFData dataWithItems: "\x03\x89"
+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+ count: 11] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated bit string",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x03\x01"
+ count: 2] objectByParsingASN1DER])
+
+ /* Octet string */
+ TEST(@"Parsing of octet string",
+ [[[[OFData dataWithItems: "\x04\x0CHello World!"
+ count: 14] objectByParsingASN1DER]
+ octetStringValue] isEqual: [OFData dataWithItems: "Hello World!"
+ count: 12]] &&
+ [[[[OFData dataWithItems: "\x04\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxx"
+ count: 131] objectByParsingASN1DER]
+ octetStringValue] isEqual:
+ [OFData dataWithItems: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ count: 128]])
+
+ EXPECT_EXCEPTION(@"Detection of out of range octet string",
+ OFOutOfRangeException,
+ [[OFData dataWithItems: "\x04\x89"
+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+ count: 11] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated octet string",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x04\x01"
+ count: 2] objectByParsingASN1DER])
+
+ /* Null */
+ TEST(@"Parsing of null",
+ [[[OFData dataWithItems: "\x05\x00"
+ count: 2] objectByParsingASN1DER]
+ isEqual: [OFNull null]])
+
+ EXPECT_EXCEPTION(@"Detection of invalid null",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x05\x01\x00"
+ count: 3] objectByParsingASN1DER])
+
+ /* Object Identifier */
+ TEST(@"Parsing of Object Identifier",
+ (array = [[[OFData dataWithItems: "\x06\x01\x27"
+ count: 3] objectByParsingASN1DER]
+ subidentifiers]) && array.count == 2 &&
+ [[array objectAtIndex: 0] unsignedLongLongValue] == 0 &&
+ [[array objectAtIndex: 1] unsignedLongLongValue] == 39 &&
+ (array = [[[OFData dataWithItems: "\x06\x01\x4F"
+ count: 3] objectByParsingASN1DER]
+ subidentifiers]) && array.count == 2 &&
+ [[array objectAtIndex: 0] unsignedLongLongValue] == 1 &&
+ [[array objectAtIndex: 1] unsignedLongLongValue] == 39 &&
+ (array = [[[OFData dataWithItems: "\x06\x02\x88\x37"
+ count: 4] objectByParsingASN1DER]
+ subidentifiers]) && array.count == 2 &&
+ [[array objectAtIndex: 0] unsignedLongLongValue] == 2 &&
+ [[array objectAtIndex: 1] unsignedLongLongValue] == 999 &&
+ (array = [[[OFData dataWithItems: "\x06\x09\x2A\x86\x48\x86\xF7\x0D"
+ "\x01\x01\x0B"
+ count: 11] objectByParsingASN1DER]
+ subidentifiers]) && array.count == 7 &&
+ [[array objectAtIndex: 0] unsignedLongLongValue] == 1 &&
+ [[array objectAtIndex: 1] unsignedLongLongValue] == 2 &&
+ [[array objectAtIndex: 2] unsignedLongLongValue] == 840 &&
+ [[array objectAtIndex: 3] unsignedLongLongValue] == 113549 &&
+ [[array objectAtIndex: 4] unsignedLongLongValue] == 1 &&
+ [[array objectAtIndex: 5] unsignedLongLongValue] == 1 &&
+ [[array objectAtIndex: 6] unsignedLongLongValue] == 11)
+
+ EXPECT_EXCEPTION(@"Detection of invalid Object Identifier #1",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x06\x01\x81"
+ count: 3] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of invalid Object Identifier #2",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x06\x02\x80\x01"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of out of range Object Identifier",
+ OFOutOfRangeException,
+ [[OFData dataWithItems: "\x06\x0A\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ "\xFF\x7F"
+ count: 12] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated Object Identifier",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x06\x02\x00"
+ count: 3] objectByParsingASN1DER])
+
+ /* Enumerated */
+ TEST(@"Parsing of enumerated",
+ [[[OFData dataWithItems: "\x0A\x00"
+ count: 2] objectByParsingASN1DER] longLongValue] ==
+ 0 &&
+ [[[OFData dataWithItems: "\x0A\x01\x01"
+ count: 3] objectByParsingASN1DER] longLongValue] ==
+ 1 &&
+ [[[OFData dataWithItems: "\x0A\x02\x01\x04"
+ count: 4] objectByParsingASN1DER] longLongValue] ==
+ 260 &&
+ [[[OFData dataWithItems: "\x0A\x01\xFF"
+ count: 3] objectByParsingASN1DER] longLongValue] ==
+ -1 &&
+ [[[OFData dataWithItems: "\x0A\x03\xFF\x00\x00"
+ count: 5] objectByParsingASN1DER] longLongValue] ==
+ -65536 &&
+ (unsigned long long)[[[OFData dataWithItems: "\x0A\x09\x00\xFF\xFF"
+ "\xFF\xFF\xFF\xFF\xFF"
+ "\xFF"
+ count: 11]
+ objectByParsingASN1DER] longLongValue] == ULLONG_MAX)
+
+ EXPECT_EXCEPTION(@"Detection of invalid enumerated #1",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x0A\x02\x00\x00"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of invalid enumerated #2",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x0A\x02\x00\x7F"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of invalid enumerated #3",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x0A\x02\xFF\x80"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of out of range enumerated",
+ OFOutOfRangeException,
+ [[OFData dataWithItems: "\x0A\x09\x01"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
+ count: 11] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated enumerated",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x0A\x02\x00"
+ count: 3] objectByParsingASN1DER])
+
+ /* UTF-8 string */
+ TEST(@"Parsing of UTF-8 string",
+ [[[[OFData dataWithItems: "\x0C\x0EHällo Wörld!"
+ count: 16] objectByParsingASN1DER]
+ UTF8StringValue] isEqual: @"Hällo Wörld!"] &&
+ [[[[OFData dataWithItems: "\x0C\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxx"
+ count: 131] objectByParsingASN1DER]
+ UTF8StringValue] isEqual: @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ @"xxxxxxxxxxx"])
+
+ EXPECT_EXCEPTION(@"Detection of out of range UTF-8 string",
+ OFOutOfRangeException,
+ [[OFData dataWithItems: "\x0C\x89"
+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+ count: 11] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated UTF-8 string",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x0C\x01"
+ count: 2] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated length",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x0C\x83\x01\x01"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of invalid / inefficient length #1",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x0C\x81\x7F"
+ count: 3] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of invalid / inefficient length #2",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x0C\x82\x00\x80xxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxx"
+ count: 132] objectByParsingASN1DER])
+
+ /* Sequence */
+ TEST(@"Parsing of sequence",
+ (array = [[OFData dataWithItems: "\x30\x00"
+ count: 2] objectByParsingASN1DER]) &&
+ [array isKindOfClass: [OFArray class]] && array.count == 0 &&
+ (array = [[OFData dataWithItems: "\x30\x09\x02\x01\x7B\x0C\x04Test"
+ count: 11] objectByParsingASN1DER]) &&
+ [array isKindOfClass: [OFArray class]] && array.count == 2 &&
+ [[array objectAtIndex: 0] longLongValue] == 123 &&
+ [[[array objectAtIndex: 1] stringValue] isEqual: @"Test"])
+
+ EXPECT_EXCEPTION(@"Detection of truncated sequence #1",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x30\x01"
+ count: 2] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated sequence #2",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x30\x04\x02\x01\x01\x00\x00"
+ count: 7] objectByParsingASN1DER])
+
+ /* Set */
+ TEST(@"Parsing of set",
+ (set = [[OFData dataWithItems: "\x31\x00"
+ count: 2] objectByParsingASN1DER]) &&
+ [set isKindOfClass: [OFSet class]] && set.count == 0 &&
+ (set = [[OFData dataWithItems: "\x31\x09\x02\x01\x7B\x0C\x04Test"
+ count: 11] objectByParsingASN1DER]) &&
+ [set isKindOfClass: [OFSet class]] && set.count == 2 &&
+ (enumerator = [set objectEnumerator]) &&
+ [[enumerator nextObject] longLongValue] == 123 &&
+ [[[enumerator nextObject] stringValue] isEqual: @"Test"])
+
+ EXPECT_EXCEPTION(@"Detection of invalid set",
+ OFInvalidFormatException,
+ [[OFData dataWithItems: "\x31\x06\x02\x01\x02\x02\x01\x01"
+ count: 8] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated set #1",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x31\x01"
+ count: 2] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated set #2",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x31\x04\x02\x01\x01\x00\x00"
+ count: 7] objectByParsingASN1DER])
+
+ /* NumericString */
+ TEST(@"Parsing of NumericString",
+ [[[[OFData dataWithItems: "\x12\x0B" "12345 67890"
+ count: 13] objectByParsingASN1DER]
+ numericStringValue] isEqual: @"12345 67890"] &&
+ [[[[OFData dataWithItems: "\x12\x81\x80" "0000000000000000000000000"
+ "0000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000"
+ "00000000000000000000000"
+ count: 131] objectByParsingASN1DER]
+ numericStringValue] isEqual: @"000000000000000000000000000000000000"
+ @"000000000000000000000000000000000000"
+ @"000000000000000000000000000000000000"
+ @"00000000000000000000"])
+
+ EXPECT_EXCEPTION(@"Detection of invalid NumericString",
+ OFInvalidEncodingException,
+ [[OFData dataWithItems: "\x12\x02."
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of out of range NumericString",
+ OFOutOfRangeException,
+ [[OFData dataWithItems: "\x12\x89"
+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+ count: 11] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated NumericString",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x12\x01"
+ count: 2] objectByParsingASN1DER])
+
+ /* PrintableString */
+ TEST(@"Parsing of PrintableString",
+ [[[[OFData dataWithItems: "\x13\x0CHello World."
+ count: 14] objectByParsingASN1DER]
+ printableStringValue] isEqual: @"Hello World."] &&
+ [[[[OFData dataWithItems: "\x13\x81\x80 '()+,-./:=?abcdefghijklmnop"
+ "qrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ '()"
+ "+,-./:=?abcdefghijklmnopqrstuvwxyzABCDEF"
+ "GHIJKLMNOPQRSTUVWXYZ"
+ count: 131] objectByParsingASN1DER]
+ printableStringValue] isEqual: @" '()+,-./:=?abcdefghijklmnopqrstuv"
+ @"wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ '()"
+ @"+,-./:=?abcdefghijklmnopqrstuvwxyz"
+ @"ABCDEFGHIJKLMNOPQRSTUVWXYZ"])
+
+ EXPECT_EXCEPTION(@"Detection of invalid PrintableString",
+ OFInvalidEncodingException,
+ [[OFData dataWithItems: "\x13\x02;"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of out of range PrintableString",
+ OFOutOfRangeException,
+ [[OFData dataWithItems: "\x13\x89"
+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+ count: 11] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated PrintableString",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x13\x01"
+ count: 2] objectByParsingASN1DER])
+
+ /* IA5String */
+ TEST(@"Parsing of IA5String",
+ [[[[OFData dataWithItems: "\x16\x0CHello World!"
+ count: 14] objectByParsingASN1DER]
+ IA5StringValue] isEqual: @"Hello World!"] &&
+ [[[[OFData dataWithItems: "\x16\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxx"
+ count: 131] objectByParsingASN1DER]
+ IA5StringValue] isEqual: @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ @"xxxxxxxx"])
+
+ EXPECT_EXCEPTION(@"Detection of invalid IA5String",
+ OFInvalidEncodingException,
+ [[OFData dataWithItems: "\x16\x02ä"
+ count: 4] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of out of range IA5String",
+ OFOutOfRangeException,
+ [[OFData dataWithItems: "\x16\x89"
+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+ count: 11] objectByParsingASN1DER])
+
+ EXPECT_EXCEPTION(@"Detection of truncated IA5String",
+ OFTruncatedDataException,
+ [[OFData dataWithItems: "\x16\x01"
+ count: 2] objectByParsingASN1DER])
+
+ objc_autoreleasePoolPop(pool);
+}
+@end
DELETED tests/OFASN1DERValueTests.m
Index: tests/OFASN1DERValueTests.m
==================================================================
--- tests/OFASN1DERValueTests.m
+++ tests/OFASN1DERValueTests.m
@@ -1,437 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
- * 2018, 2019, 2020
- * Jonathan Schleifer
- *
- * All rights reserved.
- *
- * This file is part of ObjFW. It may be distributed under the terms of the
- * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
- * the packaging of this file.
- *
- * Alternatively, it may be distributed under the terms of the GNU General
- * Public License, either version 2 or 3, which can be found in the file
- * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
- * file.
- */
-
-#include "config.h"
-
-#import "TestsAppDelegate.h"
-
-static OFString *module = @"OFData+ASN1DERValue";
-
-@implementation TestsAppDelegate (OFASN1DERValueTests)
-- (void)ASN1DERValueTests
-{
- void *pool = objc_autoreleasePoolPush();
- OFASN1BitString *bitString;
- OFArray *array;
- OFSet *set;
- OFEnumerator *enumerator;
-
- /* Boolean */
- TEST(@"Parsing of boolean",
- ![[[OFData dataWithItems: "\x01\x01\x00"
- count: 3] ASN1DERValue] booleanValue] &&
- [[[OFData dataWithItems: "\x01\x01\xFF"
- count: 3] ASN1DERValue] booleanValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid boolean #1",
- OFInvalidFormatException, [[OFData dataWithItems: "\x01\x01\x01"
- count: 3] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid boolean #2",
- OFInvalidFormatException, [[OFData dataWithItems: "\x01\x02\x00\x00"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid boolean #3",
- OFInvalidFormatException, [[OFData dataWithItems: "\x01\x00"
- count: 2] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated boolean",
- OFTruncatedDataException, [[OFData dataWithItems: "\x01\x01"
- count: 2] ASN1DERValue])
-
- /* Integer */
- TEST(@"Parsing of integer",
- [[[OFData dataWithItems: "\x02\x00"
- count: 2] ASN1DERValue] integerValue] == 0 &&
- [[[OFData dataWithItems: "\x02\x01\x01"
- count: 3] ASN1DERValue] integerValue] == 1 &&
- [[[OFData dataWithItems: "\x02\x02\x01\x04"
- count: 4] ASN1DERValue] integerValue] == 260 &&
- [[[OFData dataWithItems: "\x02\x01\xFF"
- count: 3] ASN1DERValue] integerValue] == -1 &&
- [[[OFData dataWithItems: "\x02\x03\xFF\x00\x00"
- count: 5] ASN1DERValue] integerValue] == -65536 &&
- (uintmax_t)[[[OFData dataWithItems: "\x02\x09\x00\xFF\xFF\xFF\xFF"
- "\xFF\xFF\xFF\xFF"
- count: 11] ASN1DERValue]
- integerValue] == UINTMAX_MAX)
-
- EXPECT_EXCEPTION(@"Detection of invalid integer #1",
- OFInvalidFormatException, [[OFData dataWithItems: "\x02\x02\x00\x00"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid integer #2",
- OFInvalidFormatException, [[OFData dataWithItems: "\x02\x02\x00\x7F"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid integer #3",
- OFInvalidFormatException, [[OFData dataWithItems: "\x02\x02\xFF\x80"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of out of range integer",
- OFOutOfRangeException,
- [[OFData dataWithItems: "\x02\x09\x01"
- "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
- count: 11] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated integer",
- OFTruncatedDataException, [[OFData dataWithItems: "\x02\x02\x00"
- count: 3] ASN1DERValue])
-
- /* Bit string */
- TEST(@"Parsing of bit string",
- (bitString = [[OFData dataWithItems: "\x03\x01\x00"
- count: 3] ASN1DERValue]) &&
- [bitString.bitStringValue isEqual: [OFData dataWithItems: ""
- count: 0]] &&
- bitString.bitStringLength == 0 &&
- (bitString = [[OFData dataWithItems: "\x03\x0D\x01Hello World\x80"
- count: 15] ASN1DERValue]) &&
- [bitString.bitStringValue
- isEqual: [OFData dataWithItems: "Hello World\x80"
- count: 12]] &&
- bitString.bitStringLength == 95 &&
- (bitString = [[OFData dataWithItems: "\x03\x81\x80\x00xxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
- count: 131] ASN1DERValue]) &&
- [bitString.bitStringValue
- isEqual: [OFData dataWithItems: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxx"
- count: 127]] &&
- bitString.bitStringLength == 127 * 8)
-
- EXPECT_EXCEPTION(@"Detection of invalid bit string #1",
- OFInvalidFormatException, [[OFData dataWithItems: "\x03\x00"
- count: 2] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid bit string #2",
- OFInvalidFormatException, [[OFData dataWithItems: "\x03\x01\x01"
- count: 3] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of out of range bit string",
- OFOutOfRangeException,
- [[OFData dataWithItems: "\x03\x89"
- "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
- count: 11] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated bit string",
- OFTruncatedDataException, [[OFData dataWithItems: "\x03\x01"
- count: 2] ASN1DERValue])
-
- /* Octet string */
- TEST(@"Parsing of octet string",
- [[[[OFData dataWithItems: "\x04\x0CHello World!"
- count: 14] ASN1DERValue] octetStringValue]
- isEqual: [OFData dataWithItems: "Hello World!"
- count: 12]] &&
- [[[[OFData dataWithItems: "\x04\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxx"
- count: 131] ASN1DERValue] octetStringValue]
- isEqual: [OFData dataWithItems: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxx"
- count: 128]])
-
- EXPECT_EXCEPTION(@"Detection of out of range octet string",
- OFOutOfRangeException,
- [[OFData dataWithItems: "\x04\x89"
- "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
- count: 11] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated octet string",
- OFTruncatedDataException, [[OFData dataWithItems: "\x04\x01"
- count: 2] ASN1DERValue])
-
- /* Null */
- TEST(@"Parsing of null",
- [[[OFData dataWithItems: "\x05\x00"
- count: 2] ASN1DERValue] isEqual: [OFNull null]])
-
- EXPECT_EXCEPTION(@"Detection of invalid null",
- OFInvalidFormatException, [[OFData dataWithItems: "\x05\x01\x00"
- count: 3] ASN1DERValue])
-
- /* Object Identifier */
- TEST(@"Parsing of Object Identifier",
- (array = [[[OFData dataWithItems: "\x06\x01\x27"
- count: 3] ASN1DERValue]
- subidentifiers]) && array.count == 2 &&
- [[array objectAtIndex: 0] uIntMaxValue] == 0 &&
- [[array objectAtIndex: 1] uIntMaxValue] == 39 &&
- (array = [[[OFData dataWithItems: "\x06\x01\x4F"
- count: 3] ASN1DERValue]
- subidentifiers]) && array.count == 2 &&
- [[array objectAtIndex: 0] uIntMaxValue] == 1 &&
- [[array objectAtIndex: 1] uIntMaxValue] == 39 &&
- (array = [[[OFData dataWithItems: "\x06\x02\x88\x37"
- count: 4] ASN1DERValue]
- subidentifiers]) && array.count == 2 &&
- [[array objectAtIndex: 0] uIntMaxValue] == 2 &&
- [[array objectAtIndex: 1] uIntMaxValue] == 999 &&
- (array = [[[OFData dataWithItems: "\x06\x09\x2A\x86\x48\x86\xF7\x0D"
- "\x01\x01\x0B"
- count: 11] ASN1DERValue]
- subidentifiers]) && array.count == 7 &&
- [[array objectAtIndex: 0] uIntMaxValue] == 1 &&
- [[array objectAtIndex: 1] uIntMaxValue] == 2 &&
- [[array objectAtIndex: 2] uIntMaxValue] == 840 &&
- [[array objectAtIndex: 3] uIntMaxValue] == 113549 &&
- [[array objectAtIndex: 4] uIntMaxValue] == 1 &&
- [[array objectAtIndex: 5] uIntMaxValue] == 1 &&
- [[array objectAtIndex: 6] uIntMaxValue] == 11)
-
- EXPECT_EXCEPTION(@"Detection of invalid Object Identifier #1",
- OFInvalidFormatException, [[OFData dataWithItems: "\x06\x01\x81"
- count: 3] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid Object Identifier #2",
- OFInvalidFormatException, [[OFData dataWithItems: "\x06\x02\x80\x01"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of out of range Object Identifier",
- OFOutOfRangeException,
- [[OFData dataWithItems: "\x06\x0A\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
- "\xFF\x7F"
- count: 12] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated Object Identifier",
- OFTruncatedDataException, [[OFData dataWithItems: "\x06\x02\x00"
- count: 3] ASN1DERValue])
-
- /* Enumerated */
- TEST(@"Parsing of enumerated",
- [[[OFData dataWithItems: "\x0A\x00"
- count: 2] ASN1DERValue] integerValue] == 0 &&
- [[[OFData dataWithItems: "\x0A\x01\x01"
- count: 3] ASN1DERValue] integerValue] == 1 &&
- [[[OFData dataWithItems: "\x0A\x02\x01\x04"
- count: 4] ASN1DERValue] integerValue] == 260 &&
- [[[OFData dataWithItems: "\x0A\x01\xFF"
- count: 3] ASN1DERValue] integerValue] == -1 &&
- [[[OFData dataWithItems: "\x0A\x03\xFF\x00\x00"
- count: 5] ASN1DERValue] integerValue] == -65536 &&
- (uintmax_t)[[[OFData dataWithItems: "\x0A\x09\x00\xFF\xFF\xFF\xFF"
- "\xFF\xFF\xFF\xFF"
- count: 11] ASN1DERValue]
- integerValue] == UINTMAX_MAX)
-
- EXPECT_EXCEPTION(@"Detection of invalid enumerated #1",
- OFInvalidFormatException, [[OFData dataWithItems: "\x0A\x02\x00\x00"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid enumerated #2",
- OFInvalidFormatException, [[OFData dataWithItems: "\x0A\x02\x00\x7F"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid enumerated #3",
- OFInvalidFormatException, [[OFData dataWithItems: "\x0A\x02\xFF\x80"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of out of range enumerated",
- OFOutOfRangeException,
- [[OFData dataWithItems: "\x0A\x09\x01"
- "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
- count: 11] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated enumerated",
- OFTruncatedDataException, [[OFData dataWithItems: "\x0A\x02\x00"
- count: 3] ASN1DERValue])
-
- /* UTF-8 string */
- TEST(@"Parsing of UTF-8 string",
- [[[[OFData dataWithItems: "\x0C\x0EHällo Wörld!"
- count: 16] ASN1DERValue] UTF8StringValue]
- isEqual: @"Hällo Wörld!"] &&
- [[[[OFData dataWithItems: "\x0C\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxx"
- count: 131] ASN1DERValue] UTF8StringValue]
- isEqual: @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- @"xxxxxxxxxxxxxxxx"])
-
- EXPECT_EXCEPTION(@"Detection of out of range UTF-8 string",
- OFOutOfRangeException,
- [[OFData dataWithItems: "\x0C\x89"
- "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
- count: 11] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated UTF-8 string",
- OFTruncatedDataException, [[OFData dataWithItems: "\x0C\x01"
- count: 2] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated length",
- OFTruncatedDataException, [[OFData dataWithItems: "\x0C\x83\x01\x01"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid / inefficient length #1",
- OFInvalidFormatException, [[OFData dataWithItems: "\x0C\x81\x7F"
- count: 3] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of invalid / inefficient length #2",
- OFInvalidFormatException,
- [[OFData dataWithItems: "\x0C\x82\x00\x80xxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxx"
- count: 132] ASN1DERValue])
-
- /* Sequence */
- TEST(@"Parsing of sequence",
- (array = [[OFData dataWithItems: "\x30\x00"
- count: 2] ASN1DERValue]) &&
- [array isKindOfClass: [OFArray class]] && array.count == 0 &&
- (array = [[OFData dataWithItems: "\x30\x09\x02\x01\x7B\x0C\x04Test"
- count: 11] ASN1DERValue]) &&
- [array isKindOfClass: [OFArray class]] && array.count == 2 &&
- [[array objectAtIndex: 0] integerValue] == 123 &&
- [[[array objectAtIndex: 1] stringValue] isEqual: @"Test"])
-
- EXPECT_EXCEPTION(@"Detection of truncated sequence #1",
- OFTruncatedDataException, [[OFData dataWithItems: "\x30\x01"
- count: 2] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated sequence #2",
- OFTruncatedDataException,
- [[OFData dataWithItems: "\x30\x04\x02\x01\x01\x00\x00"
- count: 7] ASN1DERValue])
-
- /* Set */
- TEST(@"Parsing of set",
- (set = [[OFData dataWithItems: "\x31\x00"
- count: 2] ASN1DERValue]) &&
- [set isKindOfClass: [OFSet class]] && set.count == 0 &&
- (set = [[OFData dataWithItems: "\x31\x09\x02\x01\x7B\x0C\x04Test"
- count: 11] ASN1DERValue]) &&
- [set isKindOfClass: [OFSet class]] && set.count == 2 &&
- (enumerator = [set objectEnumerator]) &&
- [[enumerator nextObject] integerValue] == 123 &&
- [[[enumerator nextObject] stringValue] isEqual: @"Test"])
-
- EXPECT_EXCEPTION(@"Detection of invalid set",
- OFInvalidFormatException,
- [[OFData dataWithItems: "\x31\x06\x02\x01\x02\x02\x01\x01"
- count: 8] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated set #1",
- OFTruncatedDataException, [[OFData dataWithItems: "\x31\x01"
- count: 2] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated set #2",
- OFTruncatedDataException,
- [[OFData dataWithItems: "\x31\x04\x02\x01\x01\x00\x00"
- count: 7] ASN1DERValue])
-
- /* NumericString */
- TEST(@"Parsing of NumericString",
- [[[[OFData dataWithItems: "\x12\x0B" "12345 67890"
- count: 13] ASN1DERValue] numericStringValue]
- isEqual: @"12345 67890"] &&
- [[[[OFData dataWithItems: "\x12\x81\x80" "0000000000000000000000000"
- "0000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000"
- "00000000000000000000000"
- count: 131] ASN1DERValue] numericStringValue]
- isEqual: @"00000000000000000000000000000000000000000000000000000000"
- @"00000000000000000000000000000000000000000000000000000000"
- @"0000000000000000"])
-
- EXPECT_EXCEPTION(@"Detection of invalid NumericString",
- OFInvalidEncodingException,
- [[OFData dataWithItems: "\x12\x02."
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of out of range NumericString",
- OFOutOfRangeException,
- [[OFData dataWithItems: "\x12\x89"
- "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
- count: 11] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated NumericString",
- OFTruncatedDataException, [[OFData dataWithItems: "\x12\x01"
- count: 2] ASN1DERValue])
-
- /* PrintableString */
- TEST(@"Parsing of PrintableString",
- [[[[OFData dataWithItems: "\x13\x0CHello World."
- count: 14] ASN1DERValue] printableStringValue]
- isEqual: @"Hello World."] &&
- [[[[OFData dataWithItems: "\x13\x81\x80 '()+,-./:=?abcdefghijklmnop"
- "qrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ '()"
- "+,-./:=?abcdefghijklmnopqrstuvwxyzABCDEF"
- "GHIJKLMNOPQRSTUVWXYZ"
- count: 131] ASN1DERValue] printableStringValue]
- isEqual: @" '()+,-./:=?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR"
- @"STUVWXYZ '()+,-./:=?abcdefghijklmnopqrstuvwxyzABCDEFGHIJ"
- @"KLMNOPQRSTUVWXYZ"])
-
- EXPECT_EXCEPTION(@"Detection of invalid PrintableString",
- OFInvalidEncodingException,
- [[OFData dataWithItems: "\x13\x02;"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of out of range PrintableString",
- OFOutOfRangeException,
- [[OFData dataWithItems: "\x13\x89"
- "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
- count: 11] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated PrintableString",
- OFTruncatedDataException, [[OFData dataWithItems: "\x13\x01"
- count: 2] ASN1DERValue])
-
- /* IA5String */
- TEST(@"Parsing of IA5String",
- [[[[OFData dataWithItems: "\x16\x0CHello World!"
- count: 14] ASN1DERValue] IA5StringValue]
- isEqual: @"Hello World!"] &&
- [[[[OFData dataWithItems: "\x16\x81\x80xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- "xxxxxxxxxxxxxxxxxxxx"
- count: 131] ASN1DERValue] IA5StringValue]
- isEqual: @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- @"xxxxxxxxxxxxxxxx"])
-
- EXPECT_EXCEPTION(@"Detection of invalid IA5String",
- OFInvalidEncodingException,
- [[OFData dataWithItems: "\x16\x02ä"
- count: 4] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of out of range IA5String",
- OFOutOfRangeException,
- [[OFData dataWithItems: "\x16\x89"
- "\x01\x01\x01\x01\x01\x01\x01\x01\x01"
- count: 11] ASN1DERValue])
-
- EXPECT_EXCEPTION(@"Detection of truncated IA5String",
- OFTruncatedDataException, [[OFData dataWithItems: "\x16\x01"
- count: 2] ASN1DERValue])
-
- objc_autoreleasePoolPop(pool);
-}
-@end
Index: tests/OFArrayTests.m
==================================================================
--- tests/OFArrayTests.m
+++ tests/OFArrayTests.m
@@ -420,14 +420,14 @@
#endif
TEST(@"-[valueForKey:]",
[[[arrayClass arrayWithObjects: @"foo", @"bar", @"quxqux", nil]
valueForKey: @"length"] isEqual:
- [arrayClass arrayWithObjects: [OFNumber numberWithSize: 3],
- [OFNumber numberWithSize: 3], [OFNumber numberWithSize: 6], nil]] &&
+ [arrayClass arrayWithObjects: [OFNumber numberWithInt: 3],
+ [OFNumber numberWithInt: 3], [OFNumber numberWithInt: 6], nil]] &&
[[[arrayClass arrayWithObjects: @"1", @"2", nil]
- valueForKey: @"@count"] isEqual: [OFNumber numberWithSize: 2]])
+ valueForKey: @"@count"] isEqual: [OFNumber numberWithInt: 2]])
m[0] = [mutableArrayClass arrayWithObjects:
[OFMutableURL URLWithString: @"http://foo.bar/"],
[OFMutableURL URLWithString: @"http://bar.qux/"],
[OFMutableURL URLWithString: @"http://qux.quxqux/"], nil];
Index: tests/OFDictionaryTests.m
==================================================================
--- tests/OFDictionaryTests.m
+++ tests/OFDictionaryTests.m
@@ -180,11 +180,11 @@
[mutDict objectForKey: @"key3"] == nil)
TEST(@"-[valueForKey:]",
[[mutDict valueForKey: keys[0]] isEqual: values[0]] &&
[[mutDict valueForKey: @"@count"] isEqual:
- [OFNumber numberWithSize: 2]])
+ [OFNumber numberWithInt: 2]])
EXPECT_EXCEPTION(@"Catching -[setValue:forKey:] on immutable "
@"dictionary", OFUndefinedKeyException,
[[dictionaryClass dictionary] setValue: @"x"
forKey: @"x"])
Index: tests/OFJSONTests.m
==================================================================
--- tests/OFJSONTests.m
+++ tests/OFJSONTests.m
@@ -36,11 +36,11 @@
@"foo",
[OFNumber numberWithBool: false],
nil],
nil];
- TEST(@"-[JSONValue] #1", [s.JSONValue isEqual: d])
+ TEST(@"-[objectByParsingJSON] #1", [s.objectByParsingJSON isEqual: d])
TEST(@"-[JSONRepresentation]", [[d JSONRepresentation] isEqual:
@"{\"x\":[0.5,15,null,\"foo\",false],\"foo\":\"b\\na\\r\"}"])
TEST(@"OF_JSON_REPRESENTATION_PRETTY",
@@ -50,22 +50,22 @@
TEST(@"OF_JSON_REPRESENTATION_JSON5",
[[d JSONRepresentationWithOptions: OF_JSON_REPRESENTATION_JSON5]
isEqual: @"{x:[0.5,15,null,\"foo\",false],foo:\"b\\\na\\r\"}"])
- EXPECT_EXCEPTION(@"-[JSONValue] #2", OFInvalidJSONException,
- [@"{" JSONValue])
- EXPECT_EXCEPTION(@"-[JSONValue] #3", OFInvalidJSONException,
- [@"]" JSONValue])
- EXPECT_EXCEPTION(@"-[JSONValue] #4", OFInvalidJSONException,
- [@"bar" JSONValue])
- EXPECT_EXCEPTION(@"-[JSONValue] #5", OFInvalidJSONException,
- [@"[\"a\" \"b\"]" JSONValue])
-
- TEST(@"-[JSONValue] #6",
- [@"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
- .JSONValue isEqual: [OFArray arrayWithObject:
+ EXPECT_EXCEPTION(@"-[objectByParsingJSON] #2", OFInvalidJSONException,
+ [@"{" objectByParsingJSON])
+ EXPECT_EXCEPTION(@"-[objectByParsingJSON] #3", OFInvalidJSONException,
+ [@"]" objectByParsingJSON])
+ EXPECT_EXCEPTION(@"-[objectByParsingJSON] #4", OFInvalidJSONException,
+ [@"bar" objectByParsingJSON])
+ EXPECT_EXCEPTION(@"-[objectByParsingJSON] #5", OFInvalidJSONException,
+ [@"[\"a\" \"b\"]" objectByParsingJSON])
+
+ TEST(@"-[objectByParsingJSON] #6",
+ [@"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
+ .objectByParsingJSON isEqual: [OFArray arrayWithObject:
[OFArray arrayWithObject: [OFArray arrayWithObject:
[OFArray arrayWithObject: [OFArray arrayWithObject:
[OFArray arrayWithObject: [OFArray arrayWithObject:
[OFArray arrayWithObject: [OFArray arrayWithObject:
[OFArray arrayWithObject: [OFArray arrayWithObject:
@@ -79,12 +79,12 @@
[OFArray arrayWithObject: [OFArray arrayWithObject:
[OFArray arrayWithObject: [OFArray arrayWithObject:
[OFArray arrayWithObject:
[OFDictionary dictionary]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]])
- EXPECT_EXCEPTION(@"-[JSONValue] #7", OFInvalidJSONException,
+ EXPECT_EXCEPTION(@"-[objectByParsingJSON] #7", OFInvalidJSONException,
[@"[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"
- JSONValue])
+ objectByParsingJSON])
objc_autoreleasePoolPop(pool);
}
@end
Index: tests/OFNumberTests.m
==================================================================
--- tests/OFNumberTests.m
+++ tests/OFNumberTests.m
@@ -25,15 +25,15 @@
- (void)numberTests
{
void *pool = objc_autoreleasePoolPush();
OFNumber *num;
- TEST(@"+[numberWithIntMax:]",
- (num = [OFNumber numberWithIntMax: 123456789]))
+ TEST(@"+[numberWithLongLong:]",
+ (num = [OFNumber numberWithLongLong: 123456789]))
TEST(@"-[isEqual:]",
- [num isEqual: [OFNumber numberWithUInt32: 123456789]])
+ [num isEqual: [OFNumber numberWithLong: 123456789]])
TEST(@"-[hash]", num.hash == 0x82D8BC42)
TEST(@"-[charValue]", num.charValue == 21)
Index: tests/OFPropertyListTests.m
==================================================================
--- tests/OFPropertyListTests.m
+++ tests/OFPropertyListTests.m
@@ -68,52 +68,54 @@
[OFNumber numberWithBool: false],
[OFNumber numberWithFloat: 12.25],
[OFNumber numberWithInt: -10],
nil];
- TEST(@"-[propertyListValue:] #1",
- [PLIST1.propertyListValue isEqual: @"Hello"])
-
- TEST(@"-[propertyListValue:] #2",
- [PLIST2.propertyListValue isEqual: array])
-
- TEST(@"-[propertyListValue:] #3",
- [PLIST3.propertyListValue isEqual:
+ TEST(@"-[objectByParsingPropertyList:] #1",
+ [PLIST1.objectByParsingPropertyList isEqual: @"Hello"])
+
+ TEST(@"-[objectByParsingPropertyList:] #2",
+ [PLIST2.objectByParsingPropertyList isEqual: array])
+
+ TEST(@"-[objectByParsingPropertyList:] #3",
+ [PLIST3.objectByParsingPropertyList isEqual:
[OFDictionary dictionaryWithKeysAndObjects:
@"array", array,
@"foo", @"bar",
nil]])
- EXPECT_EXCEPTION(@"-[propertyListValue] detecting unsupported version",
+ EXPECT_EXCEPTION(@"Detecting unsupported version",
OFUnsupportedVersionException,
[[PLIST(@"") stringByReplacingOccurrencesOfString: @"1.0"
withString: @"1.1"]
- propertyListValue])
-
- EXPECT_EXCEPTION(
- @"-[propertyListValue] detecting invalid format #1",
- OFInvalidFormatException,
- [PLIST(@"") propertyListValue])
-
- EXPECT_EXCEPTION(
- @"-[propertyListValue] detecting invalid format #2",
- OFInvalidFormatException,
- [PLIST(@"") propertyListValue])
-
- EXPECT_EXCEPTION(
- @"-[propertyListValue] detecting invalid format #3",
- OFInvalidFormatException,
- [PLIST(@"") propertyListValue])
-
- EXPECT_EXCEPTION(
- @"-[propertyListValue] detecting invalid format #4",
- OFInvalidFormatException,
- [PLIST(@"") propertyListValue])
-
- EXPECT_EXCEPTION(
- @"-[propertyListValue] detecting invalid format #5",
- OFInvalidFormatException,
- [PLIST(@"") propertyListValue])
+ objectByParsingPropertyList])
+
+ EXPECT_EXCEPTION(
+ @"-[objectByParsingPropertyList] detecting invalid format #1",
+ OFInvalidFormatException,
+ [PLIST(@"") objectByParsingPropertyList])
+
+ EXPECT_EXCEPTION(
+ @"-[objectByParsingPropertyList] detecting invalid format #2",
+ OFInvalidFormatException,
+ [PLIST(@"") objectByParsingPropertyList])
+
+ EXPECT_EXCEPTION(
+ @"-[objectByParsingPropertyList] detecting invalid format #3",
+ OFInvalidFormatException,
+ [PLIST(@"") objectByParsingPropertyList])
+
+ EXPECT_EXCEPTION(
+ @"-[objectByParsingPropertyList] detecting invalid format #4",
+ OFInvalidFormatException,
+ [PLIST(@"")
+ objectByParsingPropertyList])
+
+ EXPECT_EXCEPTION(
+ @"-[objectByParsingPropertyList] detecting invalid format #5",
+ OFInvalidFormatException,
+ [PLIST(@"")
+ objectByParsingPropertyList])
objc_autoreleasePoolPop(pool);
}
@end
Index: tests/OFSetTests.m
==================================================================
--- tests/OFSetTests.m
+++ tests/OFSetTests.m
@@ -276,14 +276,14 @@
TEST(@"Detection of mutation during Fast Enumeration", ok);
TEST(@"-[valueForKey:]",
[(set1 = [[setClass setWithObjects: @"a", @"ab", @"abc", @"b", nil]
valueForKey: @"length"]) isEqual: [setClass setWithObjects:
- [OFNumber numberWithSize: 1], [OFNumber numberWithSize: 2],
- [OFNumber numberWithSize: 3], nil]] &&
+ [OFNumber numberWithInt: 1], [OFNumber numberWithInt: 2],
+ [OFNumber numberWithInt: 3], nil]] &&
[[set1 valueForKey: @"@count"] isEqual:
- [OFNumber numberWithSize: 3]])
+ [OFNumber numberWithInt: 3]])
objc_autoreleasePoolPop(pool);
}
- (void)setTests
Index: tests/OFStringTests.m
==================================================================
--- tests/OFStringTests.m
+++ tests/OFStringTests.m
@@ -1067,28 +1067,33 @@
[C(@"c:\\..\\asd").stringByStandardizingPath
isEqual: @"c:\\..\\asd"])
# endif
#endif
- TEST(@"-[decimalValue]",
- C(@"1234").decimalValue == 1234 &&
- C(@"\r\n+123 ").decimalValue == 123 &&
- C(@"-500\t").decimalValue == -500 &&
- C(@"\t\t\r\n").decimalValue == 0)
-
- TEST(@"-[hexadecimalValue]",
- C(@"123f").hexadecimalValue == 0x123f &&
- C(@"\t\n0xABcd\r").hexadecimalValue == 0xABCD &&
- C(@" xbCDE").hexadecimalValue == 0xBCDE &&
- C(@"$CdEf").hexadecimalValue == 0xCDEF &&
- C(@"\rFeh ").hexadecimalValue == 0xFE &&
- C(@"\r\t").hexadecimalValue == 0)
-
- TEST(@"-[octalValue]",
- C(@"1234567").octalValue == 01234567 &&
- C(@"\r\n123").octalValue == 0123 &&
- C(@"765\t").octalValue == 0765 && C(@"\t\t\r\n").octalValue == 0)
+ TEST(@"-[longLongValue]",
+ C(@"1234").longLongValue == 1234 &&
+ C(@"\r\n+123 ").longLongValue == 123 &&
+ C(@"-500\t").longLongValue == -500 &&
+ [C(@"-0x10\t") longLongValueWithBase: 0] == -0x10 &&
+ C(@"\t\t\r\n").longLongValue == 0 &&
+ [C(@"123f") longLongValueWithBase: 16] == 0x123f &&
+ [C(@"\t\n0xABcd\r") longLongValueWithBase: 0] == 0xABCD &&
+ [C(@"1234567") longLongValueWithBase: 8] == 01234567 &&
+ [C(@"\r\n0123") longLongValueWithBase: 0] == 0123 &&
+ [C(@"765\t") longLongValueWithBase: 8] == 0765 &&
+ [C(@"\t\t\r\n") longLongValueWithBase: 8] == 0)
+
+ TEST(@"-[unsignedLongLongValue]",
+ C(@"1234").unsignedLongLongValue == 1234 &&
+ C(@"\r\n+123 ").unsignedLongLongValue == 123 &&
+ C(@"\t\t\r\n").unsignedLongLongValue == 0 &&
+ [C(@"123f") unsignedLongLongValueWithBase: 16] == 0x123f &&
+ [C(@"\t\n0xABcd\r") unsignedLongLongValueWithBase: 0] == 0xABCD &&
+ [C(@"1234567") unsignedLongLongValueWithBase: 8] == 01234567 &&
+ [C(@"\r\n0123") unsignedLongLongValueWithBase: 0] == 0123 &&
+ [C(@"765\t") unsignedLongLongValueWithBase: 8] == 0765 &&
+ [C(@"\t\t\r\n") unsignedLongLongValueWithBase: 8] == 0)
/*
* These test numbers can be generated without rounding if we have IEEE
* floating point numbers, thus we can use == on them.
*/
@@ -1107,11 +1112,11 @@
# if (!defined(OF_SOLARIS) || !defined(OF_X86)) && !defined(OF_AMIGAOS_M68K)
# define INPUT @"\t-0.123456789 "
# define EXPECTED -0.123456789
# else
/*
- * Solaris' strtod() has weird rounding on x86, but not on x86_64/
+ * Solaris' strtod() has weird rounding on x86, but not on x86_64.
* AmigaOS 3 with libnix has weird rounding as well.
*/
# define INPUT @"\t-0.125 "
# define EXPECTED -0.125
# endif
@@ -1122,25 +1127,21 @@
C(@"\r -INFINITY\n").doubleValue == -INFINITY &&
isnan(C(@" NAN\t\t").doubleValue))
#undef INPUT
#undef EXPECTED
- EXPECT_EXCEPTION(@"Detect invalid characters in -[decimalValue] #1",
- OFInvalidFormatException, [C(@"abc") decimalValue])
- EXPECT_EXCEPTION(@"Detect invalid characters in -[decimalValue] #2",
- OFInvalidFormatException, [C(@"0a") decimalValue])
- EXPECT_EXCEPTION(@"Detect invalid characters in -[decimalValue] #3",
- OFInvalidFormatException, [C(@"0 1") decimalValue])
-
- EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #1",
- OFInvalidFormatException, [C(@"0xABCDEFG") hexadecimalValue])
- EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #2",
- OFInvalidFormatException, [C(@"0x") hexadecimalValue])
- EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #3",
- OFInvalidFormatException, [C(@"$") hexadecimalValue])
- EXPECT_EXCEPTION(@"Detect invalid chars in -[hexadecimalValue] #4",
- OFInvalidFormatException, [C(@"$ ") hexadecimalValue])
+ EXPECT_EXCEPTION(@"Detect invalid chars in -[longLongValue] #1",
+ OFInvalidFormatException, [C(@"abc") longLongValue])
+ EXPECT_EXCEPTION(@"Detect invalid chars in -[longLongValue] #2",
+ OFInvalidFormatException, [C(@"0a") longLongValue])
+ EXPECT_EXCEPTION(@"Detect invalid chars in -[longLongValue] #3",
+ OFInvalidFormatException, [C(@"0 1") longLongValue])
+ EXPECT_EXCEPTION(@"Detect invalid chars in -[longLongValue] #4",
+ OFInvalidFormatException,
+ [C(@"0xABCDEFG") longLongValueWithBase: 0])
+ EXPECT_EXCEPTION(@"Detect invalid chars in -[longLongValue] #5",
+ OFInvalidFormatException, [C(@"0x") longLongValueWithBase: 0])
EXPECT_EXCEPTION(@"Detect invalid chars in -[floatValue] #1",
OFInvalidFormatException, [C(@"0.0a") floatValue])
EXPECT_EXCEPTION(@"Detect invalid chars in -[floatValue] #2",
OFInvalidFormatException, [C(@"0 0") floatValue])
@@ -1164,21 +1165,21 @@
*/
EXPECT_EXCEPTION(@"Detect invalid chars in -[doubleValue] #3",
OFInvalidFormatException, [C(@"0,0") doubleValue])
#endif
- EXPECT_EXCEPTION(@"Detect out of range in -[decimalValue]",
+ EXPECT_EXCEPTION(@"Detect out of range in -[longLongValue]",
OFOutOfRangeException,
- [C(@"12345678901234567890123456789012345678901234567890"
+ [C(@"-12345678901234567890123456789012345678901234567890"
@"12345678901234567890123456789012345678901234567890")
- decimalValue])
+ longLongValueWithBase: 16])
- EXPECT_EXCEPTION(@"Detect out of range in -[hexadecimalValue]",
+ EXPECT_EXCEPTION(@"Detect out of range in -[unsignedLongLongValue]",
OFOutOfRangeException,
[C(@"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
@"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")
- hexadecimalValue])
+ unsignedLongLongValueWithBase: 16])
TEST(@"-[characters]", (ua = C(@"fööbär🀺").characters) &&
!memcmp(ua, ucstr + 1, sizeof(ucstr) - 8))
#ifdef OF_BIG_ENDIAN
Index: tests/OFURLTests.m
==================================================================
--- tests/OFURLTests.m
+++ tests/OFURLTests.m
@@ -154,13 +154,12 @@
TEST(@"-[password]",
[u1.password isEqual: @"p@w"] && u4.password == nil)
TEST(@"-[host]", [u1.host isEqual: @"ho:st"] &&
[u6.host isEqual: @"12:34::56:abcd"] &&
[u7.host isEqual: @"12:34::56:abcd"])
- TEST(@"-[port]", [u1.port isEqual: [OFNumber numberWithUInt16: 1234]] &&
- [u4 port] == nil &&
- [u7.port isEqual: [OFNumber numberWithUInt16: 234]])
+ TEST(@"-[port]", u1.port.unsignedShortValue == 1234 &&
+ [u4 port] == nil && u7.port.unsignedShortValue == 234)
TEST(@"-[path]",
[u1.path isEqual: @"/pa?th"] && [u4.path isEqual: @"/etc/passwd"])
TEST(@"-[pathComponents]",
[u1.pathComponents isEqual:
[OFArray arrayWithObjects: @"/", @"pa?th", nil]] &&
Index: tests/TestsAppDelegate.h
==================================================================
--- tests/TestsAppDelegate.h
+++ tests/TestsAppDelegate.h
@@ -68,12 +68,12 @@
inModule: (OFString *)module;
- (void)outputFailure: (OFString *)test
inModule: (OFString *)module;
@end
-@interface TestsAppDelegate (OFASN1DERValueTests)
-- (void)ASN1DERValueTests;
+@interface TestsAppDelegate (OFASN1DERParsingTests)
+- (void)ASN1DERParsingTests;
@end
@interface TestsAppDelegate (OFASN1DERRepresentationTests)
- (void)ASN1DERRepresentationTests;
@end
Index: tests/TestsAppDelegate.m
==================================================================
--- tests/TestsAppDelegate.m
+++ tests/TestsAppDelegate.m
@@ -378,11 +378,11 @@
#ifdef OF_HAVE_FILES
[self serializationTests];
#endif
[self JSONTests];
[self propertyListTests];
- [self ASN1DERValueTests];
+ [self ASN1DERParsingTests];
[self ASN1DERRepresentationTests];
#if defined(OF_HAVE_PLUGINS)
[self pluginTests];
#endif
#ifdef OF_WINDOWS
Index: tests/iOS.xcodeproj/project.pbxproj
==================================================================
--- tests/iOS.xcodeproj/project.pbxproj
+++ tests/iOS.xcodeproj/project.pbxproj
@@ -304,11 +304,11 @@
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
OTHER_LDFLAGS = "-ObjC";
- PRODUCT_BUNDLE_IDENTIFIER = zone.heap.objfw.tests;
+ PRODUCT_BUNDLE_IDENTIFIER = im.nil.objfw.tests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
@@ -324,11 +324,11 @@
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
OTHER_LDFLAGS = "-ObjC";
- PRODUCT_BUNDLE_IDENTIFIER = zone.heap.objfw.tests;
+ PRODUCT_BUNDLE_IDENTIFIER = im.nil.objfw.tests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
Index: tests/plugin/Info.plist.in
==================================================================
--- tests/plugin/Info.plist.in
+++ tests/plugin/Info.plist.in
@@ -5,11 +5,11 @@
CFBundleExecutable
TestPlugin
CFBundleName
TestPlugin
CFBundleIdentifier
- zone.heap.objfw.testplugin
+ im.nil.objfw.tests.plugin
CFBundleInfoDictionaryVersion
6.0
CFBundlePackageType
BNDL
CFBundleVersion
Index: tests/serialization.xml
==================================================================
--- tests/serialization.xml
+++ tests/serialization.xml
@@ -15,11 +15,11 @@
Qu"xbar
test
- 1234
+ 1234
40934a456d5cfaad
asd
40934a456d5cfaad
Index: utils/ofarc/LHAArchive.m
==================================================================
--- utils/ofarc/LHAArchive.m
+++ utils/ofarc/LHAArchive.m
@@ -44,10 +44,13 @@
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
OFNumber *mode = entry.mode;
if (mode == nil)
return;
+
+ mode = [OFNumber numberWithUnsignedShort:
+ mode.unsignedShortValue & 0777];
of_file_attributes_t attributes = [OFDictionary
dictionaryWithObject: mode
forKey: of_file_attribute_key_posix_permissions];
@@ -143,28 +146,28 @@
@"%04" PRIX16, entry.CRC16];
[of_stdout writeString: @"\t"];
[of_stdout writeLine: OF_LOCALIZED(
@"list_compressed_size",
- [@"["
- @" 'Compressed: ',"
- @" ["
- @" {'size == 1': '1 byte'},"
- @" {'': '%[size] bytes'}"
- @" ]"
- @"]" JSONValue],
+ @"["
+ @" 'Compressed: ',"
+ @" ["
+ @" {'size == 1': '1 byte'},"
+ @" {'': '%[size] bytes'}"
+ @" ]"
+ @"]".objectByParsingJSON,
@"size", compressedSize)];
[of_stdout writeString: @"\t"];
[of_stdout writeLine: OF_LOCALIZED(
@"list_uncompressed_size",
- [@"["
- @" 'Uncompressed: ',"
- @" ["
- @" {'size == 1': '1 byte'},"
- @" {'': '%[size] bytes'}"
- @" ]"
- @"]" JSONValue],
+ @"["
+ @" 'Uncompressed: ',"
+ @" ["
+ @" {'size == 1': '1 byte'},"
+ @" {'': '%[size] bytes'}"
+ @" ]"
+ @"]".objectByParsingJSON,
@"size", uncompressedSize)];
[of_stdout writeString: @"\t"];
[of_stdout writeLine: OF_LOCALIZED(
@"list_compression_method",
@"Compression method: %[method]",
@@ -179,11 +182,11 @@
@"date", date)];
if (entry.mode != nil) {
OFString *modeString = [OFString
stringWithFormat:
- @"%" PRIo16, entry.mode.uInt16Value];
+ @"%ho", entry.mode.unsignedShortValue];
[of_stdout writeString: @"\t"];
[of_stdout writeLine: OF_LOCALIZED(@"list_mode",
@"Mode: %[mode]",
@"mode", modeString)];
@@ -467,20 +470,20 @@
attributes = [fileManager attributesOfItemAtPath: fileName];
type = attributes.fileType;
entry = [OFMutableLHAArchiveEntry entryWithFileName: fileName];
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
- entry.mode = [OFNumber numberWithUInt16:
+ entry.mode = [OFNumber numberWithUnsignedLong:
attributes.filePOSIXPermissions];
#endif
entry.date = attributes.fileModificationDate;
#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER
entry.UID =
- [OFNumber numberWithUInt16: attributes.filePOSIXUID];
+ [OFNumber numberWithUnsignedLong: attributes.filePOSIXUID];
entry.GID =
- [OFNumber numberWithUInt16: attributes.filePOSIXGID];
+ [OFNumber numberWithUnsignedLong: attributes.filePOSIXGID];
entry.owner = attributes.fileOwner;
entry.group = attributes.fileGroup;
#endif
if ([type isEqual: of_file_type_directory])
@@ -487,11 +490,12 @@
entry.compressionMethod = @"-lhd-";
output = [_archive streamForWritingEntry: entry];
if ([type isEqual: of_file_type_regular]) {
- uintmax_t written = 0, size = attributes.fileSize;
+ unsigned long long written = 0;
+ unsigned long long size = attributes.fileSize;
int8_t percent = -1, newPercent;
OFFile *input = [OFFile fileWithPath: fileName
mode: @"r"];
Index: utils/ofarc/TarArchive.m
==================================================================
--- utils/ofarc/TarArchive.m
+++ utils/ofarc/TarArchive.m
@@ -33,12 +33,13 @@
static void
setPermissions(OFString *path, OFTarArchiveEntry *entry)
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
+ OFNumber *mode = [OFNumber numberWithUnsignedShort: entry.mode & 0777];
of_file_attributes_t attributes = [OFDictionary
- dictionaryWithObject: [OFNumber numberWithUInt16: entry.mode]
+ dictionaryWithObject: mode
forKey: of_file_attribute_key_posix_permissions];
[[OFFileManager defaultManager] setAttributes: attributes
ofItemAtPath: path];
#endif
@@ -124,17 +125,17 @@
OFString *GID = [OFString stringWithFormat:
@"%u", entry.GID];
[of_stdout writeString: @"\t"];
[of_stdout writeLine: OF_LOCALIZED(@"list_size",
- [@"["
- @" 'Size: ',"
- @" ["
- @" {'size == 1': '1 byte'},"
- @" {'': '%[size] bytes'}"
- @" ]"
- @"]" JSONValue],
+ @"["
+ @" 'Size: ',"
+ @" ["
+ @" {'size == 1': '1 byte'},"
+ @" {'': '%[size] bytes'}"
+ @" ]"
+ @"]".objectByParsingJSON,
@"size", size)];
[of_stdout writeString: @"\t"];
[of_stdout writeLine: OF_LOCALIZED(@"list_mode",
@"Mode: %[mode]",
@"mode", mode)];
Index: utils/ofarc/ZIPArchive.m
==================================================================
--- utils/ofarc/ZIPArchive.m
+++ utils/ofarc/ZIPArchive.m
@@ -42,15 +42,16 @@
setPermissions(OFString *path, OFZIPArchiveEntry *entry)
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
if ((entry.versionMadeBy >> 8) ==
OF_ZIP_ARCHIVE_ENTRY_ATTR_COMPAT_UNIX) {
- uint16_t mode = entry.versionSpecificAttributes >> 16;
+ OFNumber *mode = [OFNumber numberWithUnsignedShort:
+ (entry.versionSpecificAttributes >> 16) & 0777];
of_file_attribute_key_t key =
of_file_attribute_key_posix_permissions;
of_file_attributes_t attributes = [OFDictionary
- dictionaryWithObject: [OFNumber numberWithUInt16: mode]
+ dictionaryWithObject: mode
forKey: key];
[[OFFileManager defaultManager] setAttributes: attributes
ofItemAtPath: path];
}
@@ -136,28 +137,28 @@
localDateStringWithFormat: @"%Y-%m-%d %H:%M:%S"];
[of_stdout writeString: @"\t"];
[of_stdout writeLine: OF_LOCALIZED(
@"list_compressed_size",
- [@"["
- @" 'Compressed: ',"
- @" ["
- @" {'size == 1': '1 byte'},"
- @" {'': '%[size] bytes'}"
- @" ]"
- @"]" JSONValue],
+ @"["
+ @" 'Compressed: ',"
+ @" ["
+ @" {'size == 1': '1 byte'},"
+ @" {'': '%[size] bytes'}"
+ @" ]"
+ @"]".objectByParsingJSON,
@"size", compressedSize)];
[of_stdout writeString: @"\t"];
[of_stdout writeLine: OF_LOCALIZED(
@"list_uncompressed_size",
- [@"["
- @" 'Uncompressed: ',"
- @" ["
- @" {'size == 1': '1 byte'},"
- @" {'': '%[size] bytes'}"
- @" ]"
- @"]" JSONValue],
+ @"["
+ @" 'Uncompressed: ',"
+ @" ["
+ @" {'size == 1': '1 byte'},"
+ @" {'': '%[size] bytes'}"
+ @" ]"
+ @"]".objectByParsingJSON,
@"size", uncompressedSize)];
[of_stdout writeString: @"\t"];
[of_stdout writeLine: OF_LOCALIZED(
@"list_compression_method",
@"Compression method: %[method]",
@@ -419,11 +420,11 @@
OFArray OF_GENERIC (OFString *) *components;
OFString *fileName;
of_file_attributes_t attributes;
bool isDirectory = false;
OFMutableZIPArchiveEntry *entry;
- uintmax_t size;
+ unsigned long long size;
OFStream *output;
components = localFileName.pathComponents;
fileName = [components componentsJoinedByString: @"/"];
@@ -456,11 +457,11 @@
[entry makeImmutable];
output = [_archive streamForWritingEntry: entry];
if (!isDirectory) {
- uintmax_t written = 0;
+ unsigned long long written = 0;
int8_t percent = -1, newPercent;
OFFile *input = [OFFile fileWithPath: fileName
mode: @"r"];
Index: utils/ofhttp/OFHTTP.m
==================================================================
--- utils/ofhttp/OFHTTP.m
+++ utils/ofhttp/OFHTTP.m
@@ -26,10 +26,13 @@
#import "OFHTTPClient.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFLocale.h"
#import "OFOptionsParser.h"
+#ifdef OF_HAVE_PLUGINS
+# import "OFPlugin.h"
+#endif
#import "OFSandbox.h"
#import "OFStdIOStream.h"
#import "OFSystemInfo.h"
#import "OFTCPSocket.h"
#import "OFTLSSocket.h"
@@ -67,11 +70,11 @@
of_http_request_method_t _method;
OFMutableDictionary *_clientHeaders;
OFHTTPClient *_HTTPClient;
char *_buffer;
OFStream *_output;
- intmax_t _received, _length, _resumedFrom;
+ unsigned long long _received, _length, _resumedFrom;
ProgressBar *_progressBar;
}
- (void)downloadNextURL;
@end
@@ -272,10 +275,21 @@
objc_autoreleasePoolPop(pool);
return [fileName autorelease];
}
@implementation OFHTTP
+#ifdef OF_HAVE_PLUGINS
++ (void)initialize
+{
+ if (self != [OFHTTP class])
+ return;
+
+ /* Opportunistically try loading ObjOpenSSL and ignore any errors. */
+ of_dlopen(@"objopenssl", OF_RTLD_LAZY);
+}
+#endif
+
- (instancetype)init
{
self = [super init];
@try {
@@ -332,11 +346,12 @@
else {
_body = [[OFFile alloc] initWithPath: path
mode: @"r"];
@try {
- uintmax_t fileSize = [[OFFileManager defaultManager]
+ unsigned long long fileSize =
+ [[OFFileManager defaultManager]
attributesOfItemAtPath: path].fileSize;
contentLength =
[OFString stringWithFormat: @"%ju", fileSize];
[_clientHeaders setObject: contentLength
@@ -374,18 +389,18 @@
@try {
size_t pos = [proxy
rangeOfString: @":"
options: OF_STRING_SEARCH_BACKWARDS].location;
OFString *host;
- intmax_t port;
+ unsigned long long port;
if (pos == OF_NOT_FOUND)
@throw [OFInvalidFormatException exception];
host = [proxy substringWithRange: of_range(0, pos)];
- port = [proxy substringWithRange:
- of_range(pos + 1, proxy.length - pos - 1)].decimalValue;
+ port = [proxy substringWithRange: of_range(pos + 1,
+ proxy.length - pos - 1)].unsignedLongLongValue;
if (port > UINT16_MAX)
@throw [OFOutOfRangeException exception];
[OFTCPSocket setSOCKS5Host: host];
@@ -719,12 +734,15 @@
[_progressBar stop];
[_progressBar draw];
[_progressBar release];
_progressBar = nil;
- if (!_quiet)
- [of_stdout writeString: @"\n Error!\n"];
+ if (!_quiet) {
+ [of_stdout writeString: @"\n "];
+ [of_stdout writeLine: OF_LOCALIZED(@"download_error",
+ @"Error!")];
+ }
URL = [_URLs objectAtIndex: _URLIndex - 1];
[of_stderr writeLine: OF_LOCALIZED(
@"download_failed_exception",
@"%[prog]: Failed to download <%[url]>!\n"
@@ -783,11 +801,11 @@
if (type == nil)
type = OF_LOCALIZED(@"type_unknown", @"unknown");
if (lengthString != nil) {
- _length = lengthString.decimalValue;
+ _length = lengthString.unsignedLongLongValue;
if (_resumedFrom + _length >= GIBIBYTE) {
lengthString = [OFString stringWithFormat:
@"%,.2f",
(float)(_resumedFrom + _length) / GIBIBYTE];
@@ -810,16 +828,16 @@
@"num", lengthString);
} else {
lengthString = [OFString stringWithFormat:
@"%jd", _resumedFrom + _length];
lengthString = OF_LOCALIZED(@"size_bytes",
- [@"["
- @" ["
- @" {'num == 1': '1 byte'},"
- @" {'': '%[num] bytes'}"
- @" ]"
- @"]" JSONValue],
+ @"["
+ @" ["
+ @" {'num == 1': '1 byte'},"
+ @" {'': '%[num] bytes'}"
+ @" ]"
+ @"]".objectByParsingJSON,
@"num", lengthString);
}
} else
lengthString =
OF_LOCALIZED(@"size_unknown", @"unknown");
@@ -1008,18 +1026,19 @@
if (_currentFileName == nil)
_currentFileName = [URL.path.lastPathComponent copy];
if (_continue) {
@try {
- uintmax_t size = [[OFFileManager defaultManager]
+ unsigned long long size =
+ [[OFFileManager defaultManager]
attributesOfItemAtPath: _currentFileName].fileSize;
OFString *range;
- if (size > INTMAX_MAX)
+ if (size > ULLONG_MAX)
@throw [OFOutOfRangeException exception];
- _resumedFrom = (intmax_t)size;
+ _resumedFrom = (unsigned long long)size;
range = [OFString stringWithFormat: @"bytes=%jd-",
_resumedFrom];
[clientHeaders setObject: range
forKey: @"Range"];
Index: utils/ofhttp/ProgressBar.h
==================================================================
--- utils/ofhttp/ProgressBar.h
+++ utils/ofhttp/ProgressBar.h
@@ -17,23 +17,27 @@
#import "OFObject.h"
@class OFDate;
@class OFTimer;
+
+#define BPS_WINDOW_SIZE 10
@interface ProgressBar: OFObject
{
- intmax_t _received, _lastReceived, _length, _resumedFrom;
+ unsigned long long _received, _lastReceived, _length, _resumedFrom;
OFDate *_startDate, *_lastReceivedDate;
OFTimer *_drawTimer, *_BPSTimer;
bool _stopped;
float _BPS;
double _ETA;
+ float _BPSWindow[BPS_WINDOW_SIZE];
+ size_t _BPSWindowIndex, _BPSWindowLength;
}
-- (instancetype)initWithLength: (intmax_t)length
- resumedFrom: (intmax_t)resumedFrom;
-- (void)setReceived: (intmax_t)received;
+- (instancetype)initWithLength: (unsigned long long)length
+ resumedFrom: (unsigned long long)resumedFrom;
+- (void)setReceived: (unsigned long long)received;
- (void)draw;
- (void)calculateBPSAndETA;
- (void)stop;
@end
Index: utils/ofhttp/ProgressBar.m
==================================================================
--- utils/ofhttp/ProgressBar.m
+++ utils/ofhttp/ProgressBar.m
@@ -31,12 +31,12 @@
#define KIBIBYTE (1024)
#define UPDATE_INTERVAL 0.1
@implementation ProgressBar
-- (instancetype)initWithLength: (intmax_t)length
- resumedFrom: (intmax_t)resumedFrom
+- (instancetype)initWithLength: (unsigned long long)length
+ resumedFrom: (unsigned long long)resumedFrom
{
self = [super init];
@try {
void *pool = objc_autoreleasePoolPush();
@@ -76,11 +76,11 @@
[_BPSTimer release];
[super dealloc];
}
-- (void)setReceived: (intmax_t)received
+- (void)setReceived: (unsigned long long)received
{
_received = received;
}
- (void)_drawProgress
@@ -202,16 +202,16 @@
@"num", num)];
} else {
OFString *num = [OFString stringWithFormat:
@"%jd", _resumedFrom + _received];
[of_stdout writeString: OF_LOCALIZED(@"progress_bytes",
- [@"["
- @" ["
- @" {'num == 1': '1 byte '},"
- @" {'': '%[num] bytes'}"
- @" ]"
- @"]" JSONValue],
+ @"["
+ @" ["
+ @" {'num == 1': '1 byte '},"
+ @" {'': '%[num] bytes'}"
+ @" ]"
+ @"]".objectByParsingJSON,
@"num", num)];
}
[of_stdout writeString: @" "];
@@ -254,12 +254,22 @@
[self _drawReceived];
}
- (void)calculateBPSAndETA
{
- _BPS = (float)(_received - _lastReceived) /
+ _BPSWindow[_BPSWindowIndex++ % BPS_WINDOW_SIZE] =
+ (float)(_received - _lastReceived) /
-(float)_lastReceivedDate.timeIntervalSinceNow;
+
+ if (_BPSWindowLength < BPS_WINDOW_SIZE)
+ _BPSWindowLength++;
+
+ _BPS = 0;
+ for (size_t i = 0; i < _BPSWindowLength; i++)
+ _BPS += _BPSWindow[i];
+ _BPS /= _BPSWindowLength;
+
_ETA = (double)(_length - _received) / _BPS;
_lastReceived = _received;
[_lastReceivedDate release];
_lastReceivedDate = [[OFDate alloc] init];
Index: utils/ofhttp/lang/de.json
==================================================================
--- utils/ofhttp/lang/de.json
+++ utils/ofhttp/lang/de.json
@@ -66,10 +66,11 @@
],
"download_failed": [
"%[prog]: Fehler beim Download von <%[url]>!\n",
" HTTP Status-Code: %[code]"
],
+ "download_error": "Fehler!",
"download_failed_exception": [
"%[prog]: Fehler beim Download von <%[url]>!\n",
" %[exception]"
],
"download_done": "Fertig!",
Index: utils/ofsock/OFSock.m
==================================================================
--- utils/ofsock/OFSock.m
+++ utils/ofsock/OFSock.m
@@ -60,11 +60,11 @@
[of_stderr writeLine: @"Need a port!"];
[OFApplication terminateWithStatus: 1];
}
[sock connectToHost: URL.host
- port: URL.port.uInt16Value];
+ port: URL.port.shortValue];
return [OFPair pairWithFirstObject: sock
secondObject: sock];
}