1 /* 2 19.03.2018 12:58 - Применен алгоритм Максима Шибнева для fromUtf8to1251 (3-x кратное ускорение) 3 01.12.2017 17:57 - Темплате на toCON 4 13.08.2017 6:32 - Проверка и ускорение cp1251 -- Utf-8 -- cp1251 5 21.04.2016 18:13 - Проверка ИНН на корректность 6 31.05.2014 7:36:58 7 Add x64 8 Repair LTrim and RTrim 9 */ 10 /* 11 ё - 184 0451 d1-91 12 Ё - 168 0401 d0-81 13 » - 00BB 14 « - 00AB 15 */ 16 module asc1251; 17 18 import std.ascii; 19 import std.conv; 20 import std.utf; 21 22 23 bool isDigit1251(char c) pure nothrow { return (mm1251[c] & tDigit) != 0; } 24 25 bool isLower1251E(char c) pure nothrow { return (mm1251[c] & tEl) != 0; } 26 27 bool isUpper1251E(char c) pure nothrow { return (mm1251[c] & tEu) != 0; } 28 29 bool isLower1251R(char c) pure nothrow { return (mm1251[c] & tRl) != 0; } 30 31 bool isUpper1251R(char c) pure nothrow { return (mm1251[c] & tRu) != 0; } 32 33 bool isLetters1251E(char c) pure nothrow { return (mm1251[c] & (tEu + tEl)) != 0; } 34 35 bool isLetters1251R(char c) pure nothrow { return (mm1251[c] & (tRu + tRl)) != 0; } 36 37 bool isLetters1251(char c) pure nothrow { return (mm1251[c] & (tRu + tRl + tEu + tEl)) != 0; } 38 39 bool isPrintLetters1251(char c) pure nothrow { return (mm1251[c] & (tPrint)) != 0; } 40 41 unittest { 42 foreach (char c; "0123456789") 43 assert(asc1251.isDigit1251(c)); 44 foreach (char c; lowercase) 45 assert(asc1251.isLower1251E(c)); 46 foreach (char c; uppercase) 47 assert(asc1251.isUpper1251E(c)); 48 foreach (char c; lowercase1251R) 49 assert(asc1251.isLower1251R(c)); 50 foreach (char c; uppercase1251R) 51 assert(asc1251.isUpper1251R(c)); 52 foreach (char c; uppercase ~ lowercase) 53 assert(asc1251.isLetters1251E(c)); 54 foreach (char c; uppercase1251R ~ lowercase1251R) 55 assert(asc1251.isLetters1251R(c)); 56 } 57 58 char[] LTrim1251(char[] str) { 59 char[] rez; 60 if (str.length == 0) 61 return rez; 62 for (auto i = 0; i < str.length; i++) { 63 if (!isPrintLetters1251(str[i])) 64 continue; 65 rez = str[i .. $]; 66 break; 67 } 68 return rez; 69 } 70 71 char[] RTrim1251(char[] str) { 72 char[] rez; 73 if (str.length == 0) 74 return rez; 75 for (auto i = str.length; i != 0; i--) { 76 if (!isPrintLetters1251(str[i - 1])) 77 continue; 78 rez = str[0 .. i]; 79 break; 80 } 81 return rez; 82 } 83 84 char[] Trim1251(char[] str) { 85 return LTrim1251(RTrim1251(str)); 86 } 87 88 unittest { 89 assert(LTrim1251(cast(char[]) "") == cast(char[]) ""); 90 assert(RTrim1251(cast(char[]) "") == cast(char[]) ""); 91 assert(LTrim1251(cast(char[]) " Hello ") == cast(char[]) "Hello "); 92 assert(RTrim1251(cast(char[]) " Hello ") == cast(char[]) " Hello"); 93 assert(LTrim1251(cast(char[]) " " ~ uppercase1251R) == cast(char[]) uppercase1251R); 94 assert(LTrim1251(cast(char[]) " " ~ lowercase1251R) == cast(char[]) lowercase1251R); 95 assert(RTrim1251(lowercase1251R ~ cast(char[]) " ") == cast(char[]) lowercase1251R); 96 assert(Trim1251(cast(char[]) " " ~ "1234567890" ~ "\x0E\x0F") == cast(char[]) "1234567890"); 97 assert(LTrim1251(cast(char[]) " " ~ cast(char[]) "1") == cast(char[]) "1"); 98 } 99 100 char toUpper1251(char c) { 101 return isLower1251E(c) | isLower1251R(c) ? cast(char)(c - 32) : c; 102 } 103 104 char[] toUpper1251(char[] str) { 105 char[] rez; 106 foreach (char c; str) { 107 rez ~= toUpper1251(c); 108 } 109 return rez; 110 } 111 112 char toLower1251(char c) { 113 return isUpper1251E(c) | isUpper1251R(c) ? cast(char)(c + 32) : c; 114 } 115 116 char[] toLower1251(char[] str) { 117 char[] rez; 118 foreach (char c; str) { 119 rez ~= toLower1251(c); 120 } 121 return rez; 122 } 123 124 char[] toFio1251(char[] str) { 125 if (str.length == 0) { 126 return str; 127 } else { 128 if (str.length == 1) { 129 char[] rez; 130 return rez ~= toUpper1251(str[0]); 131 } else { 132 return toUpper1251(str[0]) ~ toLower1251(str[1 .. $]); 133 } 134 } 135 } 136 137 unittest { 138 assert(toUpper1251('a') == 'A'); 139 foreach (char c; lowercase) 140 assert(toUpper1251(c) == std.ascii.toUpper(c)); 141 foreach (char c; lowercase1251R) 142 assert(toUpper1251(c) == uppercase1251R[c - 224]); 143 assert(toUpper1251(cast(char[]) "hello[23]") == "HELLO[23]"); 144 assert(toUpper1251(cast(char[]) "") == ""); 145 assert(toLower1251(cast(char[]) "17(HELLO)") == "17(hello)"); 146 assert(toFio1251(cast(char[]) "HELLO!!!") == "Hello!!!"); 147 assert(toFio1251(cast(char[]) "") == ""); 148 assert(toFio1251(cast(char[]) "a") == "A"); 149 } 150 151 // Функция, возвращает подстроку используя разделитель. 152 char[] Split1251(char[] from, char rz, int poz) { 153 char[] rez; 154 int i, b, e, k; 155 auto dLfrom = from.length; 156 for (i = 0; i < dLfrom; i++) { 157 if (from[i] == rz) { 158 e = i; 159 if (k == poz) { 160 rez = from[b .. e]; // Есть начало и есть конец. Надо переписать 161 return rez; 162 } else { 163 b = i + 1; 164 k++; 165 } 166 } 167 } 168 if (poz == k) 169 rez ~= from[b .. $]; 170 return rez; 171 } 172 173 unittest { 174 assert(Split1251(cast(char[]) "ABC|DEF", '|', 0) == "ABC"); 175 assert(Split1251(cast(char[]) "ABC|DEF", '|', 1) == "DEF"); 176 assert(Split1251(cast(char[]) "ABC|DEF", '|', 2) == ""); 177 assert(Split1251(cast(char[]) "ABC|DEF", '#', 2) == ""); 178 assert(Split1251(cast(char[]) "ABC|DEF", '#', 0) == "ABC|DEF"); 179 } 180 // Шифрация-Дешифрация осуществляется в том же буфере в Win-1251 и AsciiZ 181 // sh - T - шифрация, F - дешифрция 182 // str - указатель на строку 183 void shifr(bool sh, char* str) { 184 char ch; 185 int z; 186 187 if (sh) { 188 z = -1; 189 } else { 190 z = +1; 191 } 192 for (char* i = str;; i++) { 193 ch = *i; 194 if (ch == 0) 195 break; 196 *i = cast(char)(ch + z); 197 } 198 } 199 /* // Шифрует строки utf-8 200 // T - зашифровать, F - расшифровать 201 string shifr8(bool sh, string str) { 202 string rez; ubyte b; 203 if(str.length == 0) return rez; 204 if(sh) { 205 for(int i; i != str.length; i++) { 206 b = cast(ubyte)str[i]; 207 if(b > 31) rez ~= "B" ~ (cast(char)(str[i]-1)); else rez ~= "A" ~ (cast(char)(str[i]+1)); 208 } 209 } 210 else { 211 for(int i; i != str.length; i+=2) { 212 b = cast(ubyte)str[i]; 213 if(b == 66) rez ~= (cast(char)(str[i+1]+1)); else rez ~= (cast(char)(str[i+1]-1)); 214 } 215 } 216 return rez; 217 } 218 */ 219 220 221 string shifr8n(T)(bool sh, T inStr) { 222 string rez; 223 ubyte b; 224 string str = cast(string) inStr; 225 return str; 226 if (str.length == 0) 227 return rez; 228 if (sh) { 229 for (int i; i != str.length; i++) { 230 b = cast(ubyte) str[i]; 231 if (b > 31) 232 rez ~= "B" ~ (cast(char)(str[i] - 1)); 233 else 234 rez ~= "A" ~ (cast(char)(str[i] + 1)); 235 } 236 } else { 237 for (int i; i != str.length; i += 2) { 238 b = cast(ubyte) str[i]; 239 if (b == 66) 240 rez ~= (cast(char)(str[i + 1] + 1)); 241 else 242 rez ~= (cast(char)(str[i + 1] - 1)); 243 } 244 } 245 return rez; 246 } 247 248 // Проверка даты вида '27.12.2014' на корректность 249 // str = '27.12.2014' 250 // Return: T - коррктная дата 251 bool TestDate1251(char[] str) { 252 bool rez = true; 253 char[] s; 254 char r = '.'; 255 if (str.length != 10) 256 return false; 257 s = Split1251(str, r, 0); 258 if (s.length != 2) 259 return false; 260 else { 261 if (!isDigit1251(s[0]) || !isDigit1251(s[1])) 262 return false; 263 int day = to!int(s); 264 if (!(day > 0 && day < 32)) 265 return false; 266 } 267 s = Split1251(str, r, 1); 268 if (s.length != 2) 269 return false; 270 else { 271 if (!isDigit1251(s[0]) || !isDigit1251(s[1])) 272 return false; 273 int mes = to!int(s); 274 if (!(mes > 0 && mes < 13)) 275 return false; 276 } 277 s = Split1251(str, r, 2); 278 if (s.length != 4) 279 return false; 280 else { 281 if (!isDigit1251(s[0]) || !isDigit1251(s[1]) || !isDigit1251(s[2]) || !isDigit1251(s[3])) 282 return false; 283 int yar = to!int(s); 284 if (!(yar > 1900 && yar < 3000)) 285 return false; 286 } 287 return rez; 288 } 289 290 // Проверка на соответствие ФИО, 'Иванов А.Н.', 1 большая, остальные маленькие и в конце инициалы 291 bool isFioii1251(char[] str) { 292 bool rez = true; 293 bool b1 = true; 294 bool b2 = true; 295 if (str.length < 6) 296 return false; 297 if (!(isUpper1251E(str[0]) || isUpper1251R(str[0]))) 298 return false; 299 if (!((str[$ - 1] == '.') && (str[$ - 3] == '.'))) 300 return false; 301 if (!(isUpper1251E(str[$ - 2]) || isUpper1251R(str[$ - 2]))) 302 return false; 303 if (!(isUpper1251E(str[$ - 4]) || isUpper1251R(str[$ - 4]))) 304 return false; 305 if (!(str[$ - 5] == ' ')) 306 return false; 307 if (str.length > 6) 308 foreach (char c; str[1 .. $ - 6]) { 309 if (!(isLower1251E(c) || isLower1251R(c))) 310 return false; 311 } 312 return rez; 313 } 314 315 // Проверка на соответствие ФИО, 'Иванов', 1 большая, остальные маленькие 316 bool isFio1251(char[] str) { 317 bool rez = true; 318 bool b1 = true; 319 bool b2 = true; 320 if (str.length == 0) 321 return false; 322 if (!(isUpper1251E(str[0]) || isUpper1251R(str[0]))) 323 return false; 324 foreach (char c; str[1 .. $]) { 325 if (!(isLower1251E(c) || isLower1251R(c))) 326 return false; 327 } 328 return rez; 329 } 330 // Проверка на соответствие 987, целое число 331 bool isInt1251(char[] str) { 332 bool rez = true; 333 bool b1 = true; 334 bool b2 = true; 335 if (str.length == 0) 336 return false; 337 foreach (char c; str[0 .. $]) { 338 if (!isDigit(c)) 339 return false; 340 } 341 return rez; 342 } 343 344 unittest { 345 assert(TestDate1251(cast(char[]) "12.10.1961") == true); 346 assert(TestDate1251(cast(char[]) "10.10.161") == false); 347 assert(TestDate1251(cast(char[]) "00.10.1621") == false); 348 assert(TestDate1251(cast(char[]) "31.10.1621") == false); 349 assert(TestDate1251(cast(char[]) "32.10.2001") == false); 350 assert(TestDate1251(cast(char[]) "31.12.1621") == false); 351 assert(TestDate1251(cast(char[]) "31.13.2621") == false); 352 assert(TestDate1251(cast(char[]) "31.13.3001") == false); 353 // ------------------ 354 assert(isFio1251(cast(char[]) "Gena") == true); 355 assert(isFio1251(cast(char[]) "Ge na") == false); 356 assert(isFio1251(cast(char[]) "\xC3\xE5\xED\xE0") == true); 357 assert(isFio1251(cast(char[]) "GenA") == false); 358 assert(isFio1251(cast(char[]) "\xC3\xE5\xED\xC0") == false); 359 } 360 361 // Проверка правильности ИНН string[10] 362 bool tstINN(string s) { 363 string s1; 364 bool rez; 365 int[10] weights = [2, 4, 10, 3, 5, 9, 4, 6, 8, 0]; 366 int summ; 367 368 if((s.length == 0) || (s.length > 10) ) return rez; 369 foreach(ch; s) { 370 if(!isDigit1251(ch)) return rez; 371 } 372 import std..string: format, strip; 373 import std.conv: to; 374 try { 375 s1 = format("%.10s", to!long(strip(s))); 376 } catch(Throwable) { 377 return rez; // Ошибка конвертации 378 } 379 if(s1 == "0000000000") return true; 380 // Перебор цифр и вычисление суммы 381 for(int i; i != 9; i++) { 382 auto digit = s1[i] - 48; 383 summ += digit * weights[i]; 384 } 385 auto ost = summ % 11; 386 if (ost > 9) ost = ost % 10; 387 if (ost == (s1[9] - 48)) rez = true; 388 return rez; 389 } 390 391 unittest { 392 assert(tstINN("") == false); 393 assert(tstINN("0000000000") == true); 394 assert(tstINN("0") == true); 395 assert(tstINN("0000A00000") == false); 396 assert(tstINN("+000000000") == false); 397 assert(tstINN("9999999999") == false); 398 assert(tstINN("05911013765") == false); 399 400 assert(tstINN("5905033450") == true); 401 assert(tstINN("5913001268") == true); 402 assert(tstINN("6607000556") == true); 403 assert(tstINN("5911013765") == true); 404 } 405 406 char[] from1251toUtf8(char[] str) pure nothrow @trusted { 407 char[] rez; 408 foreach (char c1; str) rez ~= mm1251_Utf8[c1]; 409 return rez; 410 } 411 string from1251toUtf8(T)(T str) pure nothrow { 412 char[] rez; 413 foreach (char c1; cast(char[])str) rez ~= mm1251_Utf8[c1]; 414 return cast(string)rez; 415 } 416 T1 fromUtf8to1251(T1, T2)(T2 str) { 417 return to!(T1)(fromUtf8to1251(to!(char[])(str))); 418 } 419 420 pragma(inline) size_t utf8Length(char[] src) pure nothrow @trusted { size_t len; foreach (ref b; src) { if ((b & 0xC0) != 0x80) len++; } return len; } 421 char[] fromUtf8to1251(char[] str) pure 422 { 423 if (str.length == 0) return str; 424 425 auto ret = new char[str.utf8Length]; 426 //auto ret = new char[str.length * 4]; 427 //char prb; 428 size_t srcPos; 429 size_t dstPos; 430 size_t id; 431 432 while(srcPos < str.length) { 433 id = stride(str, srcPos); 434 switch (id) { 435 case 1: 436 ret[dstPos] = str[srcPos]; 437 break; 438 case 2: 439 switch (str[srcPos]) { 440 case '\xD0': 441 immutable prb = tbl_xD0[(str[srcPos + 1]) - 129]; 442 ret[dstPos] = ((prb == 0) ? '?' : prb); 443 break; 444 case '\xD1': 445 immutable prb = tbl_xD1[(str[srcPos + 1]) - 128]; 446 ret[dstPos] = ((prb == 0) ? '2' : prb); 447 break; 448 case '\xD2': 449 switch (str[srcPos + 1]) { 450 case '\x91': 451 ret[dstPos] = cast(char)180; 452 break; 453 case '\x90': 454 ret[dstPos] = cast(char)165; 455 break; 456 default: 457 ret[dstPos] = cast(char)7; 458 break; 459 } 460 break; 461 case '\xD3': 462 break; 463 case '\xC2': 464 immutable prb = tbl_xC2[(str[srcPos + 1]) - 152]; 465 ret[dstPos] = ((prb == 0) ? '3' : prb); 466 break; 467 default: 468 ret[dstPos] = '?'; 469 break; 470 } 471 break; 472 case 3: 473 if (str[srcPos] == '\xE2') { 474 switch (str[srcPos + 1]) { 475 case '\x80': 476 immutable prb = tbl_x80[(str[srcPos + 2]) - 147]; 477 ret[dstPos] = ((prb == 0) ? '?' : prb); 478 break; 479 case '\x82': 480 ret[dstPos] = ((str[srcPos + 2] == '\xAC') ? cast(char)136 : '?'); 481 break; 482 case '\x84': 483 switch (str[srcPos + 2]) { 484 case '\x96': 485 ret[dstPos] = (cast(char)185); 486 break; 487 case '\xA2': 488 ret[dstPos] = (cast(char)153); 489 break; 490 default: 491 ret[dstPos] = '?'; 492 break; 493 } 494 break; 495 default: 496 break; 497 } 498 } 499 break; 500 default: // 4, 5, 6 501 break; 502 } // switch (id) 503 504 srcPos += id; 505 dstPos++; 506 } 507 508 return ret; 509 } 510 511 512 unittest { 513 assert(from1251toUtf8(cast(char[]) "\xC3\xE5\xED\xE0") == "Гена"); 514 assert(from1251toUtf8(cast(char[]) "Gena123") == "Gena123"); 515 516 assert(fromUtf8to1251(cast(char[]) "Гена") == "\xC3\xE5\xED\xE0"); 517 assert(fromUtf8to1251(cast(char[]) "Gena123") == "Gena123"); 518 char[] g = [ 'G', 'e', 'n', 'a', '1', '2', '3' ]; 519 assert(fromUtf8to1251!(char[])("Gena123") == g); 520 assert(fromUtf8to1251!(char[])("Гена") == "\xC3\xE5\xED\xE0"); 521 522 } 523 524 char[] from1251to866(char[] str) { 525 if (str.length == 0) return str; 526 int dlStr = str.length; 527 auto ret = new char[dlStr]; for(int i; i != dlStr; i++) ret[i] = _1251_866[str[i]]; 528 return ret; 529 } 530 531 string toCON(T)(T s) { 532 version (Windows) { 533 return to!string(from1251to866(fromUtf8to1251(cast(char[]) s))); 534 } 535 version (linux) { 536 return cast(string)s; 537 } 538 version (OSX) { 539 return cast(string)s; 540 } 541 } 542 string char1251toUtf8(char ch) { 543 return mm1251_Utf8[ch]; 544 } 545 546 private: 547 548 const int sByte = ubyte.max + 1; 549 550 const tBad = 0; // Бяка 551 const tDigit = 1; // Цифра 552 const tEl = 2; // Анг Маленькие 553 const tEu = 4; // Анг Большие 554 const tPrint = 8; // Печатные 555 const tRl = 16; // Рус Маленькие 556 const tRu = 32; // Рус Большие 557 558 private immutable char[][sByte] mm1251_Utf8= [ 559 /* 0 */ 560 "\x00", /* 1 */ "\x01", /* 2 */ "\x02", /* 3 */ "\x03", /* 4 */ "\x04",/* 5 */ 561 "\x05", /* 6 */ "\x06", /* 7 */ "\x07", /* 8 */ "\x08", /* 9 */ "\x09",/* 10 */ 562 "\x0A", /* 11 */ "\x0B", /* 12 */ "\x0C", /* 13 */ "\x0D", /* 14 */ "\x0E",/* 15 */ 563 "\x0F", /* 16 */ "\x10", /* 17 */ "\x11", /* 18 */ "\x12", /* 19 */ "\x13",/* 20 */ 564 "\x14", /* 21 */ "\x15", /* 22 */ "\x16", /* 23 */ "\x17", /* 24 */ "\x18",/* 25 */ 565 "\x19", /* 26 */ "\x1A", /* 27 */ "\x1B", /* 28 */ "\x1C", /* 29 */ "\x1D",/* 30 */ 566 "\x1E", /* 31 */ "\x1F", /* 32 */ "\x20", /* 33 */ "\x21", /* 34 */ "\x22",/* 35 */ 567 "\x23", /* 36 */ "\x24", /* 37 */ "\x25", /* 38 */ "\x26", /* 39 */ "\x27",/* 40 */ 568 "\x28", /* 41 */ "\x29", /* 42 */ "\x2A", /* 43 */ "\x2B", /* 44 */ "\x2C",/* 45 */ 569 "\x2D", /* 46 */ "\x2E", /* 47 */ "\x2F", /* 48 */ "\x30", /* 49 */ "\x31",/* 50 */ 570 "\x32", /* 51 */ "\x33", /* 52 */ "\x34", /* 53 */ "\x35", /* 54 */ "\x36",/* 55 */ 571 "\x37", /* 56 */ "\x38", /* 57 */ "\x39", /* 58 */ "\x3A", /* 59 */ "\x3B",/* 60 */ 572 "\x3C", /* 61 */ "\x3D", /* 62 */ "\x3E", /* 63 */ "\x3F", /* 64 */ "\x40",/* 65 */ 573 "\x41", /* 66 */ "\x42", /* 67 */ "\x43", /* 68 */ "\x44", /* 69 */ "\x45",/* 70 */ 574 "\x46", /* 71 */ "\x47", /* 72 */ "\x48", /* 73 */ "\x49", /* 74 */ "\x4A",/* 75 */ 575 "\x4B", /* 76 */ "\x4C", /* 77 */ "\x4D", /* 78 */ "\x4E", /* 79 */ "\x4F",/* 80 */ 576 "\x50", /* 81 */ "\x51", /* 82 */ "\x52", /* 83 */ "\x53", /* 84 */ "\x54",/* 85 */ 577 "\x55", /* 86 */ "\x56", /* 87 */ "\x57", /* 88 */ "\x58", /* 89 */ "\x59",/* 90 */ 578 "\x5A", /* 91 */ "\x5B", /* 92 */ "\x5C", /* 93 */ "\x5D", /* 94 */ "\x5E",/* 95 */ 579 "\x5F", /* 96 */ "\x60", /* 97 */ "\x61", /* 98 */ "\x62", /* 99 */ "\x63",/* 100 */ 580 "\x64", /* 101 */ "\x65", /* 102 */ "\x66", /* 103 */ "\x67", /* 104 */ "\x68",/* 105 */ 581 "\x69", /* 106 */ "\x6A", /* 107 */ "\x6B", /* 108 */ "\x6C", /* 109 */ "\x6D",/* 110 */ 582 "\x6E", /* 111 */ "\x6F", /* 112 */ "\x70", /* 113 */ "\x71", /* 114 */ "\x72",/* 115 */ 583 "\x73", /* 116 */ "\x74", /* 117 */ "\x75", /* 118 */ "\x76", /* 119 */ "\x77",/* 120 */ 584 "\x78", /* 121 */ "\x79", /* 122 */ "\x7A", /* 123 */ "\x7B", /* 124 */ "\x7C",/* 125 */ 585 "\x7D", /* 126 */ "\x7E", /* 127 */ "\x7F", /* 128 */ "\xD0\x82", /* 129 */ "\xD0\x83", 586 /* 130 */ 587 "\xE2\x80\x9A", /* 131 */ "\xD1\x93", /* 132 */ "\xE2\x80\x9E", /* 133 */ "\xE2\x80\xA6", /* 134 */ "\xE2\x80\xA0", /* 135 */ "\xE2\x80\xA1", 588 /* 136 */ 589 "\xE2\x82\xAC", /* 137 */ "\xE2\x80\xB0", /* 138 */ "\xD0\x89", /* 139 */ "\xE2\x80\xB9", /* 140 */ "\xD0\x8A", /* 141 */ "\xD0\x8C", 590 /* 142 */ 591 "\xD0\x8B", /* 143 */ "\xD0\x8F", /* 144 */ "\xD1\x92", /* 145 */ "\xE2\x80\x98", /* 146 */ "\xE2\x80\x99", /* 147 */ "\xE2\x80\x9C", 592 /* 148 */ 593 "\xE2\x80\x9D", /* 149 */ "\xE2\x80\xA2", /* 150 */ "\xE2\x80\x93", /* 151 */ "\xE2\x80\x94", /* 152 */ "\xC2\x98", /* 153 */ "\xE2\x84\xA2", 594 /* 154 */ 595 "\xD1\x99", /* 155 */ "\xE2\x80\xBA", /* 156 */ "\xD1\x9A", /* 157 */ "\xD1\x9C", /* 158 */ "\xD1\x9B", /* 159 */ "\xD1\x9F", 596 /* 160 */ 597 "\xC2\xA0", /* 161 */ "\xD0\x8E", /* 162 */ "\xD1\x9E", /* 163 */ "\xD0\x88", /* 164 */ "\xC2\xA4", /* 165 */ "\xD2\x90", 598 /* 166 */ 599 "\xC2\xA6", /* 167 */ "\xC2\xA7", /* 168 */ "\xD0\x81", /* 169 */ "\xC2\xA9", /* 170 */ "\xD0\x84", /* 171 */ "\xC2\xAB", 600 /* 172 */ 601 "\xC2\xAC", /* 173 */ "\xC2\xAD", /* 174 */ "\xC2\xAE", /* 175 */ "\xD0\x87", /* 176 */ "\xC2\xB0", /* 177 */ "\xC2\xB1", 602 /* 178 */ 603 "\xD0\x86", /* 179 */ "\xD1\x96", /* 180 */ "\xD2\x91", /* 181 */ "\xC2\xB5", /* 182 */ "\xC2\xB6", /* 183 */ "\xC2\xB7", 604 /* 184 */ 605 "\xD1\x91", /* 185 */ "\xE2\x84\x96", /* 186 */ "\xD1\x94", /* 187 */ "\xC2\xBB", /* 188 */ "\xD1\x98", /* 189 */ "\xD0\x85", 606 /* 190 */ 607 "\xD1\x95", /* 191 */ "\xD1\x97", /* 192 */ "\xD0\x90", /* 193 */ "\xD0\x91",/* 194 */ 608 "\xD0\x92", /* 195 */ "\xD0\x93", /* 196 */ "\xD0\x94", /* 197 */ "\xD0\x95", 609 /* 198 */ 610 "\xD0\x96", /* 199 */ "\xD0\x97", /* 200 */ "\xD0\x98", /* 201 */ "\xD0\x99",/* 202 */ 611 "\xD0\x9A", /* 203 */ "\xD0\x9B", /* 204 */ "\xD0\x9C", /* 205 */ "\xD0\x9D", 612 /* 206 */ 613 "\xD0\x9E", /* 207 */ "\xD0\x9F", /* 208 */ "\xD0\xA0", /* 209 */ "\xD0\xA1",/* 210 */ 614 "\xD0\xA2", /* 211 */ "\xD0\xA3", /* 212 */ "\xD0\xA4", /* 213 */ "\xD0\xA5", 615 /* 214 */ 616 "\xD0\xA6", /* 215 */ "\xD0\xA7", /* 216 */ "\xD0\xA8", /* 217 */ "\xD0\xA9",/* 218 */ 617 "\xD0\xAA", /* 219 */ "\xD0\xAB", /* 220 */ "\xD0\xAC", /* 221 */ "\xD0\xAD", 618 /* 222 */ 619 "\xD0\xAE", /* 223 */ "\xD0\xAF", /* 224 */ "\xD0\xB0", /* 225 */ "\xD0\xB1",/* 226 */ 620 "\xD0\xB2", /* 227 */ "\xD0\xB3", /* 228 */ "\xD0\xB4", /* 229 */ "\xD0\xB5", 621 /* 230 */ 622 "\xD0\xB6", /* 231 */ "\xD0\xB7", /* 232 */ "\xD0\xB8", /* 233 */ "\xD0\xB9",/* 234 */ 623 "\xD0\xBA", /* 235 */ "\xD0\xBB", /* 236 */ "\xD0\xBC", /* 237 */ "\xD0\xBD", 624 /* 238 */ 625 "\xD0\xBE", /* 239 */ "\xD0\xBF", /* 240 */ "\xD1\x80", /* 241 */ "\xD1\x81",/* 242 */ 626 "\xD1\x82", /* 243 */ "\xD1\x83", /* 244 */ "\xD1\x84", /* 245 */ "\xD1\x85", 627 /* 246 */ 628 "\xD1\x86", /* 247 */ "\xD1\x87", /* 248 */ "\xD1\x88", /* 249 */ "\xD1\x89",/* 250 */ 629 "\xD1\x8A", /* 251 */ "\xD1\x8B", /* 252 */ "\xD1\x8C", /* 253 */ "\xD1\x8D", 630 /* 254 */ 631 "\xD1\x8E", /* 255 */ "\xD1\x8F" 632 ]; 633 634 private immutable int[sByte] mm1251= [/* 0 */ 635 tBad, /* 1 */ tBad, /* 2 */ tBad, /* 3 */ tBad, /* 4 */ tBad, /* 5 */ tBad, /* 6 */ tBad, /* 7 */ tBad, /* 8 */ tBad, 636 /* 9 */ 637 tBad, /* 10 */ tBad, /* 11 */ tBad, /* 12 */ tBad, /* 13 */ tBad, /* 14 */ tBad, /* 15 */ tBad, /* 16 */ tBad, /* 17 */ tBad, 638 /* 18 */ 639 tBad, /* 19 */ tBad, /* 20 */ tBad, /* 21 */ tBad, /* 22 */ tBad, /* 23 */ tBad, /* 24 */ tBad, /* 25 */ tBad, /* 26 */ tBad, 640 /* 27 */ 641 tBad, /* 28 */ tBad, /* 29 */ tBad, /* 30 */ tBad, /* 31 */ tBad, /* 32 */ tBad, /* 33 */ tPrint, /* 34 */ tPrint, /* 35 */ tPrint, 642 /* 36 */ 643 tPrint, /* 37 */ tPrint, /* 38 */ tPrint, /* 39 */ tPrint, /* 40 */ tPrint, /* 41 */ tPrint, /* 42 */ tPrint, /* 43 */ tPrint, /* 44 */ tPrint, 644 /* 45 */ 645 tPrint, /* 46 */ tPrint, /* 47 */ tPrint, /* 48 */ tPrint + tDigit, /* 49 */ tPrint + tDigit, /* 50 */ tPrint + tDigit, /* 51 */ tPrint + tDigit, 646 /* 52 */ 647 tPrint + tDigit, /* 53 */ tPrint + tDigit, /* 54 */ tPrint + tDigit, /* 55 */ tPrint + tDigit, 648 /* 56 */ 649 tPrint + tDigit, /* 57 */ tPrint + tDigit, /* 58 */ tPrint, /* 59 */ tPrint, /* 60 */ tPrint, /* 61 */ tPrint, 650 /* 62 */ 651 tPrint, /* 63 */ tPrint, /* 64 */ tPrint,/* 65 */ 652 tPrint + tEu, /* 66 */ tPrint + tEu, /* 67 */ tPrint + tEu, /* 68 */ tPrint + tEu, /* 69 */ tPrint + tEu, /* 70 */ tPrint + tEu, 653 /* 71 */ 654 tPrint + tEu, /* 72 */ tPrint + tEu, /* 73 */ tPrint + tEu, /* 74 */ tPrint + tEu, /* 75 */ tPrint + tEu, /* 76 */ tPrint + tEu, 655 /* 77 */ 656 tPrint + tEu, /* 78 */ tPrint + tEu, /* 79 */ tPrint + tEu, /* 80 */ tPrint + tEu, /* 81 */ tPrint + tEu, /* 82 */ tPrint + tEu, 657 /* 83 */ 658 tPrint + tEu, /* 84 */ tPrint + tEu, /* 85 */ tPrint + tEu, /* 86 */ tPrint + tEu, /* 87 */ tPrint + tEu, /* 88 */ tPrint + tEu, 659 /* 89 */ 660 tPrint + tEu, /* 90 */ tPrint + tEu,/* 91 */ 661 tPrint, /* 92 */ tPrint, /* 93 */ tPrint, /* 94 */ tPrint, /* 95 */ tPrint, 662 /* 96 */ 663 tPrint,/* 97 */ 664 tPrint + tEl, /* 98 */ tPrint + tEl, /* 99 */ tPrint + tEl, /* 100 */ tPrint + tEl, /* 101 */ tPrint + tEl, /* 102 */ tPrint + tEl, 665 /* 103 */ 666 tPrint + tEl, /* 104 */ tPrint + tEl, /* 105 */ tPrint + tEl, /* 106 */ tPrint + tEl, /* 107 */ tPrint + tEl, /* 108 */ tPrint + tEl, 667 /* 109 */ 668 tPrint + tEl, /* 110 */ tPrint + tEl, /* 111 */ tPrint + tEl, /* 112 */ tPrint + tEl, /* 113 */ tPrint + tEl, /* 114 */ tPrint + tEl, 669 /* 115 */ 670 tPrint + tEl, /* 116 */ tPrint + tEl, /* 117 */ tPrint + tEl, /* 118 */ tPrint + tEl, /* 119 */ tPrint + tEl, /* 120 */ tPrint + tEl, 671 /* 121 */ 672 tPrint + tEl, /* 122 */ tPrint + tEl, /* 123 */ tPrint, /* 124 */ tPrint, /* 125 */ tPrint, /* 126 */ tPrint, /* 127 */ tPrint, /* 128 */ tPrint, 673 /* 129 */ 674 tPrint,/* 130 */ 675 tPrint, /* 131 */ tPrint, /* 132 */ tPrint, /* 133 */ tPrint, /* 134 */ tPrint, /* 135 */ tPrint, /* 136 */ tPrint, /* 137 */ tPrint,/* 138 */ 676 tPrint, /* 139 */ tPrint, /* 140 */ tPrint, /* 141 */ tPrint, /* 142 */ tPrint, /* 143 */ tPrint, /* 144 */ tPrint, /* 145 */ tPrint,/* 146 */ 677 tPrint, /* 147 */ tPrint, /* 148 */ tPrint, /* 149 */ tPrint, /* 150 */ tPrint, /* 151 */ tPrint, /* 152 */ tPrint, /* 153 */ tPrint,/* 154 */ 678 tPrint, /* 155 */ tPrint, /* 156 */ tPrint, /* 157 */ tPrint, /* 158 */ tPrint, /* 159 */ tPrint, /* 160 */ tPrint, /* 161 */ tPrint,/* 162 */ 679 tPrint, /* 163 */ tPrint, /* 164 */ tPrint, /* 165 */ tPrint, /* 166 */ tPrint, /* 167 */ tPrint, /* 168 */ tPrint + tRu, /* 169 */ tPrint, 680 /* 170 */ 681 tPrint, /* 171 */ tPrint, /* 172 */ tPrint, /* 173 */ tPrint, /* 174 */ tPrint, /* 175 */ tPrint, /* 176 */ tPrint, /* 177 */ tPrint,/* 178 */ 682 tPrint, /* 179 */ tPrint, /* 180 */ tPrint, /* 181 */ tPrint, /* 182 */ tPrint, /* 183 */ tPrint, /* 184 */ tPrint + tRl, /* 185 */ tPrint, 683 /* 186 */ 684 tPrint, /* 187 */ tPrint, /* 188 */ tPrint, /* 189 */ tPrint, /* 190 */ tPrint, /* 191 */ tPrint, /* 192 */ tPrint + tRu, 685 /* 193 */ 686 tPrint + tRu, /* 194 */ tPrint + tRu, /* 195 */ tPrint + tRu, /* 196 */ tPrint + tRu, /* 197 */ tPrint + tRu, /* 198 */ tPrint + tRu, 687 /* 199 */ 688 tPrint + tRu, /* 200 */ tPrint + tRu, /* 201 */ tPrint + tRu, /* 202 */ tPrint + tRu, /* 203 */ tPrint + tRu, /* 204 */ tPrint + tRu, 689 /* 205 */ 690 tPrint + tRu, /* 206 */ tPrint + tRu, /* 207 */ tPrint + tRu, /* 208 */ tPrint + tRu, /* 209 */ tPrint + tRu, /* 210 */ tPrint + tRu, 691 /* 211 */ 692 tPrint + tRu, /* 212 */ tPrint + tRu, /* 213 */ tPrint + tRu, /* 214 */ tPrint + tRu, /* 215 */ tPrint + tRu, /* 216 */ tPrint + tRu, 693 /* 217 */ 694 tPrint + tRu, /* 218 */ tPrint + tRu, /* 219 */ tPrint + tRu, /* 220 */ tPrint + tRu, /* 221 */ tPrint + tRu, /* 222 */ tPrint + tRu, 695 /* 223 */ 696 tPrint + tRu, /* 224 */ tPrint + tRl, /* 225 */ tPrint + tRl, /* 226 */ tPrint + tRl, /* 227 */ tPrint + tRl, /* 228 */ tPrint + tRl, 697 /* 229 */ 698 tPrint + tRl, /* 230 */ tPrint + tRl, /* 231 */ tPrint + tRl, /* 232 */ tPrint + tRl, /* 233 */ tPrint + tRl, /* 234 */ tPrint + tRl, 699 /* 235 */ 700 tPrint + tRl, /* 236 */ tPrint + tRl, /* 237 */ tPrint + tRl, /* 238 */ tPrint + tRl, /* 239 */ tPrint + tRl, /* 240 */ tPrint + tRl, 701 /* 241 */ 702 tPrint + tRl, /* 242 */ tPrint + tRl, /* 243 */ tPrint + tRl, /* 244 */ tPrint + tRl, /* 245 */ tPrint + tRl, /* 246 */ tPrint + tRl, 703 /* 247 */ 704 tPrint + tRl, /* 248 */ tPrint + tRl, /* 249 */ tPrint + tRl, /* 250 */ tPrint + tRl, /* 251 */ tPrint + tRl, /* 252 */ tPrint + tRl, 705 /* 253 */ 706 tPrint + tRl, /* 254 */ tPrint + tRl, /* 255 */ tPrint + tRl]; 707 708 // char mm1251u[sByte]; 709 private immutable uppercase1251R = "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF"; /// А..Я 710 private immutable lowercase1251R = "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"; /// А..Я 711 private immutable _1251_866 = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x18\x19\x1A\x1B......\x20!\x22#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.+++++++++++++++++++++++++++++++++++++++1\xF0345+++++++++++1\xF1\xFC++++++\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF"; 712 private immutable char[62] tbl_xD1 = [ 713 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 0,184,144,131,186,190, 714 179,191,188,154,156,158,157, 0,162,159, 0, 0,210,211,212,213,214,215,216,217,218,219, 715 220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237 716 ]; 717 private immutable char[63] tbl_xD0 = [ 718 168,128,129,170,189,178,175,163,138,140,142,141, 0,161,143,192,193,194,195,196,197,198, 719 199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, 720 221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 721 ]; 722 private immutable char[40] tbl_x80 = [ 723 150,151, 0, 0, 0,145,146,130, 0,147,148,132, 0,134,135,149, 0, 0, 0,133, 0, 0, 724 0, 0, 0, 0, 0, 0, 0,137, 0, 0, 0, 0, 0, 0, 0, 0,139,155 725 ]; 726 private immutable char[36] tbl_xC2 = [ 727 152, 0, 0, 0, 0, 0, 0, 0,160, 0, 0, 0,164, 0,166,167, 0,169, 0,171,172,173, 728 174, 0,176,177, 0, 0, 0,181,182,183, 0, 0, 0,187 729 ]; 730 731 bool isAtr1251(char c, int atr) { 732 return (mm1251[c] & atr) != 0; 733 }