packages feed

ptr-poker-0.1.1: cbits/text.c

/*
 * Copyright (c) 2020 Nikita Volkov <nikita.y.volkov@mail.ru>.
 *
 * Portions copyright (c) 2011 Bryan O'Sullivan <bos@serpentine.com>.
 *
 * Portions copyright (c) 2008-2010 Björn Höhrmann <bjoern@hoehrmann.de>.
 *
 * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
 */

#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>


uint8_t* encode_text
(
  uint8_t *dest,
  const uint16_t *src,
  size_t src_offset,
  size_t src_length
)
#if defined(__x86_64__)
{

  src += src_offset;
  
  const uint16_t* src_end = src + src_length;
  const uint16_t* full_word_src_end = src_end - 4;

  while (src < src_end) {
    uint16_t x = *src++;

    if (x <= 0x7F) {
      *dest++ = x;

      while (src < full_word_src_end) {
        uint64_t x = *((uint64_t *) src);

        if (x & 0xFF80FF80FF80FF80ULL) {
          if (!(x & 0x000000000000FF80ULL)) {
            *dest++ = x & 0xFFFF;
            src++;
            if (!(x & 0x00000000FF800000ULL)) {
              *dest++ = (x >> 16) & 0xFFFF;
              src++;
              if (!(x & 0x0000FF8000000000ULL)) {
                *dest++ = (x >> 32) & 0xFFFF;
                src++;
              }
            }
          }
          break;
        }
        
        *dest++ = x & 0xFFFF;
        *dest++ = (x >> 16) & 0xFFFF;
        *dest++ = (x >> 32) & 0xFFFF;
        *dest++ = x >> 48;
        src += 4;
      }
    }
    else if (x <= 0x7FF) {
      *dest++ = (x >> 6) | 0xC0;
      *dest++ = (x & 0x3f) | 0x80;
    }
    else if (x < 0xD800 || x > 0xDBFF) {
      *dest++ = (x >> 12) | 0xE0;
      *dest++ = ((x >> 6) & 0x3F) | 0x80;
      *dest++ = (x & 0x3F) | 0x80;
    } else {
      uint32_t c =
        ((((uint32_t) x) - 0xD800) << 10) + 
        (((uint32_t) *src++) - 0xDC00) + 0x10000;
      *dest++ = (c >> 18) | 0xF0;
      *dest++ = ((c >> 12) & 0x3F) | 0x80;
      *dest++ = ((c >> 6) & 0x3F) | 0x80;
      *dest++ = (c & 0x3F) | 0x80;
    }
  }

  return dest;
}
#elif defined(__i386__)
{

  src += src_offset;
  
  const uint16_t* src_end = src + src_length;
  const uint16_t* full_word_src_end = src_end - 2;

  while (src < src_end) {
    uint16_t x = *src++;

    if (x <= 0x7F) {
      *dest++ = x;

      while (src < full_word_src_end) {
        uint32_t x = *((uint32_t *) src);

        if (x & 0xFF80FF80)
          break;
        *dest++ = x & 0xFFFF;
        *dest++ = x >> 16;
        src += 2;
      }

    }
    else if (x <= 0x7FF) {
      *dest++ = (x >> 6) | 0xC0;
      *dest++ = (x & 0x3f) | 0x80;
    }
    else if (x < 0xD800 || x > 0xDBFF) {
      *dest++ = (x >> 12) | 0xE0;
      *dest++ = ((x >> 6) & 0x3F) | 0x80;
      *dest++ = (x & 0x3F) | 0x80;
    } else {
      uint32_t c =
        ((((uint32_t) x) - 0xD800) << 10) + 
        (((uint32_t) *src++) - 0xDC00) + 0x10000;
      *dest++ = (c >> 18) | 0xF0;
      *dest++ = ((c >> 12) & 0x3F) | 0x80;
      *dest++ = ((c >> 6) & 0x3F) | 0x80;
      *dest++ = (c & 0x3F) | 0x80;
    }
  }

  return dest;
}
#endif


int count_text_allocation_size
(
  const uint16_t *src_ptr,
  size_t src_off,
  size_t src_len
)
#if defined(__x86_64__)
{
  src_ptr += src_off;

  const uint16_t* after_src_ptr = src_ptr + src_len;
  const uint16_t* full_word_after_src_ptr = after_src_ptr - 4;

  size_t size = 0;

  while (src_ptr < after_src_ptr) {
    uint16_t w = *src_ptr++;

    if (w <= 0x7F) {
      size += 1;

      /* Try to go in batches of 4 bytes. */
      while (src_ptr < full_word_after_src_ptr) {
        uint64_t x = *((uint64_t*) src_ptr);

        if (x & 0xFF80FF80FF80FF80ULL) {
          if (!(x & 0x000000000000FF80ULL)) {
            size++;
            src_ptr++;
            if (!(x & 0x00000000FF800000ULL)) {
              size++;
              src_ptr++;
              if (!(x & 0x0000FF8000000000ULL)) {
                size++;
                src_ptr++;
              }
            }
          }
          break;
        }
        
        size += 4;
        src_ptr += 4;
      }

    }
    else if (w <= 0x7FF) {
      size += 2;
    }
    else if (w < 0xD800 || w > 0xDBFF) {
      size += 3;
    } else {
      src_ptr++;
      size += 4;
    }
  }

  return size;
}
#elif defined(__i386__)
{
  src_ptr += src_off;

  const uint16_t* after_src_ptr = src_ptr + src_len;
  const uint16_t* full_word_after_src_ptr = after_src_ptr - 2;

  size_t size = 0;

  while (src_ptr < after_src_ptr) {
    uint16_t w = *src_ptr++;

    if (w <= 0x7F) {
      size += 1;

      /* Try to go in batches of 2 bytes. */
      while (src_ptr < full_word_after_src_ptr) {
        uint32_t x = *((uint32_t *) src_ptr);

        if (x & 0xFF80FF80) break;
        
        size += 2;
        src_ptr += 2;
      }

    }
    else if (w <= 0x7FF) {
      size += 2;
    }
    else if (w < 0xD800 || w > 0xDBFF) {
      size += 3;
    } else {
      src_ptr++;
      size += 4;
    }
  }

  return size;
}
#endif