Repository: jerryscript-project/jerryscript
File: jerry-core/lit/lit-strings.c (C)

Code before:
 * Validate utf-8 string
 *
 * NOTE:
 *   Isolated surrogates are allowed.
 *
 * @return true if utf-8 string is well-formed
 *         false otherwise
 */
bool
lit_is_valid_utf8_string (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 string */
                          lit_utf8_size_t buf_size, /**< string size */
                          bool is_strict) /**< true if surrogate pairs are not allowed */
{
  if (!utf8_buf_p)
  {
    return false;
  }

  if (buf_size == 0)
  {
    return true;
  }

  lit_utf8_size_t extra_bytes_count;

  for (const unsigned char *idx = (const unsigned char *) utf8_buf_p; (unsigned int) (idx - utf8_buf_p) < buf_size;
       idx += extra_bytes_count)
  {
    if (idx[0] <= 0x7F)
    {
      extra_bytes_count = 1;
      continue;
    }
    else if (((0xC2 <= idx[0] && idx[0] <= 0xDF) && (0x80 <= idx[1] && idx[1] <= 0xBF)))
    {
      extra_bytes_count = 2;
      continue;
    }
    else if ((idx[0] == 0xE0 && (0xA0 <= idx[1] && idx[1] <= 0xBF) && (0x80 <= idx[2] && idx[2] <= 0xBF))
              || (((0xE1 <= idx[0] && idx[0] <= 0xEC) || idx[0] == 0xEE || idx[0] == 0xEF)
              && (0x80 <= idx[1] && idx[1] <= 0xBF) && (0x80 <= idx[2] && idx[2] <= 0xBF))
              || (idx[0] == 0xED && (0x80 <= idx[1] && idx[1] <= 0x9F) && (0x80 <= idx[2] && idx[2] <= 0xBF))
              || (idx[0] == 0xED && is_strict && (((0xA0 <= idx[1] && idx[1] <= 0xAF)
              && (0x80 <= idx[2] && idx[2] <= 0xBF)) || ((0xB0 <= idx[1] && idx[1] <= 0xBF)
              && (0x80 <= idx[2] && idx[2] <= 0xBF)))))
    {
      extra_bytes_count = 3;
      continue;
    }
    else if ((idx[0] == 0xF0 && (0x90 <= idx[1] && idx[1] <= 0xBF) && (0x80 <= idx[2] && idx[2] <= 0xBF)
              && (0x80 <= idx[3] && idx[3] <= 0xBF)) || ((0xF1 <= idx[0] && idx[0] <= 0xF3)

Review comment (suggestion):
It is good to compute the `end` at the beginning and use a single variable. Furthermore the for loop makes the `buf_size == 0` check unnecessary. The 3 parts should go into one line or three lines. 

Code after:
#define LIT_UTF8_HIGH_SURROGATE_MIN 0xa0 /**< utf8 high surrogate minimum */
#define LIT_UTF8_HIGH_SURROGATE_MAX 0xaf /**< utf8 high surrogate maximum */
#define LIT_UTF8_LOW_SURROGATE_MIN 0xb0 /**< utf8 low surrogate minimum */
#define LIT_UTF8_LOW_SURROGATE_MAX 0xbf /**< utf8 low surrogate maximum */
#define LIT_UTF8_1_BYTE_MAX 0xf4 /**< utf8 one byte max */
#define LIT_UTF8_2_BYTE_MAX 0x8f /**< utf8 two byte max */
#define LIT_UTF8_VALID_TWO_BYTE_START 0xc2 /**< utf8 two byte start */

/**
 * Validate utf-8 string
 *
 * NOTE:
 *   Isolated surrogates are allowed.
 *
 * @return true if utf-8 string is well-formed
 *         false otherwise
 */
bool
lit_is_valid_utf8_string (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 string */
                          lit_utf8_size_t buf_size, /**< string size */
                          bool is_strict) /**< true if surrogate pairs are not allowed */
{
  const unsigned char *end = buf_size + utf8_buf_p;

  const unsigned char *idx = (const unsigned char *) utf8_buf_p;

  while (idx < end)
  {
    const uint8_t first_byte = *idx++;

    if (first_byte < LIT_UTF8_EXTRA_BYTE_MARKER)
    {
      continue;
    }

    if (first_byte < LIT_UTF8_VALID_TWO_BYTE_START || idx >= end)
    {
      return false;
    }

    const uint8_t second_byte = *idx++;

    if ((second_byte & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER)
    {
      return false;
    }

    if (first_byte < LIT_UTF8_3_BYTE_MARKER)
    {
      continue;
    }