ecma_save_literals_for_snapshot (ecma_collection_t *lit_pool_p, /**< list of known values */
                                 uint32_t *buffer_p, /**< [out] output snapshot buffer */
                                 size_t buffer_size, /**< size of the buffer */
                                 size_t *in_out_buffer_offset_p, /**< [in,out] write position in the buffer */
                                 lit_mem_to_snapshot_id_map_entry_t **out_map_p, /**< [out] map from literal identifiers
                                                                                  *   to the literal offsets
                                                                                  *   in snapshot */
                                 uint32_t *out_map_len_p) /**< [out] number of literals */
{
  if (lit_pool_p->item_count == 0)
  {
    *out_map_p = NULL;
    *out_map_len_p = 0;
  }

  uint32_t lit_table_size = 0;
  size_t max_lit_table_size = buffer_size - *in_out_buffer_offset_p;

  if (max_lit_table_size > (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT))
  {
    max_lit_table_size = (UINT32_MAX >> JERRY_SNAPSHOT_LITERAL_SHIFT);
  }

  ecma_value_t *lit_buffer_p = lit_pool_p->buffer_p;

  /* Compute the size of the literal pool. */
  for (uint32_t i = 0; i < lit_pool_p->item_count; i++)
  {
    if (ecma_is_value_float_number (lit_buffer_p[i]))
    {
      lit_table_size += (uint32_t) sizeof (ecma_number_t);
    }
#if JERRY_BUILTIN_BIGINT
    else if (ecma_is_value_bigint (lit_buffer_p[i]))
    {
      ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (lit_buffer_p[i]);

      lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint32_t) + ECMA_BIGINT_GET_SIZE (bigint_p),
                                                  JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
    }
#endif /* JERRY_BUILTIN_BIGINT */
    else
    {
      ecma_string_t *string_p = ecma_get_string_from_value (lit_buffer_p[i]);

      lit_table_size += (uint32_t) JERRY_ALIGNUP (sizeof (uint16_t) + ecma_string_get_size (string_p),
                                                  JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
    }

    /* Check whether enough space is available and the maximum size is not reached. */
    if (lit_table_size > max_lit_table_size)
    {
      ecma_collection_destroy (lit_pool_p);
      return false;
    }
  }

  lit_mem_to_snapshot_id_map_entry_t *map_p;
  uint32_t total_count = lit_pool_p->item_count;

  map_p = jmem_heap_alloc_block (total_count * sizeof (lit_mem_to_snapshot_id_map_entry_t));

  /* Set return values (no error is possible from here). */
  JERRY_ASSERT ((*in_out_buffer_offset_p % sizeof (uint32_t)) == 0);

  uint8_t *destination_p = (uint8_t *) (buffer_p + (*in_out_buffer_offset_p / sizeof (uint32_t)));
  uint32_t literal_offset = 0;

  *in_out_buffer_offset_p += lit_table_size;
  *out_map_p = map_p;
  *out_map_len_p = total_count;

  lit_buffer_p = lit_pool_p->buffer_p;

  /* Generate literal pool data. */
  for (uint32_t i = 0; i < lit_pool_p->item_count; i++)
  {
    map_p->literal_id = lit_buffer_p[i];
    map_p->literal_offset = (literal_offset << JERRY_SNAPSHOT_LITERAL_SHIFT) | ECMA_TYPE_SNAPSHOT_OFFSET;

    lit_utf8_size_t length;

    if (ecma_is_value_float_number (lit_buffer_p[i]))
    {
      map_p->literal_offset |= JERRY_SNAPSHOT_LITERAL_IS_NUMBER;

      ecma_number_t num = ecma_get_float_from_value (lit_buffer_p[i]);
      memcpy (destination_p, &num, sizeof (ecma_number_t));

      length = JERRY_ALIGNUP (sizeof (ecma_number_t), JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
    }
#if JERRY_BUILTIN_BIGINT
    else if (ecma_is_value_bigint (lit_buffer_p[i]))
    {
      map_p->literal_offset |= JERRY_SNAPSHOT_LITERAL_IS_BIGINT;

      ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (lit_buffer_p[i]);
      uint32_t size = ECMA_BIGINT_GET_SIZE (bigint_p);

      memcpy (destination_p, &bigint_p->u.bigint_sign_and_size, sizeof (uint32_t));
      memcpy (destination_p + sizeof (uint32_t), ECMA_BIGINT_GET_DIGITS (bigint_p, 0), size);

      length = JERRY_ALIGNUP (sizeof (uint32_t) + size, JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
    }
#endif /* JERRY_BUILTIN_BIGINT */
    else
    {
      ecma_string_t *string_p = ecma_get_string_from_value (lit_buffer_p[i]);
      length = ecma_string_get_size (string_p);

      *(uint16_t *) destination_p = (uint16_t) length;

      ecma_string_to_utf8_bytes (string_p, destination_p + sizeof (uint16_t), length);

      length = JERRY_ALIGNUP (sizeof (uint16_t) + length, JERRY_SNAPSHOT_LITERAL_ALIGNMENT);
    }

    JERRY_ASSERT ((length % sizeof (uint16_t)) == 0);
    destination_p += length;
    literal_offset += length;

    map_p++;
  }

  ecma_collection_destroy (lit_pool_p);
  return true;
} /* ecma_save_literals_for_snapshot */