jerryscript/jerry-core/lit/lit-literal-storage.h
Andrey Shitov fd9ff8e3bd Add core unicode functionality.
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
2015-06-29 23:27:58 +03:00

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 */