mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Add utf-8 processing routines. Change ecma_char_t from char/uint16_t to uint16_t. Apply all utf-8 processing routines. Change char to jerry_api_char in API functions' declarations. JerryScript-DCO-1.0-Signed-off-by: Andrey Shitov a.shitov@samsung.com
438 lines
11 KiB
C++
438 lines
11 KiB
C++
/* Copyright 2015 Samsung Electronics Co., Ltd.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef LIT_LITERAL_STORAGE_H
|
|
#define LIT_LITERAL_STORAGE_H
|
|
|
|
#include "ecma-globals.h"
|
|
#include "rcs-recordset.h"
|
|
|
|
class lit_literal_storage_t;
|
|
extern lit_literal_storage_t lit_storage;
|
|
|
|
/**
|
|
* Charset record
|
|
*
|
|
* layout:
|
|
* ------- header -----------------------
|
|
* type (4 bits)
|
|
* alignment (2 bits)
|
|
* unused (2 bits)
|
|
* hash (8 bits)
|
|
* length (16 bits)
|
|
* pointer to prev (16 bits)
|
|
* ------- characters -------------------
|
|
* ...
|
|
* chars
|
|
* ....
|
|
* ------- alignment bytes --------------
|
|
* unused bytes (their count is specified
|
|
* by 'alignment' field in header)
|
|
* --------------------------------------
|
|
*/
|
|
class lit_charset_record_t : public rcs_record_t
|
|
{
|
|
friend class rcs_recordset_t;
|
|
friend class lit_literal_storage_t;
|
|
|
|
public:
|
|
/**
|
|
* Calculate the size that record will occupy inside the storage
|
|
*
|
|
* @return size of the record in bytes
|
|
*/
|
|
static size_t
|
|
size (size_t size) /**< size of the charset buffer */
|
|
{
|
|
return JERRY_ALIGNUP (size + header_size (), RCS_DYN_STORAGE_LENGTH_UNIT);
|
|
} /* size */
|
|
|
|
/**
|
|
* Get the size of the header part of the record
|
|
*
|
|
* @return size of the header in bytes
|
|
*/
|
|
static size_t
|
|
header_size ()
|
|
{
|
|
return _header_size;
|
|
} /* header_size */
|
|
|
|
/**
|
|
* Get the count of the alignment bytes at the end of record.
|
|
* These bytes are needed to align the record to RCS_DYN_STORAGE_ALIGNMENT.
|
|
*
|
|
* @return alignment bytes count (the value of the 'alignment' field in the header)
|
|
*/
|
|
size_t
|
|
get_alignment_bytes_count () const
|
|
{
|
|
return get_field (_alignment_field_pos, _alignment_field_width);
|
|
} /* get_alignment_bytes_count */
|
|
|
|
/**
|
|
* Set the count of the alignment bytes at the end of record (the value of the 'alignment' field in the header)
|
|
*/
|
|
void
|
|
set_alignment_bytes_count (size_t count) /**< count of the alignment bytes */
|
|
{
|
|
JERRY_ASSERT (count <= RCS_DYN_STORAGE_ALIGNMENT);
|
|
set_field (_alignment_field_pos, _alignment_field_width, count);
|
|
} /* set_alignment_bytes_count */
|
|
|
|
/**
|
|
* Get hash value of the record's charset.
|
|
*
|
|
* @return hash value of the string (the value of the 'hash' field in the header)
|
|
*/
|
|
lit_string_hash_t
|
|
get_hash () const
|
|
{
|
|
return (lit_string_hash_t) get_field (_hash_field_pos, _hash_field_width);
|
|
} /* get_hash */
|
|
|
|
/**
|
|
* Get the length of the string, which is contained inside the record
|
|
*
|
|
* @return length of the string (bytes count)
|
|
*/
|
|
lit_utf8_size_t
|
|
get_length () const
|
|
{
|
|
return (lit_utf8_size_t) (get_size () - header_size () - get_alignment_bytes_count ());
|
|
} /* get_length */
|
|
|
|
/**
|
|
* Get the size of the record
|
|
*
|
|
* @return size of the record in bytes
|
|
*/
|
|
size_t
|
|
get_size () const
|
|
{
|
|
return get_field (_length_field_pos, _length_field_width) * RCS_DYN_STORAGE_LENGTH_UNIT;
|
|
} /* get_size */
|
|
|
|
rcs_record_t *get_prev () const;
|
|
|
|
lit_utf8_size_t get_charset (lit_utf8_byte_t *, size_t);
|
|
|
|
int compare_utf8 (const lit_utf8_byte_t *, lit_utf8_size_t);
|
|
bool is_equal (lit_charset_record_t *);
|
|
bool is_equal_utf8_string (const lit_utf8_byte_t *, lit_utf8_size_t);
|
|
|
|
private:
|
|
/**
|
|
* Set record's size (the value of the 'length' field in the header)
|
|
*/
|
|
void
|
|
set_size (size_t size) /**< size in bytes */
|
|
{
|
|
JERRY_ASSERT (JERRY_ALIGNUP (size, RCS_DYN_STORAGE_ALIGNMENT) == size);
|
|
|
|
set_field (_length_field_pos, _length_field_width, size >> RCS_DYN_STORAGE_ALIGNMENT_LOG);
|
|
} /* set_size */
|
|
|
|
/**
|
|
* Set record's hash (the value of the 'hash' field in the header)
|
|
*/
|
|
void
|
|
set_hash (lit_string_hash_t hash) /**< hash value */
|
|
{
|
|
set_field (_hash_field_pos, _hash_field_width, hash);
|
|
} /* set_hash */
|
|
|
|
void set_prev (rcs_record_t *);
|
|
|
|
void set_charset (const lit_utf8_byte_t *, lit_utf8_size_t);
|
|
|
|
/**
|
|
* Offset and length of 'alignment' field, in bits
|
|
*/
|
|
static const uint32_t _alignment_field_pos = _fields_offset_begin;
|
|
static const uint32_t _alignment_field_width = 2u;
|
|
|
|
/**
|
|
* Offset and length of 'hash' field, in bits
|
|
*/
|
|
static const uint32_t _hash_field_pos = _alignment_field_pos + _alignment_field_width + 2u;
|
|
static const uint32_t _hash_field_width = 8u;
|
|
|
|
/**
|
|
* Offset and length of 'alignment' field, in bits
|
|
*/
|
|
static const uint32_t _length_field_pos = _hash_field_pos + _hash_field_width;
|
|
static const uint32_t _length_field_width = 16u;
|
|
|
|
/**
|
|
* Offset and length of 'prev' field, in bits
|
|
*/
|
|
static const uint32_t _prev_field_pos = _length_field_pos + _length_field_width;
|
|
static const uint32_t _prev_field_width = rcs_cpointer_t::bit_field_width;
|
|
|
|
static const size_t _header_size = RCS_DYN_STORAGE_LENGTH_UNIT + RCS_DYN_STORAGE_LENGTH_UNIT / 2;
|
|
}; /* lit_charset_record_t */
|
|
|
|
/**
|
|
* Magic string record
|
|
* Doesn't hold any characters. Corresponding string is identified by its id.
|
|
*
|
|
* Layout:
|
|
* ------- header -----------------------
|
|
* type (4 bits)
|
|
* magic string id (12 bits)
|
|
* pointer to prev (16 bits)
|
|
* --------------------------------------
|
|
*/
|
|
class lit_magic_record_t : public rcs_record_t
|
|
{
|
|
friend class rcs_recordset_t;
|
|
friend class lit_literal_storage_t;
|
|
|
|
public:
|
|
/**
|
|
* Calculate the size that record will occupy inside the storage
|
|
*
|
|
* @return size of the record in bytes
|
|
*/
|
|
static size_t size ()
|
|
{
|
|
return _size;
|
|
} /* size */
|
|
|
|
/**
|
|
* Get the size of the header part of the record
|
|
*
|
|
* @return size of the header in bytes
|
|
*/
|
|
static size_t header_size ()
|
|
{
|
|
return _size;
|
|
} /* header_size */
|
|
|
|
/**
|
|
* Get the size of the record
|
|
*
|
|
* @return size of the record in bytes
|
|
*/
|
|
size_t get_size () const
|
|
{
|
|
return _size;
|
|
} /* get_size */
|
|
|
|
/**
|
|
* Get magic string id which is held by the record
|
|
*
|
|
* @return magic string id
|
|
*/
|
|
template <typename magic_string_id_t>
|
|
magic_string_id_t get_magic_str_id () const
|
|
{
|
|
uint32_t id = get_field (magic_field_pos, magic_field_width);
|
|
return (magic_string_id_t) id;
|
|
} /* get_magic_str_id */
|
|
|
|
private:
|
|
/**
|
|
* Set record's size (the value of the 'length' field in the header)
|
|
*/
|
|
void set_size (size_t size) /**< size in bytes */
|
|
{
|
|
JERRY_ASSERT (size == get_size ());
|
|
} /* set_size */
|
|
|
|
template <typename magic_string_id_t>
|
|
void set_magic_str_id (magic_string_id_t id)
|
|
{
|
|
set_field (magic_field_pos, magic_field_width, id);
|
|
} /* set_magic_str_id */
|
|
|
|
/**
|
|
* Get previous record in the literal storage
|
|
*
|
|
* @return pointer to the previous record relative to this record, or NULL if this is the first record in the
|
|
* storage
|
|
*/
|
|
rcs_record_t *get_prev () const
|
|
{
|
|
return get_pointer (prev_field_pos, prev_field_width);
|
|
} /* get_prev */
|
|
|
|
/**
|
|
* Set the pointer to the previous record inside the literal storage (sets 'prev' field in the header)
|
|
*/
|
|
void set_prev (rcs_record_t *prev_rec_p)
|
|
{
|
|
set_pointer (prev_field_pos, prev_field_width, prev_rec_p);
|
|
} /* set_prev */
|
|
|
|
|
|
/**
|
|
* Offset and length of 'magic string id' field, in bits
|
|
*/
|
|
static const uint32_t magic_field_pos = _fields_offset_begin;
|
|
static const uint32_t magic_field_width = 12u;
|
|
|
|
/**
|
|
* Offset and length of 'prev' field, in bits
|
|
*/
|
|
static const uint32_t prev_field_pos = magic_field_pos + magic_field_width;
|
|
static const uint32_t prev_field_width = rcs_cpointer_t::bit_field_width;
|
|
|
|
static const size_t _size = RCS_DYN_STORAGE_LENGTH_UNIT;
|
|
}; /* lit_magic_record_t */
|
|
|
|
/**
|
|
* Number record
|
|
* Doesn't hold any characters, holds a number. Numbers from source code are represented as number literals.
|
|
*
|
|
* Layout:
|
|
* ------- header -----------------------
|
|
* type (4 bits)
|
|
* padding (12 bits)
|
|
* pointer to prev (16 bits)
|
|
* --------------------------------------
|
|
* ecma_number_t
|
|
*/
|
|
class lit_number_record_t : public rcs_record_t
|
|
{
|
|
friend class rcs_recordset_t;
|
|
friend class lit_literal_storage_t;
|
|
|
|
public:
|
|
|
|
static size_t
|
|
size ()
|
|
{
|
|
return _size;
|
|
} /* size */
|
|
|
|
/**
|
|
* Get the size of the header part of the record
|
|
*
|
|
* @return size of the header in bytes
|
|
*/
|
|
static size_t
|
|
header_size ()
|
|
{
|
|
return _header_size;
|
|
} /* header_size */
|
|
|
|
/**
|
|
* Get the size of the record
|
|
*
|
|
* @return size of the record in bytes
|
|
*/
|
|
size_t
|
|
get_size () const
|
|
{
|
|
return _size;
|
|
} /* get_size */
|
|
|
|
/**
|
|
* Get previous record in the literal storage
|
|
*
|
|
* @return pointer to the previous record relative to this record, or NULL if this is the first record in the
|
|
* storage
|
|
*/
|
|
rcs_record_t *
|
|
get_prev () const
|
|
{
|
|
return get_pointer (prev_field_pos, prev_field_width);
|
|
} /* get_prev */
|
|
|
|
/**
|
|
* Set the pointer to the previous record inside the literal storage (sets 'prev' field in the header)
|
|
*/
|
|
void
|
|
set_prev (rcs_record_t *prev_rec_p)
|
|
{
|
|
set_pointer (prev_field_pos, prev_field_width, prev_rec_p);
|
|
} /* set_prev */
|
|
|
|
/**
|
|
* Get the number which is held by the record
|
|
*
|
|
* @return number
|
|
*/
|
|
ecma_number_t
|
|
get_number () const
|
|
{
|
|
rcs_record_iterator_t it ((rcs_recordset_t *)&lit_storage,
|
|
(rcs_record_t *)this);
|
|
it.skip (header_size ());
|
|
|
|
return it.read<ecma_number_t> ();
|
|
} /* get_number */
|
|
|
|
private:
|
|
/**
|
|
* Set record's size (the value of the 'length' field in the header)
|
|
*/
|
|
void
|
|
set_size (size_t size) /**< size in bytes */
|
|
{
|
|
JERRY_ASSERT (size == get_size ());
|
|
} /* set_size */
|
|
|
|
/**
|
|
* Offset and length of 'prev' field, in bits
|
|
*/
|
|
static const uint32_t prev_field_pos = _fields_offset_begin + 12u;
|
|
static const uint32_t prev_field_width = rcs_cpointer_t::bit_field_width;
|
|
|
|
static const size_t _header_size = RCS_DYN_STORAGE_LENGTH_UNIT;
|
|
static const size_t _size = _header_size + sizeof (ecma_number_t);
|
|
}; /* lit_number_record_t */
|
|
|
|
/**
|
|
* Literal storage
|
|
*
|
|
* Represents flexible storage for the literals. The following records could be created inside the storage:
|
|
* - charset literal (lit_charset_record_t)
|
|
* - magic string literal (lit_magic_record_t)
|
|
* - number literal (lit_number_record_t)
|
|
*/
|
|
class lit_literal_storage_t : public rcs_recordset_t
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
LIT_STR = _first_type_id,
|
|
LIT_MAGIC_STR,
|
|
LIT_MAGIC_STR_EX,
|
|
LIT_NUMBER
|
|
};
|
|
|
|
lit_charset_record_t *create_charset_record (const lit_utf8_byte_t *, lit_utf8_size_t);
|
|
lit_magic_record_t *create_magic_record (lit_magic_string_id_t);
|
|
lit_magic_record_t *create_magic_record_ex (lit_magic_string_ex_id_t);
|
|
lit_number_record_t *create_number_record (ecma_number_t);
|
|
|
|
void dump ();
|
|
|
|
private:
|
|
virtual rcs_record_t *get_prev (rcs_record_t *);
|
|
virtual void set_prev (rcs_record_t *, rcs_record_t *);
|
|
virtual size_t get_record_size (rcs_record_t *);
|
|
}; /* lit_literal_storage_t */
|
|
|
|
#define LIT_STR_T (lit_literal_storage_t::LIT_STR)
|
|
#define LIT_MAGIC_STR_T (lit_literal_storage_t::LIT_MAGIC_STR)
|
|
#define LIT_MAGIC_STR_EX_T (lit_literal_storage_t::LIT_MAGIC_STR_EX)
|
|
#define LIT_NUMBER_T (lit_literal_storage_t::LIT_NUMBER)
|
|
|
|
#endif /* LIT_LITERAL_STORAGE_H */
|