ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */
                             const lit_utf8_byte_t *cesu8_string2_p, /**< characters to be appended */
                             lit_utf8_size_t cesu8_string2_size, /**< byte size of cesu8_string2_p */
                             lit_utf8_size_t cesu8_string2_length) /**< character length of cesu8_string2_p */
{
  JERRY_ASSERT (string1_p != NULL && cesu8_string2_size > 0 && cesu8_string2_length > 0);

  if (JERRY_UNLIKELY (ecma_string_is_empty (string1_p)))
  {
    return ecma_new_ecma_string_from_utf8 (cesu8_string2_p, cesu8_string2_size);
  }

  lit_utf8_size_t cesu8_string1_size;
  lit_utf8_size_t cesu8_string1_length;
  uint8_t flags = ECMA_STRING_FLAG_IS_ASCII;
  lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];

  const lit_utf8_byte_t *cesu8_string1_p = ecma_string_get_chars (string1_p,
                                                                  &cesu8_string1_size,
                                                                  &cesu8_string1_length,
                                                                  uint32_to_string_buffer,
                                                                  &flags);

  JERRY_ASSERT (!(flags & ECMA_STRING_FLAG_MUST_BE_FREED));
  JERRY_ASSERT (cesu8_string1_length > 0);
  JERRY_ASSERT (cesu8_string1_length <= cesu8_string1_size);

  lit_utf8_size_t new_size = cesu8_string1_size + cesu8_string2_size;

  /* Poor man's carry flag check: it is impossible to allocate this large string. */
  if (new_size < (cesu8_string1_size | cesu8_string2_size))
  {
    jerry_fatal (ERR_OUT_OF_MEMORY);
  }

  lit_magic_string_id_t magic_string_id;
  magic_string_id = lit_is_utf8_string_pair_magic (cesu8_string1_p,
                                                   cesu8_string1_size,
                                                   cesu8_string2_p,
                                                   cesu8_string2_size);

  if (magic_string_id != LIT_MAGIC_STRING__COUNT)
  {
    ecma_deref_ecma_string (string1_p);
    return ecma_get_magic_string (magic_string_id);
  }

  if ((flags & ECMA_STRING_FLAG_IS_UINT32) && new_size <= ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32)
  {
    memcpy (uint32_to_string_buffer + cesu8_string1_size, cesu8_string2_p, cesu8_string2_size);

    uint32_t array_index;

    if (ecma_string_to_array_index (uint32_to_string_buffer, new_size, &array_index))
    {
      ecma_deref_ecma_string (string1_p);
      return ecma_new_ecma_string_from_uint32 (array_index);
    }
  }

  if (lit_get_magic_string_ex_count () > 0)
  {
    lit_magic_string_ex_id_t magic_string_ex_id;
    magic_string_ex_id = lit_is_ex_utf8_string_pair_magic (cesu8_string1_p,
                                                           cesu8_string1_size,
                                                           cesu8_string2_p,
                                                           cesu8_string2_size);

    if (magic_string_ex_id < lit_get_magic_string_ex_count ())
    {
      ecma_deref_ecma_string (string1_p);
      return ecma_new_ecma_string_from_magic_string_ex_id (magic_string_ex_id);
    }
  }

  lit_utf8_byte_t *data_p;
  ecma_string_t *string_desc_p = ecma_new_ecma_string_from_utf8_buffer (cesu8_string1_length + cesu8_string2_length,
                                                                        new_size,
                                                                        &data_p);

  lit_string_hash_t hash_start;

  if (JERRY_UNLIKELY (flags & ECMA_STRING_FLAG_REHASH_NEEDED))
  {
    hash_start = lit_utf8_string_calc_hash (cesu8_string1_p, cesu8_string1_size);
  }
  else
  {
    JERRY_ASSERT (!ECMA_IS_DIRECT_STRING (string1_p));
    hash_start = string1_p->u.hash;
  }

  string_desc_p->u.hash = lit_utf8_string_hash_combine (hash_start, cesu8_string2_p, cesu8_string2_size);

  memcpy (data_p, cesu8_string1_p, cesu8_string1_size);
  memcpy (data_p + cesu8_string1_size, cesu8_string2_p, cesu8_string2_size);

  ecma_deref_ecma_string (string1_p);
  return (ecma_string_t *) string_desc_p;
} /* ecma_append_chars_to_string */