| 59 | } |
| 60 | |
| 61 | ImageOperation imageOperationFromString(StringView string) { |
| 62 | try { |
| 63 | std::string_view view = string.utf8(); |
| 64 | //double time = view.size() > 10000 ? Time::monotonicTime() : 0.0; |
| 65 | auto firstBitEnd = view.find_first_of("=;"); |
| 66 | if (view.substr(0, firstBitEnd).compare("replace") == 0 && (firstBitEnd + 1) != view.size()) { |
| 67 | //Perform optimized replace parse |
| 68 | ColorReplaceImageOperation operation; |
| 69 | |
| 70 | std::string_view bits = view.substr(firstBitEnd + 1); |
| 71 | operation.colorReplaceMap.reserve(bits.size() / 8); |
| 72 | |
| 73 | char const* hexPtr = nullptr; |
| 74 | unsigned int hexLen = 0; |
| 75 | |
| 76 | char const* ptr = bits.data(); |
| 77 | char const* end = ptr + bits.size(); |
| 78 | |
| 79 | char a[4]{}, b[4]{}; |
| 80 | bool which = true; |
| 81 | |
| 82 | while (true) { |
| 83 | char ch = *ptr; |
| 84 | |
| 85 | if (ch == '=' || ch == ';' || ptr == end) { |
| 86 | if (hexLen != 0) { |
| 87 | char* c = which ? a : b; |
| 88 | |
| 89 | if (hexLen == 3) { |
| 90 | nibbleDecode(hexPtr, 3, c, 4); |
| 91 | c[0] |= (c[0] << 4); |
| 92 | c[1] |= (c[1] << 4); |
| 93 | c[2] |= (c[2] << 4); |
| 94 | c[3] = static_cast<char>(255); |
| 95 | } |
| 96 | else if (hexLen == 4) { |
| 97 | nibbleDecode(hexPtr, 4, c, 4); |
| 98 | c[0] |= (c[0] << 4); |
| 99 | c[1] |= (c[1] << 4); |
| 100 | c[2] |= (c[2] << 4); |
| 101 | c[3] |= (c[3] << 4); |
| 102 | } |
| 103 | else if (hexLen == 6) { |
| 104 | hexDecode(hexPtr, 6, c, 4); |
| 105 | c[3] = static_cast<char>(255); |
| 106 | } |
| 107 | else if (hexLen == 8) { |
| 108 | hexDecode(hexPtr, 8, c, 4); |
| 109 | } |
| 110 | else if (!which || (ptr != end && ++ptr != end)) |
| 111 | return ErrorImageOperation{strf("Improper size for hex string '{}'", StringView(hexPtr, hexLen))}; |
| 112 | else // we're in A of A=B. In vanilla only A=B pairs are evaluated, so only throw an error if B is also there. |
| 113 | return operation; |
| 114 | |
| 115 | if ((which = !which)) |
| 116 | operation.colorReplaceMap[*(Vec4B*)&a] = *(Vec4B*)&b; |
| 117 | |
| 118 | hexLen = 0; |
no test coverage detected