Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / C++ Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4   вперед  Ctrl      все
 Вычисление длины utf-8 строки в compile time  [new]
petrav
Member

Откуда:
Сообщений: 2430
Как думаете нормально? Работать будет? :)

inline constexpr
size_t c_strlen(char const *start, size_t const maxBuffSize)
{
    char const *end = start;
    while (*end != '\0')
    {
        ++end;

        if (end - start >= maxBuffSize)
        {
            throw std::runtime_error("The string is too long.");
        }
    }

    size_t charCount = 0;
    while (start < end)
    {
        byte const ch = static_cast<byte>(*start);
        size_t chSize = {};

        if      ((ch & 0x80) == 0x00)   chSize = 1;
        else if ((ch & 0xE0) == 0xC0)   chSize = 2;
        else if ((ch & 0xF0) == 0xE0)   chSize = 3;
        else if ((ch & 0xF8) == 0xF0)   chSize = 4;
        else throw std::runtime_error("Invalid UTF-8 char.");

        if (chSize > end - start)
        {
            throw std::runtime_error("UTF-8 string too short.");
        }

        for (size_t i = 1; i < chSize; ++i)
        {
            if ((start[i] & 0xC0) != 0x80)
            {
                throw std::runtime_error("Expected continuation UTF-8 byte.");
            }
        }

        ++charCount;
        start += chSize;
    }

    return charCount;
}
20 июл 20, 20:20    [22170676]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 3384
petrav, так ты скомпилируй и посмотри! :)
21 июл 20, 10:45    [22170870]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 3384
petrav, к чему вообще весь этот зоопарк, если тебе, всего лишь, надо узнать кол-во байт литерала?
#include <cstdlib>
#include <stdio.h>

using namespace std;

static constexpr char test[] = u8"Тестовое сообщение";

int main(int argc, char** argv)
{
  printf("\r\n%zu\r\n", sizeof(test));
  return 0;
}
Результат, как и ожидалось, "36".
21 июл 20, 11:28    [22170893]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
petrav
Member

Откуда:
Сообщений: 2430
rdb_dev
petrav, к чему вообще весь этот зоопарк, если тебе, всего лишь, надо узнать кол-во байт литерала?

Не количество байт, а количество символов. И не обязательно у литерала. Compile time только по возможности.

Я, конечно, тестировал на русских буквах и иероглифах. Но я ведь программировал по мотивам кода со стек-оферфлоу. И там было приписано, что реализация наивная. Поэтому и спрашиваю, может можно улучшить.
21 июл 20, 12:07    [22170917]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
AmKad
Member

Откуда:
Сообщений: 5184
Я когда-то взял не глядя функцию UTF2Unicode с хабра https://habr.com/ru/post/282191/
Правда параметр заменил на
const /*unsigned*/ char* txt

Для подсчета символов тоже подойдет. На иероглифах не пробовал.
21 июл 20, 12:56    [22170943]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5361
AmKad,
А какой смысл в символах считать? Это не универсально.
Может на знаки? Диакритические знаки? Кодовые точки, составные символы?
21 июл 20, 13:16    [22170970]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 3384
petrav,
+ Вот как-то так...
#include <cstdlib>
#include <stdio.h>

using namespace std;


static constexpr char test[] = u8"Тестовое сообщение";

class utf8literal
{
  template <typename T>
  static constexpr
  size_t bytes_per_u8char(T chr, bool start = true)
  {
    return (start && !(chr & 0x80))
        ? 1
        : (chr & 0x80)
            ? 1 + bytes_per_u8char(chr << 1, false)
            : 0;
  }

  template <typename T, size_t D>
  static constexpr
  size_t calc_length(T (&a)[D], size_t i = 0)
  {
    return (i < D)
        ? 1 + calc_length(a, i + bytes_per_u8char(a[i]))
        : 0;
  }

public:

  template <typename T, size_t D>
  static constexpr
  size_t length(T (&a)[D])
  {
    return calc_length<T, D>(a) - 1;
  }
};

int main(int argc, char** argv)
{
  printf("\r\n%zu\r\n", utf8literal::length(test));
  return 0;
}
Только не забудь впихнуть static_assert для (T != char).
21 июл 20, 13:18    [22170977]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
AmKad
Member

Откуда:
Сообщений: 5184
PetroNotC Sharp
А какой смысл в символах считать? Это не универсально.
Может на знаки? Диакритические знаки? Кодовые точки, составные символы?
Лично мне эта функция нужна для целей, описанных в статье - для рендеринга. И длину я считаю не в символах, в пикселях. Но алгоритм можно заюзать и для подсчета символов, например, для выравнивания вывода моноширинного шрифта в консоли.
21 июл 20, 13:25    [22170986]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
petrav
Member

Откуда:
Сообщений: 2430
rdb_dev
petrav,
+ Вот как-то так...
#include <cstdlib>
#include <stdio.h>

using namespace std;


static constexpr char test[] = u8"Тестовое сообщение";

class utf8literal
{
  template <typename T>
  static constexpr
  size_t bytes_per_u8char(T chr, bool start = true)
  {
    return (start && !(chr & 0x80))
        ? 1
        : (chr & 0x80)
            ? 1 + bytes_per_u8char(chr << 1, false)
            : 0;
  }

  template <typename T, size_t D>
  static constexpr
  size_t calc_length(T (&a)[D], size_t i = 0)
  {
    return (i < D)
        ? 1 + calc_length(a, i + bytes_per_u8char(a[i]))
        : 0;
  }

public:

