forで全部調べて,returnで返す

guard let unichars = $0.baseAddress else { throw HTMLSpecialCharactersError.invalidEscapeSquence }
let length = $0.count
if let t = getUnescapeTable(length: $0.count) {
    for i in 0..<t.count {
        if memcmp(t[i].unescapingCodes, unichars, MemoryLayout<UniChar>.size * length) == 0 {
            return t[i].code
        }
    }
}
throw HTMLSpecialCharactersError.invalidEscapeSquence

forEachで回して,例外で値を返す

guard let unichars = $0.baseAddress else { throw HTMLSpecialCharactersError.invalidEscapeSquence }
let length = $0.count
do {
    try getUnescapeTable(length: length)?.forEach({
        if memcmp($0.unescapingCodes, unichars, MemoryLayout<UniChar>.size * length) == 0 {
            throw HTMLSpecialCharactersError.notErrorMatchedUnicode(code: $0.code)
        }
    })
    throw HTMLSpecialCharactersError.invalidEscapeSquence
} catch HTMLSpecialCharactersError.notErrorMatchedUnicode(let code) {
    return code
}

Profileのためのコード

let testCount = 1000
let escape1 = "&quot;"

func testUnescapePerformanceUsingException() {
    self.measure {
        for _ in 0..<self.testCount {
            _ = self.escape1.unescapeHTML_usingException
        }
    }
}

func testUnescapePerformance() {
    self.measure {
        for _ in 0..<self.testCount {
            _ = self.escape1.unescapeHTML
        }
    }
}

let escape100 = "&quot;&amp;&amp;apos;&lt;&quot;&amp;&amp;apos;&lt;&Yuml;&circ;&quot;&amp;&amp;apos;&lt;&quot;&amp;&amp;apos;&lt;&Yuml;&circ;&quot;&amp;&amp;apos;&lt;&quot;&amp;&amp;apos;&lt;&Yuml;&circ;&quot;&amp;&amp;apos;&lt;&quot;&amp;&amp;apos;&lt;&Yuml;&circ;&quot;&amp;&amp;apos;&lt;&quot;&amp;&amp;apos;&lt;&Yuml;&circ;&quot;&amp;&amp;apos;&lt;&quot;&amp;&amp;apos;&lt;&Yuml;&circ;&quot;&amp;&amp;apos;&lt;&quot;&amp;&amp;apos;&lt;&Yuml;&circ;&quot;&amp;&amp;apos;&lt;&quot;&amp;&amp;apos;&lt;&Yuml;&circ;&quot;&amp;&amp;apos;&lt;&quot;&amp;&amp;apos;&lt;&Yuml;&circ;&quot;&amp;&amp;apos;&lt;&quot;&amp;&amp;apos;&lt;&Yuml;&circ;"

func testUnescapePerformanceUsingExceptionFor100() {
    self.measure {
        for _ in 0..<self.testCount {
            _ = self.escape100.unescapeHTML_usingException
        }
    }
}

func testUnescapePerformanceFor100() {
    self.measure {
        for _ in 0..<self.testCount {
            _ = self.escape100.unescapeHTML
        }
    }
}

Profileの結果

特殊文字100個を1000回[sec] release debug(unescape) debug(convertToUTF16Codes)
forEach 0.48 10.5 3.91
for 0.27 8.2 1.98
特殊文字1個を1000回[sec] release debug(unescape) debug(convertToUTF16Codes)
forEach 0.018 0.171 0.026
for 0.014 0.148 0.015

iMac(3.4 GHz Intel Core i7) + Instruments + Xcode9