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