1/* Copyright JS Foundation and other contributors, http://js.foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "jcontext.h" 17#include "lit-magic-strings.h" 18#include "lit-strings.h" 19 20/** 21 * Maximum number of external magic strings that can be registered. 22 */ 23#define LIT_EXTERNAL_MAGIC_STRING_LIMIT (UINT32_MAX / 2) 24 25/** 26 * Get number of external magic strings 27 * 28 * @return number of the strings, if there were registered, 29 * zero - otherwise. 30 */ 31inline uint32_t JERRY_ATTR_ALWAYS_INLINE 32lit_get_magic_string_ex_count (void) 33{ 34 return JERRY_CONTEXT (lit_magic_string_ex_count); 35} /* lit_get_magic_string_ex_count */ 36 37/** 38 * Get specified magic string as zero-terminated string 39 * 40 * @return pointer to zero-terminated magic string 41 */ 42const lit_utf8_byte_t * 43lit_get_magic_string_utf8 (uint32_t id) /**< magic string id */ 44{ 45 static const lit_utf8_byte_t * const lit_magic_strings[] JERRY_ATTR_CONST_DATA = 46 { 47/** @cond doxygen_suppress */ 48#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) 49#define LIT_MAGIC_STRING_DEF(id, utf8_string) \ 50 (const lit_utf8_byte_t *) utf8_string, 51#include "lit-magic-strings.inc.h" 52#undef LIT_MAGIC_STRING_DEF 53#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE 54/** @endcond */ 55 }; 56 57 JERRY_ASSERT (id < LIT_NON_INTERNAL_MAGIC_STRING__COUNT); 58 59 return lit_magic_strings[id]; 60} /* lit_get_magic_string_utf8 */ 61 62/** 63 * Get size of specified magic string 64 * 65 * @return size in bytes 66 */ 67lit_utf8_size_t 68lit_get_magic_string_size (uint32_t id) /**< magic string id */ 69{ 70 static const lit_magic_size_t lit_magic_string_sizes[] JERRY_ATTR_CONST_DATA = 71 { 72/** @cond doxygen_suppress */ 73#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) 74#define LIT_MAGIC_STRING_DEF(id, utf8_string) \ 75 sizeof(utf8_string) - 1, 76#include "lit-magic-strings.inc.h" 77#undef LIT_MAGIC_STRING_DEF 78#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE 79/** @endcond */ 80 }; 81 82 JERRY_ASSERT (id < LIT_NON_INTERNAL_MAGIC_STRING__COUNT); 83 84 return lit_magic_string_sizes[id]; 85} /* lit_get_magic_string_size */ 86 87/** 88 * Get the block start element with the given size from 89 * the list of ECMA and implementation-defined magic string constants 90 * 91 * @return magic string id 92 */ 93static lit_magic_string_id_t 94lit_get_magic_string_size_block_start (lit_utf8_size_t size) /**< magic string size */ 95{ 96 static const lit_magic_string_id_t lit_magic_string_size_block_starts[] JERRY_ATTR_CONST_DATA = 97 { 98/** @cond doxygen_suppress */ 99#define LIT_MAGIC_STRING_DEF(id, utf8_string) 100#define LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE(size, id) \ 101 id, 102#include "lit-magic-strings.inc.h" 103 LIT_NON_INTERNAL_MAGIC_STRING__COUNT 104#undef LIT_MAGIC_STRING_DEF 105#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE 106/** @endcond */ 107 }; 108 109 JERRY_ASSERT (size <= (sizeof (lit_magic_string_size_block_starts) / sizeof (lit_magic_string_id_t))); 110 111 return lit_magic_string_size_block_starts[size]; 112} /* lit_get_magic_string_size_block_start */ 113 114/** 115 * Get specified magic string as zero-terminated string from external table 116 * 117 * @return pointer to zero-terminated magic string 118 */ 119const lit_utf8_byte_t * 120lit_get_magic_string_ex_utf8 (uint32_t id) /**< extern magic string id */ 121{ 122 JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_array) && id < JERRY_CONTEXT (lit_magic_string_ex_count)); 123 124 return JERRY_CONTEXT (lit_magic_string_ex_array)[id]; 125} /* lit_get_magic_string_ex_utf8 */ 126 127/** 128 * Get size of specified external magic string 129 * 130 * @return size in bytes 131 */ 132lit_utf8_size_t 133lit_get_magic_string_ex_size (uint32_t id) /**< external magic string id */ 134{ 135 return JERRY_CONTEXT (lit_magic_string_ex_sizes)[id]; 136} /* lit_get_magic_string_ex_size */ 137 138/** 139 * Register external magic strings 140 */ 141void 142lit_magic_strings_ex_set (const lit_utf8_byte_t * const *ex_str_items, /**< character arrays, representing 143 * external magic strings' contents */ 144 uint32_t count, /**< number of the strings */ 145 const lit_utf8_size_t *ex_str_sizes) /**< sizes of the strings */ 146{ 147 JERRY_ASSERT (ex_str_items != NULL); 148 JERRY_ASSERT (count > 0); 149 JERRY_ASSERT (ex_str_sizes != NULL); 150 151 JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_array) == NULL); 152 JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_count) == 0); 153 JERRY_ASSERT (JERRY_CONTEXT (lit_magic_string_ex_sizes) == NULL); 154 155 /* Limit the number of external magic strings */ 156 if (count > LIT_EXTERNAL_MAGIC_STRING_LIMIT) 157 { 158 count = LIT_EXTERNAL_MAGIC_STRING_LIMIT; 159 } 160 161 /* Set external magic strings information */ 162 JERRY_CONTEXT (lit_magic_string_ex_array) = ex_str_items; 163 JERRY_CONTEXT (lit_magic_string_ex_count) = count; 164 JERRY_CONTEXT (lit_magic_string_ex_sizes) = ex_str_sizes; 165 166#ifndef JERRY_NDEBUG 167 for (lit_magic_string_ex_id_t id = (lit_magic_string_ex_id_t) 0; 168 id < JERRY_CONTEXT (lit_magic_string_ex_count); 169 id = (lit_magic_string_ex_id_t) (id + 1)) 170 { 171 lit_utf8_size_t string_size = JERRY_CONTEXT (lit_magic_string_ex_sizes)[id]; 172 173 /** 174 * Check whether the strings are sorted by size and lexicographically, 175 * e.g., "Bb" < "aa" < "aaa" < "xyz0". 176 */ 177 if (id > 0) 178 { 179 const lit_magic_string_ex_id_t prev_id = id - 1; 180 const lit_utf8_size_t prev_string_size = lit_get_magic_string_ex_size (prev_id); 181 JERRY_ASSERT (lit_is_valid_cesu8_string (lit_get_magic_string_ex_utf8 (id), 182 string_size)); 183 JERRY_ASSERT (prev_string_size <= string_size); 184 185 if (prev_string_size == string_size) 186 { 187 const lit_utf8_byte_t *prev_ex_string_p = lit_get_magic_string_ex_utf8 (prev_id); 188 const lit_utf8_byte_t *curr_ex_string_p = lit_get_magic_string_ex_utf8 (id); 189 JERRY_ASSERT (memcmp (prev_ex_string_p, curr_ex_string_p, string_size) < 0); 190 } 191 } 192 } 193#endif /* !JERRY_NDEBUG */ 194} /* lit_magic_strings_ex_set */ 195 196/** 197 * Returns the magic string id of the argument string if it is available. 198 * 199 * @return id - if magic string id is found, 200 * LIT_MAGIC_STRING__COUNT - otherwise. 201 */ 202lit_magic_string_id_t 203lit_is_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ 204 lit_utf8_size_t string_size) /**< string size in bytes */ 205{ 206 if (string_size > lit_get_magic_string_size (LIT_NON_INTERNAL_MAGIC_STRING__COUNT - 1)) 207 { 208 return LIT_MAGIC_STRING__COUNT; 209 } 210 211 /**< The string must be in this id range. */ 212 lit_utf8_size_t first = lit_get_magic_string_size_block_start (string_size); 213 lit_utf8_size_t last = lit_get_magic_string_size_block_start (string_size + 1); 214 215 while (first < last) 216 { 217 lit_utf8_size_t middle = ((first + last) / 2); /**< mid point of search */ 218 int compare = memcmp (lit_get_magic_string_utf8 ((lit_magic_string_id_t) middle), string_p, string_size); 219 220 if (compare == 0) 221 { 222 return (lit_magic_string_id_t) middle; 223 } 224 else if (compare > 0) 225 { 226 last = middle; 227 } 228 else 229 { 230 first = middle + 1; 231 } 232 } 233 234 return LIT_MAGIC_STRING__COUNT; 235} /* lit_is_utf8_string_magic */ 236 237/** 238 * Returns the magic string id of the argument string pair if it is available. 239 * 240 * @return id - if magic string id is found, 241 * LIT_MAGIC_STRING__COUNT - otherwise. 242 */ 243lit_magic_string_id_t 244lit_is_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, /**< first utf-8 string */ 245 lit_utf8_size_t string1_size, /**< first string size in bytes */ 246 const lit_utf8_byte_t *string2_p, /**< second utf-8 string */ 247 lit_utf8_size_t string2_size) /**< second string size in bytes */ 248{ 249 lit_utf8_size_t total_string_size = string1_size + string2_size; 250 251 if (total_string_size > lit_get_magic_string_size (LIT_NON_INTERNAL_MAGIC_STRING__COUNT - 1)) 252 { 253 return LIT_MAGIC_STRING__COUNT; 254 } 255 256 /**< The string must be in this id range. */ 257 lit_utf8_size_t first = lit_get_magic_string_size_block_start (total_string_size); 258 lit_utf8_size_t last = lit_get_magic_string_size_block_start (total_string_size + 1); 259 260 while (first < last) 261 { 262 lit_utf8_size_t middle = ((first + last) / 2); /**< mid point of search */ 263 const lit_utf8_byte_t *middle_string_p = lit_get_magic_string_utf8 ((lit_magic_string_id_t) middle); 264 265 int compare = memcmp (middle_string_p, string1_p, string1_size); 266 267 if (compare == 0) 268 { 269 compare = memcmp (middle_string_p + string1_size, string2_p, string2_size); 270 } 271 272 if (compare == 0) 273 { 274 return (lit_magic_string_id_t) middle; 275 } 276 else if (compare > 0) 277 { 278 last = middle; 279 } 280 else 281 { 282 first = middle + 1; 283 } 284 } 285 286 return LIT_MAGIC_STRING__COUNT; 287} /* lit_is_utf8_string_pair_magic */ 288 289/** 290 * Returns the ex magic string id of the argument string if it is available. 291 * 292 * @return id - if magic string id is found, 293 * lit_get_magic_string_ex_count () - otherwise. 294 */ 295lit_magic_string_ex_id_t 296lit_is_ex_utf8_string_magic (const lit_utf8_byte_t *string_p, /**< utf-8 string */ 297 lit_utf8_size_t string_size) /**< string size in bytes */ 298{ 299 const uint32_t magic_string_ex_count = lit_get_magic_string_ex_count (); 300 301 if (magic_string_ex_count == 0 302 || string_size > lit_get_magic_string_ex_size (magic_string_ex_count - 1)) 303 { 304 return (lit_magic_string_ex_id_t) magic_string_ex_count; 305 } 306 307 lit_magic_string_ex_id_t first = 0; 308 lit_magic_string_ex_id_t last = (lit_magic_string_ex_id_t) magic_string_ex_count; 309 310 while (first < last) 311 { 312 const lit_magic_string_ex_id_t middle = (first + last) / 2; 313 const lit_utf8_byte_t *ext_string_p = lit_get_magic_string_ex_utf8 (middle); 314 const lit_utf8_size_t ext_string_size = lit_get_magic_string_ex_size (middle); 315 316 if (string_size == ext_string_size) 317 { 318 const int string_compare = memcmp (ext_string_p, string_p, string_size); 319 320 if (string_compare == 0) 321 { 322 return middle; 323 } 324 else if (string_compare < 0) 325 { 326 first = middle + 1; 327 } 328 else 329 { 330 last = middle; 331 } 332 } 333 else if (string_size > ext_string_size) 334 { 335 first = middle + 1; 336 } 337 else 338 { 339 last = middle; 340 } 341 } 342 343 return (lit_magic_string_ex_id_t) magic_string_ex_count; 344} /* lit_is_ex_utf8_string_magic */ 345 346/** 347 * Returns the ex magic string id of the argument string pair if it is available. 348 * 349 * @return id - if magic string id is found, 350 * lit_get_magic_string_ex_count () - otherwise. 351 */ 352lit_magic_string_ex_id_t 353lit_is_ex_utf8_string_pair_magic (const lit_utf8_byte_t *string1_p, /**< first utf-8 string */ 354 lit_utf8_size_t string1_size, /**< first string size in bytes */ 355 const lit_utf8_byte_t *string2_p, /**< second utf-8 string */ 356 lit_utf8_size_t string2_size) /**< second string size in bytes */ 357{ 358 const uint32_t magic_string_ex_count = lit_get_magic_string_ex_count (); 359 const lit_utf8_size_t total_string_size = string1_size + string2_size; 360 361 if (magic_string_ex_count == 0 362 || total_string_size > lit_get_magic_string_ex_size (magic_string_ex_count - 1)) 363 { 364 return (lit_magic_string_ex_id_t) magic_string_ex_count; 365 } 366 367 lit_magic_string_ex_id_t first = 0; 368 lit_magic_string_ex_id_t last = (lit_magic_string_ex_id_t) magic_string_ex_count; 369 370 while (first < last) 371 { 372 const lit_magic_string_ex_id_t middle = (first + last) / 2; 373 const lit_utf8_byte_t *ext_string_p = lit_get_magic_string_ex_utf8 (middle); 374 const lit_utf8_size_t ext_string_size = lit_get_magic_string_ex_size (middle); 375 376 if (total_string_size == ext_string_size) 377 { 378 int string_compare = memcmp (ext_string_p, string1_p, string1_size); 379 380 if (string_compare == 0) 381 { 382 string_compare = memcmp (ext_string_p + string1_size, string2_p, string2_size); 383 } 384 385 if (string_compare == 0) 386 { 387 return middle; 388 } 389 else if (string_compare < 0) 390 { 391 first = middle + 1; 392 } 393 else 394 { 395 last = middle; 396 } 397 } 398 else if (total_string_size > ext_string_size) 399 { 400 first = middle + 1; 401 } 402 else 403 { 404 last = middle; 405 } 406 } 407 408 return (lit_magic_string_ex_id_t) magic_string_ex_count; 409} /* lit_is_ex_utf8_string_pair_magic */ 410 411/** 412 * Copy magic string to buffer 413 * 414 * Warning: 415 * the routine requires that buffer size is enough 416 * 417 * @return pointer to the byte next to the last copied in the buffer 418 */ 419lit_utf8_byte_t * 420lit_copy_magic_string_to_buffer (lit_magic_string_id_t id, /**< magic string id */ 421 lit_utf8_byte_t *buffer_p, /**< destination buffer */ 422 lit_utf8_size_t buffer_size) /**< size of buffer */ 423{ 424 const lit_utf8_byte_t *magic_string_bytes_p = lit_get_magic_string_utf8 (id); 425 lit_utf8_size_t magic_string_bytes_count = lit_get_magic_string_size (id); 426 427 const lit_utf8_byte_t *str_iter_p = magic_string_bytes_p; 428 lit_utf8_byte_t *buf_iter_p = buffer_p; 429 lit_utf8_size_t bytes_copied = 0; 430 431 while (magic_string_bytes_count--) 432 { 433 bytes_copied ++; 434 JERRY_ASSERT (bytes_copied <= buffer_size); 435 436 *buf_iter_p++ = *str_iter_p++; 437 } 438 439 return buf_iter_p; 440} /* lit_copy_magic_string_to_buffer */ 441