Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -975,10 +975,12 @@ 4BF48CE118A95F83000E8D04 /* OFBigDataArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF48CDF18A95F83000E8D04 /* OFBigDataArray.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BF48CE218A95F83000E8D04 /* OFBigDataArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF48CE018A95F83000E8D04 /* OFBigDataArray.m */; }; 4BF5CB901E2DC1D800CF7584 /* iso_8859_2.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF5CB8F1E2DC1D800CF7584 /* iso_8859_2.m */; }; 4BF5CB911E2DC1D800CF7584 /* iso_8859_2.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF5CB8F1E2DC1D800CF7584 /* iso_8859_2.m */; }; 4BF69CE61BD44F8B00DFFC1B /* platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF69CE51BD44F8B00DFFC1B /* platform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BFC37BD1E50E11C00EE1269 /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BFC37BC1E50E11C00EE1269 /* common.h */; }; + 4BFC37BE1E50E11C00EE1269 /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BFC37BC1E50E11C00EE1269 /* common.h */; }; 4BFF3714177E17C100192782 /* OFRemoveItemFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BFF3710177E17C100192782 /* OFRemoveItemFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BFF3715177E17C100192782 /* OFRemoveItemFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BFF3711177E17C100192782 /* OFRemoveItemFailedException.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1605,10 +1607,11 @@ 4BF48CDF18A95F83000E8D04 /* OFBigDataArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFBigDataArray.h; path = src/OFBigDataArray.h; sourceTree = ""; }; 4BF48CE018A95F83000E8D04 /* OFBigDataArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFBigDataArray.m; path = src/OFBigDataArray.m; sourceTree = ""; }; 4BF5CB8F1E2DC1D800CF7584 /* iso_8859_2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = iso_8859_2.m; path = src/encodings/iso_8859_2.m; sourceTree = ""; }; 4BF69CE51BD44F8B00DFFC1B /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = platform.h; path = src/platform.h; sourceTree = ""; }; 4BFBDD1610A0724800051AFB /* unicode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = unicode.m; path = src/unicode.m; sourceTree = ""; }; + 4BFC37BC1E50E11C00EE1269 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = common.h; path = src/encodings/common.h; sourceTree = ""; }; 4BFF3710177E17C100192782 /* OFRemoveItemFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFRemoveItemFailedException.h; path = src/exceptions/OFRemoveItemFailedException.h; sourceTree = ""; }; 4BFF3711177E17C100192782 /* OFRemoveItemFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRemoveItemFailedException.m; path = src/exceptions/OFRemoveItemFailedException.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1917,10 +1920,11 @@ isa = PBXGroup; children = ( 4BB52CC617B8EA7F00B7EBF5 /* codepage_437.m */, 4B5EBFB51E25A8CF004FE6A2 /* codepage_850.m */, 4B6736111E2B2F6F00681F2C /* codepage_858.m */, + 4BFC37BC1E50E11C00EE1269 /* common.h */, 4BF5CB8F1E2DC1D800CF7584 /* iso_8859_2.m */, 4B276E351E493D4900E20CE4 /* iso_8859_3.m */, 4B6AF96F10A8D40E0003FB0A /* iso_8859_15.m */, 4B276E361E493D4900E20CE4 /* koi8_r.m */, 4B276E371E493D4900E20CE4 /* koi8_u.m */, @@ -2537,10 +2541,11 @@ 4B2C22891DA292BE00735907 /* OFUnknownXMLEntityException.h in Headers */, 4B2C228A1DA292BE00735907 /* OFUnlockFailedException.h in Headers */, 4B2C228B1DA292BE00735907 /* OFUnsupportedProtocolException.h in Headers */, 4B2C228C1DA292BE00735907 /* OFUnsupportedVersionException.h in Headers */, 4B2C228D1DA292BE00735907 /* OFWriteFailedException.h in Headers */, + 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 */, 4B2C22911DA292BE00735907 /* OFCountedSet_hashtable.h in Headers */, @@ -2565,12 +2570,12 @@ 4B2C22A41DA292BE00735907 /* OFTarArchiveEntry+Private.h in Headers */, 4B2C22A51DA292BE00735907 /* OFTCPSocket+SOCKS5.h in Headers */, 4B2C22A61DA292BE00735907 /* OFThread+Private.h in Headers */, 4B2C22A71DA292BE00735907 /* OFTimer+Private.h in Headers */, 4B2C22A81DA292BE00735907 /* OFZIPArchiveEntry+Private.h in Headers */, - 4B2C22A91DA292BE00735907 /* config.h in Headers */, 4B2C22AA1DA292BE00735907 /* socket_helpers.h in Headers */, + 4BFC37BE1E50E11C00EE1269 /* common.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 4B3D23731337FBC800DD29B8 /* Headers */ = { isa = PBXHeadersBuildPhase; @@ -2756,10 +2761,11 @@ 4B91FD12196B4F5900C5C25E /* OFUnknownXMLEntityException.h in Headers */, 4B6743F5163C384A00EB1E59 /* OFUnlockFailedException.h in Headers */, 4B17FFB1133A3664003E6DCD /* OFUnsupportedProtocolException.h in Headers */, 4BA4846215CC9F1E00D75360 /* OFUnsupportedVersionException.h in Headers */, 4B55A116133AC24600B58A93 /* OFWriteFailedException.h in Headers */, + 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 */, 4BA85BCA140ECCE800E91D51 /* OFCountedSet_hashtable.h in Headers */, @@ -2784,12 +2790,12 @@ 4BC176361D04963000C32718 /* OFTarArchiveEntry+Private.h in Headers */, 4BD653C5143B8489006182F0 /* OFTCPSocket+SOCKS5.h in Headers */, 4B6C8ADC17BD5C2E00B194F2 /* OFThread+Private.h in Headers */, 4B6C8ADD17BD5C2E00B194F2 /* OFTimer+Private.h in Headers */, 4B6C8ADE17BD5C2E00B194F2 /* OFZIPArchiveEntry+Private.h in Headers */, - 4BDF37B51338055600F9A81A /* config.h in Headers */, 4B7DD58218942FE200990FD6 /* socket_helpers.h in Headers */, + 4BFC37BD1E50E11C00EE1269 /* common.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 4B5D70711DA2F87A00B3B2D7 /* Headers */ = { isa = PBXHeadersBuildPhase; ADDED src/encodings/common.h Index: src/encodings/common.h ================================================================== --- src/encodings/common.h +++ src/encodings/common.h @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#define CASE_MISSING_IS_KEEP(nr) \ + case nr: \ + if OF_UNLIKELY ((c & 0xFF) < page##nr##Start) { \ + output[i] = (unsigned char)c; \ + continue; \ + } \ + \ + index = (c & 0xFF) - page##nr##Start; \ + \ + if (index >= page##nr##Size) { \ + output[i] = (unsigned char)c; \ + continue; \ + } \ + \ + if (page##nr[index] == 0x00) { \ + if (lossy) { \ + output[i] = '?'; \ + continue; \ + } else \ + return false; \ + } \ + \ + output[i] = page##nr[index]; \ + break; +#define CASE_MISSING_IS_ERROR(nr) \ + case nr: \ + if OF_UNLIKELY ((c & 0xFF) < page##nr##Start) { \ + if (lossy) { \ + output[i] = '?'; \ + continue; \ + } else \ + return false; \ + } \ + \ + index = (c & 0xFF) - page##nr##Start; \ + \ + if (index >= page##nr##Size || page##nr[index] == 0) { \ + if (lossy) { \ + output[i] = '?'; \ + continue; \ + } else \ + return false; \ + } \ + \ + output[i] = page##nr[index]; \ + break; Index: src/encodings/iso_8859_2.m ================================================================== --- src/encodings/iso_8859_2.m +++ src/encodings/iso_8859_2.m @@ -15,10 +15,12 @@ */ #include "config.h" #import "OFString.h" + +#import "common.h" const of_char16_t of_iso_8859_2_table[] = { 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, @@ -45,11 +47,11 @@ 0x00, 0x00, 0x00, 0xD3, 0xD4, 0x00, 0xD6, 0xD7, 0x00, 0x00, 0xDA, 0x00, 0xDC, 0xDD, 0x00, 0xDF, 0x00, 0xE1, 0xE2, 0x00, 0xE4, 0x00, 0x00, 0xE7, 0x00, 0xE9, 0x00, 0xEB, 0x00, 0xED, 0xEE, 0x00, 0x00, 0x00, 0x00, 0xF3, 0xF4, 0x00, 0xF6, 0xF7, - 0x00, 0x00, 0xFA, 0x00, 0xFC, 0xFD + 0x00, 0x00, 0xFA, 0x00, 0xFC, 0xFD, 0x00, 0x00 }; static const uint8_t page0Start = 0xA0; static const uint16_t page0Size = sizeof(page0) / sizeof(*page0); static const char page1[] = { @@ -98,48 +100,13 @@ } else return false; } switch (c >> 8) { - case 0: - if OF_UNLIKELY ((c & 0xFF) < page0Start) { - output[i] = (unsigned char)c; - continue; - } - - index = (c & 0xFF) - page0Start; - if (index >= page0Size || page0[index] == 0) { - if (lossy) { - output[i] = '?'; - continue; - } else - return false; - } - output[i] = page0[index]; - break; - case 1: - index = (c & 0xFF) - page1Start; - if (index >= page1Size || page1[index] == 0) { - if (lossy) { - output[i] = '?'; - continue; - } else - return false; - } - output[i] = page1[index]; - break; - case 2: - index = (c & 0xFF) - page2Start; - if (index >= page2Size || page2[index] == 0) { - if (lossy) { - output[i] = '?'; - continue; - } else - return false; - } - output[i] = page2[index]; - break; + CASE_MISSING_IS_KEEP(0) + CASE_MISSING_IS_ERROR(1) + CASE_MISSING_IS_ERROR(2) default: if (lossy) { output[i] = '?'; continue; } else Index: src/encodings/iso_8859_3.m ================================================================== --- src/encodings/iso_8859_3.m +++ src/encodings/iso_8859_3.m @@ -15,10 +15,12 @@ */ #include "config.h" #import "OFString.h" + +#import "common.h" const of_char16_t of_iso_8859_3_table[] = { 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0xFFFF, 0x0124, 0x00A7, 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0xFFFF, 0x017B, 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, @@ -95,48 +97,13 @@ } else return false; } switch (c >> 8) { - case 0: - if OF_UNLIKELY ((c & 0xFF) < page0Start) { - output[i] = (unsigned char)c; - continue; - } - - index = (c & 0xFF) - page0Start; - if (index >= page0Size || page0[index] == 0) { - if (lossy) { - output[i] = '?'; - continue; - } else - return false; - } - output[i] = page0[index]; - break; - case 1: - index = (c & 0xFF) - page1Start; - if (index >= page1Size || page1[index] == 0) { - if (lossy) { - output[i] = '?'; - continue; - } else - return false; - } - output[i] = page1[index]; - break; - case 2: - index = (c & 0xFF) - page2Start; - if (index >= page2Size || page2[index] == 0) { - if (lossy) { - output[i] = '?'; - continue; - } else - return false; - } - output[i] = page2[index]; - break; + CASE_MISSING_IS_KEEP(0) + CASE_MISSING_IS_ERROR(1) + CASE_MISSING_IS_ERROR(2) default: if (lossy) { output[i] = '?'; continue; } else