  template <typename T, size_t D>
  static constexpr
  size_t length(T (&a)[D])
  {
    return calc_length<T, D>(a) - 1;
  }
};

int main(int argc, char** argv)
{
  printf("\r\n%zu\r\n", utf8literal::length(test));
  return 0;
}
Только не забудь впихнуть static_assert для (T != char).

Как-то у вас всё переусложнено, ИМХО. Я так понимаю тут подсчитываются лидирующие символы, а не лидирующие пропускаются.
21 июл 20, 13:27    [22170988]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 3384
petrav
Как-то у вас всё переусложнено, ИМХО.
Наоборот - всё до безобразия упрощено.

petrav
Я так понимаю тут подсчитываются лидирующие символы, а не лидирующие пропускаются.
Пропуск кол-ва байт символа определяется по старшим битам лидирующего байта символа, а в подсчёт попадают именно символы. Попробуй впихнуть в литерал между русскими символами те, что кодируются четырьмя байтами и почувствуй разницу. Ведь ты же хотел именно подсчёт символов, а не байт?
21 июл 20, 13:39    [22171008]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5361
AmKad,
В пикселях же в winApi есть?
Типа getTextPoint.....
И там учитывается шрифт, выравнивание и куча всего.
21 июл 20, 13:42    [22171010]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
AmKad
Member

Откуда:
Сообщений: 5184
PetroNotC Sharp
В пикселях же в winApi есть?
Может быть и есть, но winApi нет на ведроиде и яблоке.
21 июл 20, 13:46    [22171019]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
petrav
Member

Откуда:
Сообщений: 2430
rdb_dev
petrav
Как-то у вас всё переусложнено, ИМХО.
Наоборот - всё до безобразия упрощено.

petrav
Я так понимаю тут подсчитываются лидирующие символы, а не лидирующие пропускаются.
Пропуск кол-ва байт символа определяется по старшим битам лидирующего байта символа, а в подсчёт попадают именно символы. Попробуй впихнуть в литерал между русскими символами те, что кодируются четырьмя байтами и почувствуй разницу. Ведь ты же хотел именно подсчёт символов, а не байт?

Да символов. Попробовал, с моим кодом тоже всё работает.
21 июл 20, 13:51    [22171024]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 3384
petrav, enjoy! :)
21 июл 20, 14:03    [22171046]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
petrav
Member

Откуда:
Сообщений: 2430
rdb_dev
petrav, enjoy! :)

Правда у меня смесь русских букв и иероглифов (иероглифы в три байта).
21 июл 20, 14:05    [22171051]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 3384
petrav
Правда у меня смесь русских букв и иероглифов (иероглифы в три байта).
Для теста самое то!
21 июл 20, 14:05    [22171053]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5361
AmKad
PetroNotC Sharp
В пикселях же в winApi есть?
Может быть и есть, но winApi нет на ведроиде и яблоке.

Блин, опять универсальность везде).
Тогда конечно.
А так там свои API есть
Типа:
getTextBounds
Added in API level 1
public void getTextBounds (String text,
int start,
int end,
Rect bounds)
21 июл 20, 14:29    [22171074]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
AmKad
Member

Откуда:
Сообщений: 5184
PetroNotC Sharp,

Я стараюсь все, что можно сделать на перенесимом C++, делать на нем. Посчитать размер выводимой через openglES строки текста - задача не сложная. Завязываться на специфичное Java-API ради этого не хочется.
21 июл 20, 15:21    [22171104]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50765

Осталась сущая мелочь: найти в С++ переносимые шрифты.

Posted via ActualForum NNTP Server 1.5

21 июл 20, 15:23    [22171106]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5361
AmKad,

У OpenGL разве не в Canvas. У которого есть Pаint. С длиной текста методом?
21 июл 20, 15:30    [22171115]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
AmKad
Member

Откуда:
Сообщений: 5184
Dimitry Sibiryakov

Осталась сущая мелочь: найти в С++ переносимые шрифты.
Статья как раз о том, как сделать такой "шрифт" на основе SDF.
21 июл 20, 15:30    [22171117]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5361
AmKad
Dimitry Sibiryakov

Осталась сущая мелочь: найти в С++ переносимые шрифты.
Статья как раз о том, как сделать такой "шрифт" на основе SDF.
и отрисовать попиксельно сглаживая) :))
Круто.
21 июл 20, 15:34    [22171121]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 5361
Глянул статью - опять игрушки.
Понятно.
21 июл 20, 15:35    [22171123]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
AmKad
Member

Откуда:
Сообщений: 5184
PetroNotC Sharp
AmKad,

У OpenGL разве не в Canvas. У которого есть Pаint. С длиной текста методом?
Не знаю что такое canvas и paint. У openGL(ES) нет функций для вывода текста. Только многоугольники. В случае ES - треугольники. Вообще, если интересно покопаться в моем говнокоде и закидать меня помидорами, могу дать ссылку на репозиторий.
21 июл 20, 15:36    [22171125]     Ответить | Цитировать Сообщить модератору
 Re: Вычисление длины utf-8 строки в compile time  [new]
AmKad
Member

Откуда:
Сообщений: 5184
PetroNotC Sharp
Глянул статью - опять игрушки.
Понятно.
Да. Увы, на что-то серьезное я не способен
21 июл 20, 15:36    [22171126]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4   вперед  Ctrl      все
Все форумы / C++ Ответить