Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -943,10 +943,24 @@ 4BB4B54716775FF4002A2DCE /* OFHTTPServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4B54216775FF4002A2DCE /* OFHTTPServer.m */; }; 4BB4B54A16776094002A2DCE /* OFHTTPClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB4B54916776094002A2DCE /* OFHTTPClientTests.m */; }; 4BB524C1143D1E4E0085FBCC /* OFProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB524BF143D1E4E0085FBCC /* OFProcess.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BB524C2143D1E4E0085FBCC /* OFProcess.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB524C0143D1E4E0085FBCC /* OFProcess.m */; settings = {ATTRIBUTES = (Public, ); }; }; 4BB52CC717B8EA7F00B7EBF5 /* codepage_437.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB52CC617B8EA7F00B7EBF5 /* codepage_437.m */; }; + 4BB99CDA1FAEC9DA00CC79A9 /* OFCharacterSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB99CD61FAEC9D900CC79A9 /* OFCharacterSet.m */; }; + 4BB99CDB1FAEC9DA00CC79A9 /* OFCharacterSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB99CD61FAEC9D900CC79A9 /* OFCharacterSet.m */; }; + 4BB99CDC1FAEC9DA00CC79A9 /* OFCharacterSet_bitset.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB99CD71FAEC9D900CC79A9 /* OFCharacterSet_bitset.h */; }; + 4BB99CDD1FAEC9DA00CC79A9 /* OFCharacterSet_bitset.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB99CD71FAEC9D900CC79A9 /* OFCharacterSet_bitset.h */; }; + 4BB99CDE1FAEC9DA00CC79A9 /* OFCharacterSet_bitset.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB99CD81FAEC9DA00CC79A9 /* OFCharacterSet_bitset.m */; }; + 4BB99CDF1FAEC9DA00CC79A9 /* OFCharacterSet_bitset.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB99CD81FAEC9DA00CC79A9 /* OFCharacterSet_bitset.m */; }; + 4BB99CE01FAEC9DA00CC79A9 /* OFCharacterSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB99CD91FAEC9DA00CC79A9 /* OFCharacterSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BB99CE11FAEC9DA00CC79A9 /* OFCharacterSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB99CD91FAEC9DA00CC79A9 /* OFCharacterSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BB99CE41FAF542000CC79A9 /* OFCharacterSet_range.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB99CE21FAF542000CC79A9 /* OFCharacterSet_range.h */; }; + 4BB99CE51FAF542000CC79A9 /* OFCharacterSet_range.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB99CE21FAF542000CC79A9 /* OFCharacterSet_range.h */; }; + 4BB99CE61FAF542000CC79A9 /* OFCharacterSet_range.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB99CE31FAF542000CC79A9 /* OFCharacterSet_range.m */; }; + 4BB99CE71FAF542000CC79A9 /* OFCharacterSet_range.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB99CE31FAF542000CC79A9 /* OFCharacterSet_range.m */; }; + 4BB99CE91FAF77BC00CC79A9 /* OFCharacterSetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB99CE81FAF77BC00CC79A9 /* OFCharacterSetTests.m */; }; + 4BB99CEA1FAF77BC00CC79A9 /* OFCharacterSetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB99CE81FAF77BC00CC79A9 /* OFCharacterSetTests.m */; }; 4BC090441584F6760040640F /* OFInvalidJSONException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC090421584F6760040640F /* OFInvalidJSONException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BC090451584F6760040640F /* OFInvalidJSONException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC090431584F6760040640F /* OFInvalidJSONException.m */; }; 4BC1762F1D04963000C32718 /* OFKeyValueCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC176231D04963000C32718 /* OFKeyValueCoding.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BC176301D04963000C32718 /* OFObject+KeyValueCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC176241D04963000C32718 /* OFObject+KeyValueCoding.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BC176311D04963000C32718 /* OFObject+KeyValueCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BC176251D04963000C32718 /* OFObject+KeyValueCoding.m */; }; @@ -1689,10 +1703,17 @@ 4BB50DCF12F863C700C9393F /* of_asprintf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = of_asprintf.h; path = src/of_asprintf.h; sourceTree = SOURCE_ROOT; }; 4BB50DD012F863C700C9393F /* of_asprintf.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = of_asprintf.m; path = src/of_asprintf.m; sourceTree = SOURCE_ROOT; }; 4BB524BF143D1E4E0085FBCC /* OFProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFProcess.h; path = src/OFProcess.h; sourceTree = ""; }; 4BB524C0143D1E4E0085FBCC /* OFProcess.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFProcess.m; path = src/OFProcess.m; sourceTree = ""; }; 4BB52CC617B8EA7F00B7EBF5 /* codepage_437.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = codepage_437.m; path = src/encodings/codepage_437.m; sourceTree = ""; }; + 4BB99CD61FAEC9D900CC79A9 /* OFCharacterSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFCharacterSet.m; path = src/OFCharacterSet.m; sourceTree = ""; }; + 4BB99CD71FAEC9D900CC79A9 /* OFCharacterSet_bitset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCharacterSet_bitset.h; path = src/OFCharacterSet_bitset.h; sourceTree = ""; }; + 4BB99CD81FAEC9DA00CC79A9 /* OFCharacterSet_bitset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFCharacterSet_bitset.m; path = src/OFCharacterSet_bitset.m; sourceTree = ""; }; + 4BB99CD91FAEC9DA00CC79A9 /* OFCharacterSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCharacterSet.h; path = src/OFCharacterSet.h; sourceTree = ""; }; + 4BB99CE21FAF542000CC79A9 /* OFCharacterSet_range.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCharacterSet_range.h; path = src/OFCharacterSet_range.h; sourceTree = ""; }; + 4BB99CE31FAF542000CC79A9 /* OFCharacterSet_range.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFCharacterSet_range.m; path = src/OFCharacterSet_range.m; sourceTree = ""; }; + 4BB99CE81FAF77BC00CC79A9 /* OFCharacterSetTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFCharacterSetTests.m; path = tests/OFCharacterSetTests.m; sourceTree = ""; }; 4BBA36C411406AB700CBA3AC /* atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = atomic.h; path = src/atomic.h; sourceTree = ""; }; 4BBA36C511406AB700CBA3AC /* macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macros.h; path = src/macros.h; sourceTree = ""; }; 4BC090421584F6760040640F /* OFInvalidJSONException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFInvalidJSONException.h; path = src/exceptions/OFInvalidJSONException.h; sourceTree = ""; }; 4BC090431584F6760040640F /* OFInvalidJSONException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFInvalidJSONException.m; path = src/exceptions/OFInvalidJSONException.m; sourceTree = ""; }; 4BC176231D04963000C32718 /* OFKeyValueCoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFKeyValueCoding.h; path = src/OFKeyValueCoding.h; sourceTree = ""; }; @@ -2132,10 +2153,16 @@ 4B67995C1099E7C50041064A /* OFAutoreleasePool.h */, 4B67995D1099E7C50041064A /* OFAutoreleasePool.m */, 4B1473CA17E6391900B46BB8 /* OFAutoreleasePool+Private.h */, 4BD86D801237A6C600ED9912 /* OFBlock.h */, 4BD86D811237A6C600ED9912 /* OFBlock.m */, + 4BB99CD91FAEC9DA00CC79A9 /* OFCharacterSet.h */, + 4BB99CD61FAEC9D900CC79A9 /* OFCharacterSet.m */, + 4BB99CD71FAEC9D900CC79A9 /* OFCharacterSet_bitset.h */, + 4BB99CD81FAEC9DA00CC79A9 /* OFCharacterSet_bitset.m */, + 4BB99CE21FAF542000CC79A9 /* OFCharacterSet_range.h */, + 4BB99CE31FAF542000CC79A9 /* OFCharacterSet_range.m */, 4BAF5F46123460C900F4E111 /* OFCollection.h */, 4B6743F7163C395900EB1E59 /* OFCondition.h */, 4B6743F8163C395900EB1E59 /* OFCondition.m */, 4BE5F0D712DF4225005C7A0C /* OFConstantString.h */, 4BE5F0D812DF4225005C7A0C /* OFConstantString.m */, @@ -2429,10 +2456,11 @@ 4BF33B4113380CB60059CEF7 /* Supporting Files */, 4B6EF682123535960076B512 /* objc_sync */, 4BA4846515CC9FAD00D75360 /* ForwardingTests.m */, 4B6EF66E1235358D0076B512 /* OFArrayTests.m */, 4BE5F0E412DF4259005C7A0C /* OFBlockTests.m */, + 4BB99CE81FAF77BC00CC79A9 /* OFCharacterSetTests.m */, 4B6EF66F1235358D0076B512 /* OFDataTests.m */, 4BE5F0E512DF4259005C7A0C /* OFDateTests.m */, 4B6EF6701235358D0076B512 /* OFDictionaryTests.m */, 4BF0DD731D44645D001D9949 /* OFHMACTests.m */, 4BB4B54916776094002A2DCE /* OFHTTPClientTests.m */, @@ -2571,10 +2599,11 @@ files = ( 4B2C21D71DA292BE00735907 /* OFApplication.h in Headers */, 4B2C21D81DA292BE00735907 /* OFArray.h in Headers */, 4B2C21DA1DA292BE00735907 /* OFAutoreleasePool.h in Headers */, 4B2C21DC1DA292BE00735907 /* OFBlock.h in Headers */, + 4BB99CE11FAEC9DA00CC79A9 /* OFCharacterSet.h in Headers */, 4B2C21DD1DA292BE00735907 /* OFCollection.h in Headers */, 4B2C21DE1DA292BE00735907 /* OFCondition.h in Headers */, 4B2C21DF1DA292BE00735907 /* OFConstantString.h in Headers */, 4B2C21E01DA292BE00735907 /* OFCountedSet.h in Headers */, 4B2C21E11DA292BE00735907 /* OFCryptoHash.h in Headers */, @@ -2765,10 +2794,12 @@ 4B2C22A91DA292BE00735907 /* config.h in Headers */, 4B2C228E1DA292BE00735907 /* OFArray_adjacent.h in Headers */, 4B2C228F1DA292BE00735907 /* OFArray_adjacentSubarray.h in Headers */, 4B2C21D91DA292BE00735907 /* OFArray_subarray.h in Headers */, 4B2C22901DA292BE00735907 /* OFAutoreleasePool+Private.h in Headers */, + 4BB99CDD1FAEC9DA00CC79A9 /* OFCharacterSet_bitset.h in Headers */, + 4BB99CE51FAF542000CC79A9 /* OFCharacterSet_range.h in Headers */, 4B2C22911DA292BE00735907 /* OFCountedSet_hashtable.h in Headers */, 4B1223171F23E6C100D9F8FF /* OFData+Private.h in Headers */, 4B2C22921DA292BE00735907 /* OFDictionary_hashtable.h in Headers */, 4B2C22931DA292BE00735907 /* OFINICategory+Private.h in Headers */, 4B2C22941DA292BE00735907 /* OFKernelEventObserver+Private.h in Headers */, @@ -2806,10 +2837,11 @@ files = ( 4B3D23BC1337FC8300DD29B8 /* OFApplication.h in Headers */, 4B3D23BD1337FC8300DD29B8 /* OFArray.h in Headers */, 4B3D23BE1337FC8300DD29B8 /* OFAutoreleasePool.h in Headers */, 4B3D23BF1337FC8300DD29B8 /* OFBlock.h in Headers */, + 4BB99CE01FAEC9DA00CC79A9 /* OFCharacterSet.h in Headers */, 4B3D23C01337FC8300DD29B8 /* OFCollection.h in Headers */, 4B674400163C395900EB1E59 /* OFCondition.h in Headers */, 4B3D23C11337FC8300DD29B8 /* OFConstantString.h in Headers */, 4B45355313DCFE1E0037AB4D /* OFCountedSet.h in Headers */, 4B3D23C91337FCB000DD29B8 /* OFCryptoHash.h in Headers */, @@ -3001,10 +3033,12 @@ 4BDF37B51338055600F9A81A /* config.h in Headers */, 4B2B3E7D140D430500EC2F7C /* OFArray_adjacent.h in Headers */, 4B9BB7BD141CDE2D000AD1CC /* OFArray_adjacentSubarray.h in Headers */, 4B9BB7BF141CDE2D000AD1CC /* OFArray_subarray.h in Headers */, 4B1473CB17E6391900B46BB8 /* OFAutoreleasePool+Private.h in Headers */, + 4BB99CDC1FAEC9DA00CC79A9 /* OFCharacterSet_bitset.h in Headers */, + 4BB99CE41FAF542000CC79A9 /* OFCharacterSet_range.h in Headers */, 4BA85BCA140ECCE800E91D51 /* OFCountedSet_hashtable.h in Headers */, 4B1223141F23E6C000D9F8FF /* OFData+Private.h in Headers */, 4B2B3E7F140D430500EC2F7C /* OFDictionary_hashtable.h in Headers */, 4B06855518B2AD3800FC731A /* OFINICategory+Private.h in Headers */, 4B0EA9231898690E00F573A4 /* OFKernelEventObserver+Private.h in Headers */, @@ -3365,10 +3399,13 @@ 4B2C21211DA292BE00735907 /* OFArray_adjacent.m in Sources */, 4B2C21221DA292BE00735907 /* OFArray_adjacentSubarray.m in Sources */, 4B2C21231DA292BE00735907 /* OFArray_subarray.m in Sources */, 4B2C21241DA292BE00735907 /* OFAutoreleasePool.m in Sources */, 4B2C21261DA292BE00735907 /* OFBlock.m in Sources */, + 4BB99CDB1FAEC9DA00CC79A9 /* OFCharacterSet.m in Sources */, + 4BB99CDF1FAEC9DA00CC79A9 /* OFCharacterSet_bitset.m in Sources */, + 4BB99CE71FAF542000CC79A9 /* OFCharacterSet_range.m in Sources */, 4B2C21271DA292BE00735907 /* OFCondition.m in Sources */, 4B2C21281DA292BE00735907 /* OFConstantString.m in Sources */, 4B2C21291DA292BE00735907 /* OFCountedSet.m in Sources */, 4B2C212A1DA292BE00735907 /* OFCountedSet_hashtable.m in Sources */, 4B2C212B1DA292BE00735907 /* OFData.m in Sources */, @@ -3575,10 +3612,13 @@ 4B2B3E7E140D430500EC2F7C /* OFArray_adjacent.m in Sources */, 4B9BB7BE141CDE2D000AD1CC /* OFArray_adjacentSubarray.m in Sources */, 4B9BB7C0141CDE2D000AD1CC /* OFArray_subarray.m in Sources */, 4B3D238D1337FC0D00DD29B8 /* OFAutoreleasePool.m in Sources */, 4B3D238E1337FC0D00DD29B8 /* OFBlock.m in Sources */, + 4BB99CDA1FAEC9DA00CC79A9 /* OFCharacterSet.m in Sources */, + 4BB99CDE1FAEC9DA00CC79A9 /* OFCharacterSet_bitset.m in Sources */, + 4BB99CE61FAF542000CC79A9 /* OFCharacterSet_range.m in Sources */, 4B674401163C395900EB1E59 /* OFCondition.m in Sources */, 4B3D238F1337FC0D00DD29B8 /* OFConstantString.m in Sources */, 4B45355413DCFE1E0037AB4D /* OFCountedSet.m in Sources */, 4BA85BCB140ECCE800E91D51 /* OFCountedSet_hashtable.m in Sources */, 4B3D23901337FC0D00DD29B8 /* OFData.m in Sources */, @@ -3790,10 +3830,11 @@ buildActionMask = 2147483647; files = ( 4BD9CA001DA2C5FC00E5AD52 /* ForwardingTests.m in Sources */, 4BD9CA011DA2C5FE00E5AD52 /* OFArrayTests.m in Sources */, 4BD9CA021DA2C60200E5AD52 /* OFBlockTests.m in Sources */, + 4BB99CEA1FAF77BC00CC79A9 /* OFCharacterSetTests.m in Sources */, 4BD9CA031DA2C60400E5AD52 /* OFDataTests.m in Sources */, 4BD9CA041DA2C60700E5AD52 /* OFDateTests.m in Sources */, 4BD9CA051DA2C60900E5AD52 /* OFDictionaryTests.m in Sources */, 4BD9CA061DA2C60B00E5AD52 /* OFHMACTests.m in Sources */, 4BD9CA071DA2C60E00E5AD52 /* OFHTTPClientTests.m in Sources */, @@ -3838,10 +3879,11 @@ buildActionMask = 2147483647; files = ( 4BA4846615CC9FAD00D75360 /* ForwardingTests.m in Sources */, 4BF33AFC133807A20059CEF7 /* OFArrayTests.m in Sources */, 4BF33AFD133807A20059CEF7 /* OFBlockTests.m in Sources */, + 4BB99CE91FAF77BC00CC79A9 /* OFCharacterSetTests.m in Sources */, 4BF33AFE133807A20059CEF7 /* OFDataTests.m in Sources */, 4BF33AFF133807A20059CEF7 /* OFDateTests.m in Sources */, 4BF33B00133807A20059CEF7 /* OFDictionaryTests.m in Sources */, 4BF0DD741D44645D001D9949 /* OFHMACTests.m in Sources */, 4BB4B54A16776094002A2DCE /* OFHTTPClientTests.m in Sources */, Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -12,10 +12,11 @@ SRCS = OFApplication.m \ OFArray.m \ OFAutoreleasePool.m \ OFBlock.m \ + OFCharacterSet.m \ OFConstantString.m \ OFCountedSet.m \ OFData.m \ OFData+CryptoHashing.m \ OFData+MessagePackValue.m \ @@ -155,10 +156,12 @@ ${USE_INCLUDES_ATOMIC} SRCS += OFArray_adjacent.m \ OFArray_adjacentSubarray.m \ OFArray_subarray.m \ + OFCharacterSet_bitset.m \ + OFCharacterSet_range.m \ OFCountedSet_hashtable.m \ OFDictionary_hashtable.m \ OFMutableArray_adjacent.m \ OFMutableDictionary_hashtable.m \ OFMutableSet_hashtable.m \ ADDED src/OFCharacterSet.h Index: src/OFCharacterSet.h ================================================================== --- src/OFCharacterSet.h +++ src/OFCharacterSet.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * 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 "OFObject.h" +#import "OFString.h" + +OF_ASSUME_NONNULL_BEGIN + +/*! + * @class OFCharacterSet OFCharacterSet.h ObjFW/OFCharacterSet.h + * + * @brief A class cluster representing a character set. + */ +@interface OFCharacterSet: OFObject +/*! + * @brief Creates a new character set containing the characters of the + * specified string. + * + * @param characters The characters for the character set + * @return A new OFCharacterSet + */ ++ (instancetype)characterSetWithCharactersInString: (OFString *)characters; + +/*! + * @brief Creates a new character set containing the characters in the specified + * range. + * + * @param range The range of characters for the character set + * @return A new OFCharacterSet + */ ++ (instancetype)characterSetWithRange: (of_range_t)range; + +/*! + * @brief Initializes an already allocated character set with the characters of + * the specified string. + * + * @param characters The characters for the character set + * @return An initialized OFCharacterSet + */ +- (instancetype)initWithCharactersInString: (OFString *)characters; + +/*! + * @brief Initializes an already allocated character set with the characters in + * the specified range. + * + * @param range The range of characters for the character set + * @return An initialized OFCharacterSet + */ +- (instancetype)initWithRange: (of_range_t)range; + +/*! + * @brief Returns whether the specified character is a member of the character + * set. + * + * @param character The character that is checked for being a member of the + * character set + * @return Whether the specified character is a member of the character set. + */ +- (bool)characterIsMember: (of_unichar_t)character; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFCharacterSet.m Index: src/OFCharacterSet.m ================================================================== --- src/OFCharacterSet.m +++ src/OFCharacterSet.m @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * 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 "OFCharacterSet.h" +#import "OFCharacterSet_bitset.h" +#import "OFCharacterSet_range.h" + +static struct { + Class isa; +} placeholder; + +@interface OFCharacterSet_placeholder: OFCharacterSet +@end + +@implementation OFCharacterSet_placeholder +- (instancetype)init +{ + return (id)[[OFCharacterSet_bitset alloc] init]; +} + +- (instancetype)initWithCharactersInString: (OFString *)characters +{ + return (id)[[OFCharacterSet_bitset alloc] + initWithCharactersInString: characters]; +} + +- (instancetype)initWithRange: (of_range_t)range +{ + return (id)[[OFCharacterSet_range alloc] initWithRange: range]; +} + +- (instancetype)retain +{ + return self; +} + +- (instancetype)autorelease +{ + return self; +} + +- (void)release +{ +} + +- (void)dealloc +{ + OF_DEALLOC_UNSUPPORTED +} +@end + +@implementation OFCharacterSet ++ (void)initialize +{ + if (self != [OFCharacterSet class]) + return; + + placeholder.isa = [OFCharacterSet_placeholder class]; +} + ++ (instancetype)alloc +{ + if (self == [OFCharacterSet class]) + return (id)&placeholder; + + return [super alloc]; +} + ++ (instancetype)characterSetWithCharactersInString: (OFString *)characters +{ + return [[[self alloc] initWithCharactersInString: characters] + autorelease]; +} + ++ (instancetype)characterSetWithRange: (of_range_t)range +{ + return [[[self alloc] initWithRange: range] autorelease]; +} + +- (instancetype)init +{ + if ([self isMemberOfClass: [OFCharacterSet class]]) { + @try { + [self doesNotRecognizeSelector: _cmd]; + } @catch (id e) { + [self release]; + @throw e; + } + + abort(); + } + + return [super init]; +} + +- (instancetype)initWithCharactersInString: (OFString *)characters +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithRange: (of_range_t)range +{ + OF_INVALID_INIT_METHOD +} + +- (bool)characterIsMember: (of_unichar_t)character +{ + OF_UNRECOGNIZED_SELECTOR +} +@end ADDED src/OFCharacterSet_bitset.h Index: src/OFCharacterSet_bitset.h ================================================================== --- src/OFCharacterSet_bitset.h +++ src/OFCharacterSet_bitset.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * 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 "OFCharacterSet.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFCharacterSet_bitset: OFCharacterSet +{ + unsigned char *_bitset; + size_t _size; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFCharacterSet_bitset.m Index: src/OFCharacterSet_bitset.m ================================================================== --- src/OFCharacterSet_bitset.m +++ src/OFCharacterSet_bitset.m @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * 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 "OFCharacterSet_bitset.h" +#import "OFString.h" + +#import "OFOutOfRangeException.h" + +@implementation OFCharacterSet_bitset +- (instancetype)initWithCharactersInString: (OFString *)string +{ + self = [super init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + const of_unichar_t *characters = [string characters]; + size_t length = [string length]; + + for (size_t i = 0; i < length; i++) { + of_unichar_t c = characters[i]; + + if (c / 8 >= _size) { + size_t newSize; + + if (UINT32_MAX - c < 1) + @throw [OFOutOfRangeException + exception]; + + newSize = OF_ROUND_UP_POW2(8, c + 1) / 8; + + _bitset = [self resizeMemory: _bitset + size: newSize]; + memset(_bitset + _size, '\0', newSize - _size); + + _size = newSize; + } + + of_bitset_set(_bitset, c); + } + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (bool)characterIsMember: (of_unichar_t)character +{ + if (character / 8 >= _size) + return false; + + return of_bitset_isset(_bitset, character); +} +@end ADDED src/OFCharacterSet_range.h Index: src/OFCharacterSet_range.h ================================================================== --- src/OFCharacterSet_range.h +++ src/OFCharacterSet_range.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * 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 "OFCharacterSet.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface OFCharacterSet_range: OFCharacterSet +{ + of_range_t _range; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/OFCharacterSet_range.m Index: src/OFCharacterSet_range.m ================================================================== --- src/OFCharacterSet_range.m +++ src/OFCharacterSet_range.m @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * 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 "OFCharacterSet_range.h" +#import "OFString.h" + +#import "OFOutOfRangeException.h" + +@implementation OFCharacterSet_range +- (instancetype)initWithRange: (of_range_t)range +{ + self = [super init]; + + @try { + if (SIZE_MAX - range.location < range.length) + @throw [OFOutOfRangeException exception]; + + _range = range; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (bool)characterIsMember: (of_unichar_t)character +{ + return (character >= _range.location && + character < _range.location + _range.length); +} +@end Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -17,10 +17,11 @@ #import "OFObject.h" #import "OFBlock.h" #import "OFAutoreleasePool.h" #import "OFString.h" +#import "OFCharacterSet.h" #import "OFData.h" #import "OFArray.h" #import "OFList.h" Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -766,23 +766,23 @@ OF_HASH_ADD(hash, (otherCopy >> 8) & 0xFF); \ OF_HASH_ADD(hash, otherCopy & 0xFF); \ } static OF_INLINE bool -of_bitset_isset(uint8_t *_Nonnull storage, size_t idx) +of_bitset_isset(unsigned char *_Nonnull storage, size_t idx) { return storage[idx / 8] & (1 << (idx % 8)); } static OF_INLINE void -of_bitset_set(uint8_t *_Nonnull storage, size_t idx) +of_bitset_set(unsigned char *_Nonnull storage, size_t idx) { storage[idx / 8] |= (1 << (idx % 8)); } static OF_INLINE void -of_bitset_clear(uint8_t *_Nonnull storage, size_t idx) +of_bitset_clear(unsigned char *_Nonnull storage, size_t idx) { storage[idx / 8] &= ~(1 << (idx % 8)); } static OF_INLINE char *_Nullable Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -9,10 +9,11 @@ PROG_NOINST = tests${PROG_SUFFIX} SRCS = ForwardingTests.m \ OFArrayTests.m \ ${OFBLOCKTESTS_M} \ + OFCharacterSetTests.m \ OFDataTests.m \ OFDateTests.m \ OFDictionaryTests.m \ OFHTTPCookieTests.m \ OFHTTPCookieManagerTests.m \ ADDED tests/OFCharacterSetTests.m Index: tests/OFCharacterSetTests.m ================================================================== --- tests/OFCharacterSetTests.m +++ tests/OFCharacterSetTests.m @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * 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 "OFCharacterSet.h" +#import "OFCharacterSet_bitset.h" +#import "OFCharacterSet_range.h" +#import "OFAutoreleasePool.h" + +#import "TestsAppDelegate.h" + +static OFString *module = nil; + +@interface SimpleCharacterSet: OFCharacterSet +@end + +@implementation SimpleCharacterSet +- (bool)characterIsMember: (of_unichar_t)character +{ + return (character % 2 == 0); +} +@end + +@implementation TestsAppDelegate (OFCharacterSetTests) +- (void)characterSetTests +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + OFCharacterSet *cs; + bool ok; + + module = @"OFCharacterSet"; + + cs = [[[SimpleCharacterSet alloc] init] autorelease]; + + ok = true; + for (of_unichar_t c = 0; c < 65536; c++) { + if (c % 2 == 0) { + if (![cs characterIsMember: c]) + ok = false; + } else if ([cs characterIsMember: c]) + ok = false; + } + TEST(@"-[characterIsMember:]", ok); + + module = @"OFCharacterSet_bitset"; + + TEST(@"+[characterSetWithCharactersInString:]", + (cs = [OFCharacterSet characterSetWithCharactersInString: + @"0123456789"]) && + [cs isKindOfClass: [OFCharacterSet_bitset class]]) + + ok = true; + for (of_unichar_t c = 0; c < 65536; c++) { + if (c >= '0' && c <= '9') { + if (![cs characterIsMember: c]) + ok = false; + } else if ([cs characterIsMember: c]) + ok = false; + } + TEST(@"-[characterIsMember:]", ok); + + module = @"OFCharacterSet_range"; + + TEST(@"+[characterSetWithRange:]", + (cs = [OFCharacterSet characterSetWithRange: of_range('0', 10)]) && + [cs isKindOfClass: [OFCharacterSet_range class]]) + + ok = true; + for (of_unichar_t c = 0; c < 65536; c++) { + if (c >= '0' && c <= '9') { + if (![cs characterIsMember: c]) + ok = false; + } else if ([cs characterIsMember: c]) + ok = false; + } + TEST(@"-[characterIsMember:]", ok); + + [pool drain]; +} +@end Index: tests/TestsAppDelegate.h ================================================================== --- tests/TestsAppDelegate.h +++ tests/TestsAppDelegate.h @@ -77,10 +77,14 @@ @end @interface TestsAppDelegate (OFBlockTests) - (void)blockTests; @end + +@interface TestsAppDelegate (OFCharacterSetTests) +- (void)characterSetTests; +@end @interface TestsAppDelegate (OFDataTests) - (void)dataTests; @end Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -378,18 +378,19 @@ [[OFFileManager defaultManager] changeCurrentDirectoryPath: @"/apps/objfw-tests"]; #endif [self runtimeTests]; + [self objectTests]; [self methodSignatureTests]; [self invocationTests]; [self forwardingTests]; - [self objectTests]; #ifdef OF_HAVE_BLOCKS [self blockTests]; #endif [self stringTests]; + [self characterSetTests]; [self dataTests]; [self arrayTests]; [self dictionaryTests]; [self listTests]; [self setTests];