Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2023 Project CHIP Authors 4 : * All rights reserved. 5 : * 6 : * Licensed under the Apache License, Version 2.0 (the "License"); 7 : * you may not use this file except in compliance with the License. 8 : * You may obtain a copy of the License at 9 : * 10 : * http://www.apache.org/licenses/LICENSE-2.0 11 : * 12 : * Unless required by applicable law or agreed to in writing, software 13 : * distributed under the License is distributed on an "AS IS" BASIS, 14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 : * See the License for the specific language governing permissions and 16 : * limitations under the License. 17 : */ 18 : #include "utf8.h" 19 : 20 : namespace chip { 21 : namespace Utf8 { 22 : 23 : namespace { 24 : /** 25 : State machine for UTF8 valid bytes 26 : 27 : Table 3-7. Well-Formed UTF-8 Byte Sequences 28 : 29 : Code Points | First B | Second B | Third B | Fourth B 30 : ------------------+----------+------------+---------+--------- 31 : U+0000..U+007F | 00..7F | | | 32 : U+0080..U+07FF | C2..DF | 80..BF | | 33 : U+0800..U+0FFF | E0 | A0..BF (A) | 80..BF | 34 : U+1000..U+CFFF | E1..EC | 80..BF | 80..BF | 35 : U+D000..U+D7FF | ED | 80..9F (B) | 80..BF | 36 : U+E000..U+FFFF | EE..EF | 80..BF | 80..BF | 37 : U+10000..U+3FFFF | F0 | 90..BF (C) | 80..BF | 80..BF 38 : U+40000..U+FFFFF | F1..F3 | 80..BF | 80..BF | 80..BF 39 : U+100000..U+10FFFF| F4 | 80..8F (D) | 80..BF | 80..BF 40 : */ 41 : 42 : enum class ParserState 43 : { 44 : kFirstByte, 45 : kSecondByte_A, 46 : kSecondByte_B, 47 : kSecondByte_C, 48 : kSecondByte_D, 49 : kExtraOneByte, // 0x80 .. 0xBF once 50 : kExtraTwoBytes, // 0x80 .. 0xBF twice 51 : kExtraThreeBytes, // 0x80 .. 0xBF three times 52 : // 53 : kInvalid, // some error 54 : }; 55 : 56 115243 : ParserState NextState(ParserState state, uint8_t value) 57 : { 58 115243 : switch (state) 59 : { 60 115122 : case ParserState::kFirstByte: 61 115122 : if (value <= 0x7F) 62 : { 63 115022 : return ParserState::kFirstByte; 64 : } 65 100 : else if ((value >= 0xC2) && (value <= 0xDF)) 66 : { 67 16 : return ParserState::kExtraOneByte; 68 : } 69 84 : else if (value == 0xE0) 70 : { 71 6 : return ParserState::kSecondByte_A; 72 : } 73 78 : else if ((value >= 0xE1) && (value <= 0xEC)) 74 : { 75 3 : return ParserState::kExtraTwoBytes; 76 : } 77 75 : else if (value == 0xED) 78 : { 79 6 : return ParserState::kSecondByte_B; 80 : } 81 69 : else if ((value >= 0xEE) && (value <= 0xEF)) 82 : { 83 35 : return ParserState::kExtraTwoBytes; 84 : } 85 34 : else if (value == 0xF0) 86 : { 87 8 : return ParserState::kSecondByte_C; 88 : } 89 26 : else if ((value >= 0xF1) && (value <= 0xF3)) 90 : { 91 3 : return ParserState::kExtraThreeBytes; 92 : } 93 23 : else if (value == 0xF4) 94 : { 95 6 : return ParserState::kSecondByte_D; 96 : } 97 : else 98 : { 99 17 : return ParserState::kInvalid; 100 : } 101 5 : case ParserState::kSecondByte_A: 102 5 : if (value >= 0xA0 && value <= 0xBF) 103 : { 104 1 : return ParserState::kExtraOneByte; 105 : } 106 : else 107 : { 108 4 : return ParserState::kInvalid; 109 : } 110 6 : case ParserState::kSecondByte_B: 111 6 : if (value >= 0x80 && value <= 0x9F) 112 : { 113 3 : return ParserState::kExtraOneByte; 114 : } 115 : else 116 : { 117 3 : return ParserState::kInvalid; 118 : } 119 7 : case ParserState::kSecondByte_C: 120 7 : if (value >= 0x90 && value <= 0xBF) 121 : { 122 3 : return ParserState::kExtraTwoBytes; 123 : } 124 : else 125 : { 126 4 : return ParserState::kInvalid; 127 : } 128 5 : case ParserState::kSecondByte_D: 129 5 : if (value >= 0x80 && value <= 0x8F) 130 : { 131 1 : return ParserState::kExtraTwoBytes; 132 : } 133 : else 134 : { 135 4 : return ParserState::kInvalid; 136 : } 137 55 : case ParserState::kExtraOneByte: 138 55 : if (value >= 0x80 && value <= 0xBF) 139 : { 140 55 : return ParserState::kFirstByte; 141 : } 142 : else 143 : { 144 0 : return ParserState::kInvalid; 145 : } 146 41 : case ParserState::kExtraTwoBytes: 147 41 : if (value >= 0x80 && value <= 0xBF) 148 : { 149 41 : return ParserState::kExtraOneByte; 150 : } 151 : else 152 : { 153 0 : return ParserState::kInvalid; 154 : } 155 2 : case ParserState::kExtraThreeBytes: 156 2 : if (value >= 0x80 && value <= 0xBF) 157 : { 158 2 : return ParserState::kExtraTwoBytes; 159 : } 160 : else 161 : { 162 0 : return ParserState::kInvalid; 163 : } 164 0 : default: 165 0 : return ParserState::kInvalid; 166 : } 167 : } 168 : 169 : } // namespace 170 : 171 2085 : bool IsValid(CharSpan span) 172 : { 173 2085 : ParserState state = ParserState::kFirstByte; 174 : 175 2085 : const char * data = span.data(); 176 2085 : const size_t kLength = span.size(); 177 : 178 : // Every byte should be valid 179 117296 : for (size_t i = 0; i < kLength; i++) 180 : { 181 115243 : state = NextState(state, static_cast<uint8_t>(data[i])); 182 : 183 115243 : if (state == ParserState::kInvalid) 184 : { 185 32 : return false; 186 : } 187 : } 188 : 189 : // finally no continuation should be expected 190 2053 : return state == ParserState::kFirstByte; 191 : } 192 : 193 : } // namespace Utf8 194 : } // namespace chip