Supporting string concatenations that are longer than 64k.
This commit is contained in:
@@ -28,6 +28,12 @@
|
|||||||
#include "jerry-libc.h"
|
#include "jerry-libc.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for length field of ecma_string_t indicating that
|
||||||
|
* length of string is unknown and should be calculated.
|
||||||
|
*/
|
||||||
|
#define ECMA_STRING_LENGTH_SHOULD_BE_CALCULATED ((ecma_length_t)-1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate new ecma-string and fill it with characters from specified buffer
|
* Allocate new ecma-string and fill it with characters from specified buffer
|
||||||
*
|
*
|
||||||
@@ -198,18 +204,27 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */
|
|||||||
JERRY_ASSERT (string1_p != NULL
|
JERRY_ASSERT (string1_p != NULL
|
||||||
&& string2_p != NULL);
|
&& string2_p != NULL);
|
||||||
|
|
||||||
uint32_t length = (uint32_t) string1_p->length + (uint32_t) string2_p->length;
|
int64_t length = (int64_t)ecma_string_get_length (string1_p) + (int64_t) ecma_string_get_length (string2_p);
|
||||||
if (length != (uint32_t) (string1_p->length + string2_p->length))
|
|
||||||
{
|
|
||||||
FIXME (/* Support length greater than 64K */);
|
|
||||||
JERRY_UNIMPLEMENTED();
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_string_t* string_desc_p = ecma_alloc_string ();
|
ecma_string_t* string_desc_p = ecma_alloc_string ();
|
||||||
string_desc_p->refs = 1;
|
string_desc_p->refs = 1;
|
||||||
string_desc_p->length = (ecma_length_t) length;
|
|
||||||
string_desc_p->container = ECMA_STRING_CONTAINER_CONCATENATION;
|
string_desc_p->container = ECMA_STRING_CONTAINER_CONCATENATION;
|
||||||
|
|
||||||
|
if ((int64_t) ((int32_t) length) != length)
|
||||||
|
{
|
||||||
|
/* concatenated strings with length more than 2^32 are not supported */
|
||||||
|
JERRY_UNREACHABLE ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int64_t) ((ecma_length_t) length) != length)
|
||||||
|
{
|
||||||
|
string_desc_p->length = ECMA_STRING_LENGTH_SHOULD_BE_CALCULATED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string_desc_p->length = (ecma_length_t) length;
|
||||||
|
}
|
||||||
|
|
||||||
ecma_ref_ecma_string (string1_p);
|
ecma_ref_ecma_string (string1_p);
|
||||||
ecma_ref_ecma_string (string2_p);
|
ecma_ref_ecma_string (string2_p);
|
||||||
|
|
||||||
@@ -332,7 +347,7 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */
|
|||||||
case ECMA_STRING_CONTAINER_HEAP_CHUNKS:
|
case ECMA_STRING_CONTAINER_HEAP_CHUNKS:
|
||||||
case ECMA_STRING_CONTAINER_CONCATENATION:
|
case ECMA_STRING_CONTAINER_CONCATENATION:
|
||||||
{
|
{
|
||||||
ecma_char_t zt_string_buffer [str_p->length + 1];
|
ecma_char_t zt_string_buffer [ecma_string_get_length (str_p) + 1];
|
||||||
|
|
||||||
ssize_t bytes_copied = ecma_string_to_zt_string (str_p,
|
ssize_t bytes_copied = ecma_string_to_zt_string (str_p,
|
||||||
zt_string_buffer,
|
zt_string_buffer,
|
||||||
@@ -346,15 +361,6 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */
|
|||||||
JERRY_UNREACHABLE ();
|
JERRY_UNREACHABLE ();
|
||||||
} /* ecma_string_to_number */
|
} /* ecma_string_to_number */
|
||||||
|
|
||||||
/**
|
|
||||||
* Get size of buffer required to store the ecma-string in zt-form.
|
|
||||||
*/
|
|
||||||
static ssize_t
|
|
||||||
ecma_string_get_required_buffer_size_for_zt_form (const ecma_string_t *string_desc_p) /**< ecma-string */
|
|
||||||
{
|
|
||||||
return (ssize_t) ((string_desc_p->length + 1u) * sizeof (ecma_char_t));
|
|
||||||
} /* ecma_string_get_required_buffer_size_for_zt_form */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy ecma-string's contents to a buffer.
|
* Copy ecma-string's contents to a buffer.
|
||||||
*
|
*
|
||||||
@@ -374,7 +380,7 @@ ecma_string_to_zt_string (const ecma_string_t *string_desc_p, /**< ecma-string d
|
|||||||
JERRY_ASSERT (buffer_p != NULL);
|
JERRY_ASSERT (buffer_p != NULL);
|
||||||
JERRY_ASSERT (buffer_size > 0);
|
JERRY_ASSERT (buffer_size > 0);
|
||||||
|
|
||||||
ssize_t required_buffer_size = ecma_string_get_required_buffer_size_for_zt_form (string_desc_p);
|
ssize_t required_buffer_size = ((ecma_string_get_length (string_desc_p) + 1) * ((ssize_t) sizeof (ecma_char_t)));
|
||||||
ssize_t bytes_copied = 0;
|
ssize_t bytes_copied = 0;
|
||||||
|
|
||||||
if (required_buffer_size > buffer_size)
|
if (required_buffer_size > buffer_size)
|
||||||
@@ -429,9 +435,9 @@ ecma_string_to_zt_string (const ecma_string_t *string_desc_p, /**< ecma-string d
|
|||||||
JERRY_ASSERT (str_p != NULL);
|
JERRY_ASSERT (str_p != NULL);
|
||||||
|
|
||||||
ecma_copy_zt_string_to_buffer (str_p, buffer_p, required_buffer_size);
|
ecma_copy_zt_string_to_buffer (str_p, buffer_p, required_buffer_size);
|
||||||
JERRY_ASSERT (__strlen ((char*)buffer_p) == string_desc_p->length);
|
JERRY_ASSERT (__strlen ((char*)buffer_p) == (size_t) ecma_string_get_length (string_desc_p));
|
||||||
|
|
||||||
bytes_copied = (ssize_t) ((string_desc_p->length + 1u) * sizeof (ecma_char_t));
|
bytes_copied = (ssize_t) ((ecma_string_get_length (string_desc_p) + 1) * ((ssize_t) sizeof (ecma_char_t)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
|
case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
|
||||||
@@ -447,7 +453,7 @@ ecma_string_to_zt_string (const ecma_string_t *string_desc_p, /**< ecma-string d
|
|||||||
|
|
||||||
ecma_length_t length = ecma_number_to_zt_string (*num_p, buffer_p, buffer_size);
|
ecma_length_t length = ecma_number_to_zt_string (*num_p, buffer_p, buffer_size);
|
||||||
|
|
||||||
JERRY_ASSERT (string_desc_p->length == length);
|
JERRY_ASSERT (ecma_string_get_length (string_desc_p) == length);
|
||||||
|
|
||||||
bytes_copied = (length + 1) * ((ssize_t) sizeof (ecma_char_t));
|
bytes_copied = (length + 1) * ((ssize_t) sizeof (ecma_char_t));
|
||||||
|
|
||||||
@@ -466,7 +472,7 @@ ecma_string_to_zt_string (const ecma_string_t *string_desc_p, /**< ecma-string d
|
|||||||
|
|
||||||
/* one character, which is the null character at end of string, will be overwritten */
|
/* one character, which is the null character at end of string, will be overwritten */
|
||||||
bytes_copied1 -= (ssize_t) sizeof (ecma_char_t);
|
bytes_copied1 -= (ssize_t) sizeof (ecma_char_t);
|
||||||
dest_p += string1_p->length;
|
dest_p += ecma_string_get_length (string1_p);
|
||||||
|
|
||||||
bytes_copied2 = ecma_string_to_zt_string (string2_p,
|
bytes_copied2 = ecma_string_to_zt_string (string2_p,
|
||||||
dest_p,
|
dest_p,
|
||||||
@@ -495,7 +501,7 @@ ecma_compare_strings_in_heap_chunks (const ecma_string_t *string1_p, /* ecma-str
|
|||||||
{
|
{
|
||||||
JERRY_ASSERT (string1_p->container == ECMA_STRING_CONTAINER_HEAP_CHUNKS
|
JERRY_ASSERT (string1_p->container == ECMA_STRING_CONTAINER_HEAP_CHUNKS
|
||||||
&& string2_p->container == ECMA_STRING_CONTAINER_HEAP_CHUNKS);
|
&& string2_p->container == ECMA_STRING_CONTAINER_HEAP_CHUNKS);
|
||||||
JERRY_ASSERT (string1_p->length == string2_p->length);
|
JERRY_ASSERT (ecma_string_get_length (string1_p) == ecma_string_get_length (string2_p));
|
||||||
|
|
||||||
ecma_collection_chunk_t *string1_chunk_p = ECMA_GET_POINTER (string1_p->u.chunk_cp);
|
ecma_collection_chunk_t *string1_chunk_p = ECMA_GET_POINTER (string1_p->u.chunk_cp);
|
||||||
ecma_collection_chunk_t *string2_chunk_p = ECMA_GET_POINTER (string2_p->u.chunk_cp);
|
ecma_collection_chunk_t *string2_chunk_p = ECMA_GET_POINTER (string2_p->u.chunk_cp);
|
||||||
@@ -527,7 +533,7 @@ ecma_compare_strings_in_heap_chunks (const ecma_string_t *string1_p, /* ecma-str
|
|||||||
} /* ecma_compare_strings_in_heap_chunks */
|
} /* ecma_compare_strings_in_heap_chunks */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare ecma-string to zt-string
|
* Compare zt-string to ecma-string stored in heap chunks
|
||||||
*
|
*
|
||||||
* @return true - if strings are equal;
|
* @return true - if strings are equal;
|
||||||
* false - otherwise.
|
* false - otherwise.
|
||||||
@@ -700,7 +706,7 @@ ecma_compare_ecma_string_to_ecma_string (const ecma_string_t *string1_p, /* ecma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely (string1_p->length != string2_p->length))
|
if (likely (ecma_string_get_length (string1_p) != ecma_string_get_length (string2_p)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -730,9 +736,11 @@ ecma_compare_ecma_string_to_ecma_string (const ecma_string_t *string1_p, /* ecma
|
|||||||
}
|
}
|
||||||
case ECMA_STRING_CONTAINER_CHARS_IN_DESC:
|
case ECMA_STRING_CONTAINER_CHARS_IN_DESC:
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (string1_p->length == string2_p->length);
|
JERRY_ASSERT (ecma_string_get_length (string1_p) == ecma_string_get_length (string2_p));
|
||||||
|
|
||||||
return (__memcmp (string1_p->u.chars, string2_p->u.chars, string1_p->length * sizeof (ecma_char_t)) == 0);
|
return (__memcmp (string1_p->u.chars,
|
||||||
|
string2_p->u.chars,
|
||||||
|
(size_t) (ecma_string_get_length (string1_p) * ((ssize_t) sizeof (ecma_char_t)))) == 0);
|
||||||
}
|
}
|
||||||
case ECMA_STRING_CONTAINER_HEAP_CHUNKS:
|
case ECMA_STRING_CONTAINER_HEAP_CHUNKS:
|
||||||
{
|
{
|
||||||
@@ -758,6 +766,33 @@ ecma_compare_ecma_string_to_ecma_string (const ecma_string_t *string1_p, /* ecma
|
|||||||
return ecma_compare_ecma_string_to_ecma_string_longpath (string1_p, string2_p);
|
return ecma_compare_ecma_string_to_ecma_string_longpath (string1_p, string2_p);
|
||||||
} /* ecma_compare_ecma_string_to_ecma_string */
|
} /* ecma_compare_ecma_string_to_ecma_string */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get length of ecma-string
|
||||||
|
*
|
||||||
|
* @return number of characters in the string
|
||||||
|
*/
|
||||||
|
int32_t
|
||||||
|
ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */
|
||||||
|
{
|
||||||
|
if (string_p->container != ECMA_STRING_CONTAINER_CONCATENATION)
|
||||||
|
{
|
||||||
|
return string_p->length;
|
||||||
|
}
|
||||||
|
else if (string_p->length != ECMA_STRING_LENGTH_SHOULD_BE_CALCULATED)
|
||||||
|
{
|
||||||
|
return string_p->length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ecma_string_t *string1_p, *string2_p;
|
||||||
|
|
||||||
|
string1_p = ECMA_GET_POINTER (string_p->u.concatenation.string1_cp);
|
||||||
|
string2_p = ECMA_GET_POINTER (string_p->u.concatenation.string2_cp);
|
||||||
|
|
||||||
|
return ecma_string_get_length (string1_p) + ecma_string_get_length (string2_p);
|
||||||
|
}
|
||||||
|
} /* ecma_string_get_length */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare zero-terminated string to zero-terminated string
|
* Compare zero-terminated string to zero-terminated string
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ extern ssize_t ecma_string_to_zt_string (const ecma_string_t *string_desc_p,
|
|||||||
ssize_t buffer_size);
|
ssize_t buffer_size);
|
||||||
extern bool ecma_compare_ecma_string_to_ecma_string (const ecma_string_t *string1_p,
|
extern bool ecma_compare_ecma_string_to_ecma_string (const ecma_string_t *string1_p,
|
||||||
const ecma_string_t *string2_p);
|
const ecma_string_t *string2_p);
|
||||||
|
extern int32_t ecma_string_get_length (const ecma_string_t *string_p);
|
||||||
extern bool ecma_compare_zt_string_to_zt_string (const ecma_char_t *string1_p, const ecma_char_t *string2_p);
|
extern bool ecma_compare_zt_string_to_zt_string (const ecma_char_t *string1_p, const ecma_char_t *string2_p);
|
||||||
extern ssize_t ecma_copy_zt_string_to_buffer (const ecma_char_t *string_p, ecma_char_t *buffer_p, ssize_t buffer_size);
|
extern ssize_t ecma_copy_zt_string_to_buffer (const ecma_char_t *string_p, ecma_char_t *buffer_p, ssize_t buffer_size);
|
||||||
extern ecma_length_t ecma_zt_string_length (const ecma_char_t *string_p);
|
extern ecma_length_t ecma_zt_string_length (const ecma_char_t *string_p);
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ ecma_op_to_boolean (ecma_value_t value) /**< ecma-value */
|
|||||||
{
|
{
|
||||||
ecma_string_t *str_p = ECMA_GET_POINTER(value.value);
|
ecma_string_t *str_p = ECMA_GET_POINTER(value.value);
|
||||||
|
|
||||||
return ecma_make_simple_completion_value ((str_p->length == 0) ? ECMA_SIMPLE_VALUE_FALSE
|
return ecma_make_simple_completion_value ((ecma_string_get_length (str_p) == 0) ? ECMA_SIMPLE_VALUE_FALSE
|
||||||
: ECMA_SIMPLE_VALUE_TRUE);
|
: ECMA_SIMPLE_VALUE_TRUE);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user