1 /* 2 * Hunt - A xml library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.xml.Internal; 13 14 import hunt.xml.Common; 15 16 import hunt.logging.ConsoleLogger; 17 18 // dfmt off 19 20 ubyte[256] lookup_whitespace = [ 21 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 22 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 23 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 24 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 25 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 26 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 27 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A 33 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B 34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C 35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D 36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E 37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F 38 ]; // Whitespace table 39 40 ubyte[256] lookup_node_name = [ 41 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 42 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 43 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 44 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 45 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 46 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 47 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 48 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 49 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 50 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 51 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 52 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 53 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 54 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 55 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 56 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 57 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F 58 ]; // Node name table 59 60 ubyte[256] lookup_element_name = [ 61 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 62 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 63 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 64 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 65 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, // 3 66 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 67 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 68 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 69 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 70 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 71 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 72 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 73 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 74 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 75 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 76 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 77 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F 78 ]; // Element name table 79 80 ubyte[256] lookup_text = [ 81 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 82 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 83 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 84 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 85 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 86 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 87 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 88 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 89 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 90 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 91 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 92 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 93 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 94 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 95 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 96 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 97 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F 98 ]; 99 // Text table 100 ubyte[256] lookup_text_pure_no_ws = [ 101 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 102 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 103 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 104 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 105 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 106 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 107 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 108 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 109 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 110 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 111 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 112 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 113 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 114 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 115 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 116 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 117 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F 118 ]; 119 // Text table 120 ubyte[256] lookup_text_pure_with_ws = [ 121 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 122 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 123 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 124 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 125 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 126 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 127 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 128 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 129 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 130 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 131 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 132 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 133 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 134 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 135 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 136 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 137 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F 138 ]; 139 140 // Text table 141 ubyte[256] lookup_attribute_name = [ 142 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 143 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 144 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 145 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 146 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 147 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 148 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 149 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 150 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 151 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 152 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 153 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 154 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 155 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 156 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 157 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 158 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F 159 ]; 160 161 // Attribute name table 162 ubyte[256] lookup_attribute_data_1 = [ 163 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 164 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 165 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 166 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 167 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 168 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 169 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 170 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 171 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 172 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 173 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 174 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 175 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 176 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 177 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 178 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 179 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F 180 ]; 181 182 // Attribute data table with single quote 183 ubyte[256] lookup_attribute_data_1_pure = [ 184 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 185 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 186 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 187 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 188 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 189 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 190 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 191 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 192 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 193 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 194 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 195 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 196 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 197 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 198 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 199 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 200 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F 201 ]; 202 203 // Attribute data table with single quote 204 ubyte[256] lookup_attribute_data_2 = [ 205 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 206 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 207 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 208 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 209 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 210 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 211 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 212 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 213 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 214 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 215 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 216 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 217 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 218 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 219 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 220 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 221 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F 222 ]; 223 224 // Attribute data table with double quotes 225 ubyte[256] lookup_attribute_data_2_pure = [ 226 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 227 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 228 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 229 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 230 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 231 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 232 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 233 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 234 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 235 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 236 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 237 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A 238 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B 239 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C 240 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D 241 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E 242 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F 243 ]; 244 245 // Attribute data table with double quotes 246 247 ubyte[256] lookup_digits = [ 248 // 0 1 2 3 4 5 6 7 8 9 A B C D E F 249 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0 250 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1 251 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2 252 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3 253 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4 254 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5 255 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6 256 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7 257 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8 258 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9 259 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A 260 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B 261 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C 262 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D 263 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E 264 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F 265 ]; 266 267 // Digits 268 269 ubyte[256] lookup_upcase = [ 270 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F 271 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 272 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 273 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 274 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 275 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 276 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 277 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6 278 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7 279 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8 280 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9 281 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A 282 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B 283 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C 284 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D 285 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E 286 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F 287 ]; 288 289 // dfmt on 290 291 void insertCodedCharacter(int Flags)(ref char[] text, ulong code) 292 { 293 if (Flags & ParsingFlags.NoUtf8) 294 { 295 // Insert 8-bit ASCII character 296 // Todo: possibly verify that code is less than 256 and use replacement char otherwise? 297 text[0] = cast(char)(code); 298 text = text[ 1 .. $]; 299 } 300 else 301 { 302 // Insert UTF8 sequence 303 if (code < 0x80) // 1 byte sequence 304 { 305 text[0] = cast(char)(code); 306 text = text[1 .. $]; 307 } 308 else if (code < 0x800) // 2 byte sequence 309 { 310 text[1] = cast(char)((code | 0x80) & 0xBF); code >>= 6; 311 text[0] = cast(char)(code | 0xC0); 312 text = text[ 2 .. $]; 313 } 314 else if (code < 0x10000) // 3 byte sequence 315 { 316 text[2] = cast(char)((code | 0x80) & 0xBF); code >>= 6; 317 text[1] = cast(char)((code | 0x80) & 0xBF); code >>= 6; 318 text[0] = cast(char)(code | 0xE0); 319 text = text[3 .. $]; 320 } 321 else if (code < 0x110000) // 4 byte sequence 322 { 323 text[3] = cast(char)((code | 0x80) & 0xBF); code >>= 6; 324 text[2] = cast(char)((code | 0x80) & 0xBF); code >>= 6; 325 text[1] = cast(char)((code | 0x80) & 0xBF); code >>= 6; 326 text[0] = cast(char)(code | 0xF0); 327 text = text[4 .. $]; 328 } 329 else // Invalid, only codes up to 0x10FFFF are allowed in Unicode 330 { 331 throw new XmlParsingException("invalid numeric character entity", text); 332 } 333 } 334 } 335 336 // Skip characters until predicate evaluates to true while doing the following: 337 // - replacing XML character entity references with proper characters (' & " < > &#...;) 338 // - condensing whitespace sequences to single space character 339 340 static char[] skipAndExpandCharacterRefs(T , TP , int Flags)(ref char[] text) 341 { 342 // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip 343 if (Flags & ParsingFlags.EntityTranslation && 344 !(Flags & ParsingFlags.NormalizeWhitespace) && 345 !(Flags & ParsingFlags.TrimWhitespace)) 346 { 347 skip!(T)(text); 348 return text; 349 } 350 351 // Use simple skip until first modification is detected 352 skip!(TP)(text); 353 // Use translation skip 354 char[] src = text; 355 char[] dest = src; 356 long index = 0; 357 while (T.test(src[0])) 358 { 359 // If entity translation is enabled 360 if (!(Flags & ParsingFlags.EntityTranslation)) 361 { 362 // Test if replacement is needed 363 if (src[0] == ('&')) 364 { 365 switch (src[1]) 366 { 367 368 // & ' 369 case ('a'): 370 if (src[2] == ('m') && src[3] == ('p') && src[4] == (';')) 371 { 372 dest[index] = ('&'); 373 ++index; 374 src=src[5..$]; 375 376 continue; 377 } 378 if (src[2] == ('p') && src[3] == ('o') && src[4] == ('s') && src[5] == (';')) 379 { 380 dest[index] = ('\''); 381 ++index; 382 src = src[6 .. $]; 383 continue; 384 } 385 break; 386 387 // " 388 case ('q'): 389 if (src[2] == ('u') && src[3] == ('o') && src[4] == ('t') && src[5] == (';')) 390 { 391 dest[index] = ('"'); 392 ++index; 393 src = src[6 .. $]; 394 continue; 395 } 396 break; 397 398 // > 399 case ('g'): 400 if (src[2] == ('t') && src[3] == (';')) 401 { 402 dest[index] = ('>'); 403 ++index; 404 src = src[4 .. $]; 405 continue; 406 } 407 break; 408 409 // < 410 case ('l'): 411 if (src[2] == ('t') && src[3] == (';')) 412 { 413 dest[index] = ('<'); 414 ++index; 415 src = src[ 4 .. $]; 416 continue; 417 } 418 break; 419 420 // &#...; - assumes ASCII 421 case ('#'): 422 if (src[2] == ('x')) 423 { 424 ulong code = 0; 425 src = src[3 .. $]; // Skip &#x 426 while (1) 427 { 428 ubyte digit = lookup_digits[src[0]]; 429 if (digit == 0xFF) 430 break; 431 code = code * 16 + digit; 432 src = src[1 .. $]; 433 } 434 435 insertCodedCharacter!Flags(dest, code); // Put character in output 436 } 437 else 438 { 439 ulong code = 0; 440 src = src[2 .. $]; // Skip &# 441 while (1) 442 { 443 ubyte digit = lookup_digits[src[0]]; 444 if (digit == 0xFF) 445 break; 446 code = code * 10 + digit; 447 src=src[1 .. $]; 448 } 449 insertCodedCharacter!Flags(dest, code); // Put character in output 450 } 451 if (src[0] == (';')) 452 src=src[1..$]; 453 else 454 throw new XmlParsingException("expected ;", src); 455 continue; 456 457 // Something else 458 default: 459 // Ignore, just copy '&' verbatim 460 break; 461 462 } 463 } 464 } 465 466 // If whitespace condensing is enabled 467 if (Flags & ParsingFlags.NormalizeWhitespace) 468 { 469 // Test if condensing is needed 470 if (WhitespacePred.test(src[0])) 471 { 472 dest[index] = (' '); ++index; // Put single space in dest 473 src = src[1 .. $]; // Skip first whitespace char 474 // Skip remaining whitespace chars 475 while (WhitespacePred.test(src[0])) 476 src = src[1 .. $]; 477 continue; 478 } 479 } 480 481 // No replacement, only copy character 482 dest[index] = src[0]; 483 ++index; 484 src = src[1 .. $]; 485 486 } 487 488 // Return new end 489 text = src; 490 dest = dest[index..$]; 491 return dest; 492 493 } 494 495 // private static void skip(T )(ref char[] text) 496 // { 497 498 // char[] tmp = text; 499 // while(tmp.length > 0 && T.test(tmp[0])) 500 // { 501 // tmp = tmp[1 .. $]; 502 // } 503 // text = tmp; 504 // } 505 506 507 void skip(T)(ref char[] text) 508 { 509 int index = 0; 510 int length = cast(int)text.length; 511 while(index < text.length && T.test(text[index])) 512 index++; 513 text = text[index .. $]; 514 } 515 516 struct WhitespacePred 517 { 518 static ubyte test(ubyte ch) 519 { 520 return lookup_whitespace[ch]; 521 } 522 } 523 524 // Detect node name character 525 struct NodeNamePred 526 { 527 static ubyte test(ubyte ch) 528 { 529 return lookup_node_name[ch]; 530 } 531 } 532 533 // Detect element name character 534 struct ElementNamePred 535 { 536 static ubyte test(ubyte ch) 537 { 538 return lookup_element_name[ch]; 539 } 540 } 541 542 // Detect attribute name character 543 struct AttributeNamePred 544 { 545 static ubyte test(ubyte ch) 546 { 547 return lookup_attribute_name[ch]; 548 } 549 } 550 551 // Detect text character (PCDATA) 552 struct TextPred 553 { 554 static ubyte test(ubyte ch) 555 { 556 return lookup_text[ch]; 557 } 558 } 559 560 // Detect text character (PCDATA) that does not require processing 561 struct TextPureNoWsPred 562 { 563 static ubyte test(ubyte ch) 564 { 565 return lookup_text_pure_no_ws[ch]; 566 } 567 } 568 569 // Detect text character (PCDATA) that does not require processing 570 struct TextPureWithWsPred 571 { 572 static ubyte test(ubyte ch) 573 { 574 return lookup_text_pure_with_ws[ch]; 575 } 576 } 577 578 // Detect attribute value character 579 580 struct AttributeValuePred(alias Quote) 581 { 582 static ubyte test(ubyte ch) 583 { 584 if (Quote == '\'') 585 return lookup_attribute_data_1[ch]; 586 else if (Quote == '"') 587 return lookup_attribute_data_2[ch]; 588 else 589 return 0; // Should never be executed, to avoid warnings on Comeau 590 } 591 } 592 593 // Detect attribute value character 594 struct AttributeValuePurePred(alias Quote) 595 { 596 static ubyte test(ubyte ch) 597 { 598 if (Quote == '\'') 599 return lookup_attribute_data_1_pure[ch]; 600 else if (Quote == ('"')) 601 return lookup_attribute_data_2_pure[ch]; 602 else 603 return 0; // Should never be executed, to avoid warnings on Comeau 604 } 605 }