• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
31 inline uint32_t JERRY_ATTR_ALWAYS_INLINE
lit_get_magic_string_ex_count(void)32 lit_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  */
42 const lit_utf8_byte_t *
lit_get_magic_string_utf8(uint32_t id)43 lit_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  */
67 lit_utf8_size_t
lit_get_magic_string_size(uint32_t id)68 lit_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  */
93 static lit_magic_string_id_t
lit_get_magic_string_size_block_start(lit_utf8_size_t size)94 lit_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  */
119 const lit_utf8_byte_t *
lit_get_magic_string_ex_utf8(uint32_t id)120 lit_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  */
132 lit_utf8_size_t
lit_get_magic_string_ex_size(uint32_t id)133 lit_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  */
141 void
lit_magic_strings_ex_set(const lit_utf8_byte_t * const * ex_str_items,uint32_t count,const lit_utf8_size_t * ex_str_sizes)142 lit_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  */
202 lit_magic_string_id_t
lit_is_utf8_string_magic(const lit_utf8_byte_t * string_p,lit_utf8_size_t string_size)203 lit_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  */
243 lit_magic_string_id_t
lit_is_utf8_string_pair_magic(const lit_utf8_byte_t * string1_p,lit_utf8_size_t string1_size,const lit_utf8_byte_t * string2_p,lit_utf8_size_t string2_size)244 lit_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  */
295 lit_magic_string_ex_id_t
lit_is_ex_utf8_string_magic(const lit_utf8_byte_t * string_p,lit_utf8_size_t string_size)296 lit_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  */
352 lit_magic_string_ex_id_t
lit_is_ex_utf8_string_pair_magic(const lit_utf8_byte_t * string1_p,lit_utf8_size_t string1_size,const lit_utf8_byte_t * string2_p,lit_utf8_size_t string2_size)353 lit_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  */
419 lit_utf8_byte_t *
lit_copy_magic_string_to_buffer(lit_magic_string_id_t id,lit_utf8_byte_t * buffer_p,lit_utf8_size_t buffer_size)420 lit_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