LINUX.ORG.RU

Релиз библиотеки libfatchars 0.4 и использующей её программы raskormiknigu 0.1

 ,


2

3

Состоялся релиз низкоуровневой библиотеки на языке Си для чтения и записи файлов/текстовых потоков в кодировке UTF-8 на уровне отдельных байт libfatchars 0.4 и использующей её программы-фильтра raskormiknigu 0.1.

Библиотека libfatchars предоставляет ряд следующих функций:

  • int sizeoffatc(int); — возвращает размер символа в байтах по первому байту; в случае ошибки (некорректные данные) возвращает -1
  • char rsizeoffatc(int); — возвращает размер симвода в байтах по коду символа;
  • char ismodifierfatc(int); — проверка на соответствие диапазонам модификаторов;
  • int fgetfatc(FILE *); — читает UTF-8 символ из файла/текстового потока; в случае EOF возвращает EOF, в случае ошибки в sizeoffatc возвращает -2;
  • int nextfatc(FILE *); — переход к следующему символу в файле/текстовом потоке;
  • int nextvisfatc(FILE *); — переход к следующему видимому символу в файле/текстовом потоке (проверяется соответствие диапазонам модификаторов);
  • int fputfatc(int, FILE *); - вывод UTF-8 символа в файл/текстовый поток; в случае EOF возвращает EOF, в случае некорректных данных возвращает -2.

Программа raskormiknigu является программой-фильтром, которая читает с stdin текст в кодировке KOI8-R, собственными силами перекодирует его в UTF-8 с автоматической расстановкой юникодных кавычек-ёлочек, дефисов, коротких и длинных тире, а затем выводит итоговый текст в UTF-8 на stdout через библиотеку libfatchars. Вложенные кавычки, конечно, не обрабатываются, однако для простого фильтра и этого функционала не так уж и мало. Программа адресована любителям писать книги и другие тексты в KOI8-R.

Простейшим примером использования библиотеки libfatchars является следующий фильтр, который просто читает с stdin и пишет в stdout без проверки переполнения последнего:

#include <fatchars/fatchars.h>

int main(){
        int c;
        while((c = fgetfatc(stdin)) != EOF) fputfatc(c, stdout);
        return 0;
}

Скачать библиотеку libfatchars

Скачать программу raskormiknigu

★★★★★

Проверено: Shaman007 ()
Последнее исправление: cetjs2 (всего исправлений: 4)
Ответ на: комментарий от TeopeTuK

и в ее вызовах уже баги со знаками преобразованных типов

Какие ещё баги? В чём они заключаются? Где их можно здесь найти?

int sizeoffatc(int headbyte)
{
    if (headbyte >= 0 && headbyte <= 0x7f)
        return 1;
    else if (headbyte >= 0xc0 && headbyte <= 0xdf)
        return 2;
    else if (headbyte >= 0xe0 && headbyte <= 0xef)
        return 3;
    else if (headbyte >= 0xf0 && headbyte <= 0xf7)
        return 4;
    else if (headbyte >= 0xf8 && headbyte <= 0xff)
        return -1;              // error
    return -1;                  // error
}
Специально перекомпилировал с -Wall, и компилятор этот кусок компилирует молча.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от q0tw4

Но, эта библиотека для работы с текстовыми файлами в UTF-8. В том и проблема, что заранее знать сколько байт в файле невозможно. Иначе бы и gets() всегда была бы одной из самых надёжных функций, и её бы не отправляли на пенсию как устаревшую.

Можно прочитать по байту, посчитать сколько их до EOF, выделить буфер нужного размера, и перечитать всё второй раз в этот буфер. Но, это медленнее чем прочитать один раз.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от q0tw4

Он невменяемый, с ним нет смысла вести продуктивную дискуссию.

TeopeTuK ★★★★★
()
Ответ на: комментарий от TeopeTuK

Ну, для ARM'ов, допустим, не совсем готово, но на x86_64 проблем там нет. char можно спокойно использовать как short short int.

Вот что смущает компилятор, так это использование переменной типа char как индекс массива (-Wchar-subscripts). Однако, практически всё работает.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от q0tw4

Со строками типа «char *»? Это, конечно, можно будет сделать.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от TeopeTuK

На x86_64 их нет. Это на ARM'ах char только беззнаковый.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Напоминаю, что в Unix'ах - всё файл. Включая stdin, stdout и stderr.

Анта бака? Вот сделал к примеру get запрос, это что теперь на жёсткий диск писать?

NextGenenration ★★
()
Ответ на: комментарий от saahriktu

Надо -W -Wall

fatchars.c: In function 'fgetfatc':
fatchars.c:67:2: warning: array subscript has type 'char' [-Wchar-subscripts]
  cdt[cdindx] = cdbuf;
  ^
fatchars.c:77:61: warning: suggest parentheses around '+' inside '<<' [-Wparentheses]
     return (cdt[0] & 0xf0) << 0x12 | (cdt[1] & 0x7f) << 0xc +
                                                             ^
fatchars.c:52:9: warning: unused variable 'rutfchar' [-Wunused-variable]
     int rutfchar = 0;
         ^
fatchars.c: In function 'fputfatc':
fatchars.c:109:23: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
  return fputc(fatcode & 0x7f | 0x00, fatstream);
                       ^
fatchars.c:112:30: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
  csts = fputc(fatcode >> 0x6 & 0x1f | 0xc0, fatstream);
                              ^
fatchars.c:115:23: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
  return fputc(fatcode & 0x3f | 0x80, fatstream);
                       ^
fatchars.c:118:30: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
  csts = fputc(fatcode >> 0xc & 0x0f | 0xe0, fatstream);
                              ^
fatchars.c:121:30: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
  csts = fputc(fatcode >> 0x6 & 0x3f | 0x80, fatstream);
                              ^
fatchars.c:124:23: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
  return fputc(fatcode & 0x3f | 0x80, fatstream);
                       ^
fatchars.c:127:31: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
  csts = fputc(fatcode >> 0x12 & 0x07 | 0xf0, fatstream);
                               ^
fatchars.c:130:30: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
  csts = fputc(fatcode >> 0xc & 0x3f | 0x80, fatstream);
                              ^
fatchars.c:133:28: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
  csts = fputc(fatcode >> 6 & 0x3f | 0x80, fatstream);
                            ^
fatchars.c:134:23: warning: suggest parentheses around arithmetic in operand of '|' [-Wparentheses]
  return fputc(fatcode & 0x3f | 0x80, fatstream);
                       ^
vodz ★★★★★
()
Ответ на: комментарий от NextGenenration

Вот сделал к примеру get запрос

Какой ещё «get запрос»? getc()? Но, вместо него можно вызвать fgetc().

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Ты предлагаешь ужаснейший велосипед. Есть задача - скачать, малость обработать, показать. Незачем порождать процессы и тому подобное.

NextGenenration ★★
()
Ответ на: комментарий от NextGenenration

Как это незачем? Как минимум один новый процесс всё равно будет создан, т.е. это уже начало цепочки порождения процессов. При этом каждый процесс будет выполнять только свою задачу и соединяться с другим процессом через pipe(). И это вполне Unixway'но.

Я понимаю, что сегодня многим незнакомым с Unixway'ем он кажется складом велосипедов, но, тем не менее, он им не является, и архитектурно красив. Но, чтобы увидеть в нём архитектурную красоту просто слышать о его существовании мало. Это часть определённой программистской культуры.

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 1)
Ответ на: комментарий от NextGenenration

Выкидывай пакетный менеджер - это одновременно и субд, архиватор и куча остального

Правильно, только LFS, только хардкор.

petrosyan ★★★★★
()
Ответ на: комментарий от NextGenenration

Во-первых, пакетные менеджеры являются прослойками над уже имеющимися реализациями архиваторов и СУБД. При этом они могут быть реализованы и без БД как таковой, просто скриптами на файлах. Во-вторых, у меня пакетного менеджера и нет. Я юзаю LFS. И, да, я его не вчера установил. А в 2007-м году. И регулярно обновляю. Руками.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

А в 2007-м году. И регулярно обновляю

ну всё с тобой понятно. ты уже забыл как выглядит удобство. Я тоже по привычке несколько раз консоль собирался открыть - не смотря на то что я уже поднял скрипт делающий это за меня.

пакетные менеджеры являются прослойками над уже имеющимися реализациями архиваторов и СУБД

Они просто дёргают нужные функции. это всё равно что взять char*. А не FILE*. Дополнительно вводить потоки, когда это уже есть в памяти мягко говоря странно.

NextGenenration ★★
()
Ответ на: комментарий от NextGenenration

Напоминаю, что в Unix'ах - всё файл. Включая stdin, stdout и stderr.

Анта бака? Вот сделал к примеру get запрос, это что теперь на жёсткий диск писать?

Файловую семантику Unix очевидно, следует представлять себе не иначе как API ядра Unix вокруг file descriptors и исходить сообразно в рассужденьях.

[d_a@home ~]$ exec 8<>/dev/tcp/example.org/80
[d_a@home ~]$ cat <<EOF >&8
> GET / HTTP/1.1
> Host: example.org
> 
> EOF
[d_a@home ~]$ cat <&8
HTTP/1.1 200 OK
Cache-Control: max-age=604800
Content-Type: text/html
Date: Wed, 15 Mar 2017 17:55:20 GMT
Etag: "359670651+ident"
Expires: Wed, 22 Mar 2017 17:55:20 GMT
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
Server: ECS (ewr/15BD)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1270

<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
.....
.....

d_a ★★★★★
()
Ответ на: комментарий от NextGenenration

Что именно натолкнуло тебя на такую мысль? Продемонстрированный мной пример файловой семантики в HTTP-чате, или это было что-то другое?

d_a ★★★★★
()
Ответ на: комментарий от NextGenenration

Программы можно склеивать шеллом без необходимости внедрять pipe().

Например, так: «wget -O- url | filter».

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от d_a

Может то что был приведен пример на баше? Как ни как но на том же питоне файл с кодом будет больше

NextGenenration ★★
()
Ответ на: комментарий от saahriktu

Ты предлагаешь пользователю самому писать эту строку или же вызывать скрипт, который будет вызвать маленькие unix-way программки?

NextGenenration ★★
()
Ответ на: комментарий от NextGenenration

А это уже кто как хочет. В любом случае нет необходимости делать одной программой на Си.

saahriktu ★★★★★
() автор топика

Вот это я понимаю - жирный троллинг.

zabbal ★★★★★
()
Ответ на: комментарий от saahriktu

Определение длины символа UTF-8 можно, ЕМНИП, свести к операции подсчёта верхних единиц (верхних нолей — CLZ).

Deleted
()
Ответ на: комментарий от NextGenenration

Вы неправильно читаете/ставите вопросы.

Первоначально Вы видели проблему в необходимости записи на диск чтобы конвертировать строку в файловый поток. Я показал, что нет необходимости записи на диск чтобы конвертировать строку в файловый поток. В том смысле, что есть и другие варианты конвертирования строки в файловый поток. Таким образом, первоначально поставленный вопрос не имеет оснований. И речь именно об этом.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

На тот мой вопрос вы ответили.

При чтении этой темы меня навели на размышления о том как можно создать свой гуи к дебагеру. Пошёл делать.

NextGenenration ★★
()
Ответ на: комментарий от saahriktu

Но почему бы не реализовать функции, работающие со строками, а функции для работы с потоками сделать convenience-функциями, основанными на первых?

Deleted
()
Ответ на: комментарий от Deleted

Потому, что в Unix'ах всё является файлом. Впрочем, если разделить 2 функции на 4, то через функции кодирования/декодирования можно добавить и функции работы со строками.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от stormblastt

Не всем нужен github, который также забракован проектом GNU. Тарболы наше всё.

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Да, эти предупреждения я уже видел и почистил.

Простите, но это по вашей ссылке не наблюдается.

Это не баги и на x86_64 всё работало и так.

Это кривость кода и x86_64 вообще тут ни к селу ни к городу. Нет никакого смысла юзать char в качестве индекса, оно же у вас даже не входной символ, а вообще счётчик. Счётчик должен быть размером с регистр и приводится к нему.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Так по ссылке старый релиз про который новость. Нового ещё не было.

Для хранения значений в диапазоне от 0 до 255 достаточно одного байта, т.е. char. Проблемы начинаются с отрицательных чисел и интерпретации char как unsigned char (что характерно для ARM'ов, но не для x86/x86_64). Впрочем, можно возращать ошибку и положительным числом.

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 2)
Ответ на: комментарий от saahriktu

Для хранения значений

Хранить подразумевает, что ресурс для хранения желательно экономить. Ваш алгоритм не хранит. Там компилятор всё равно заюзает регистр. И правильно возмущается, что в качества индекса выбран кривой тип.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Прямо таки всё исключительно на регистрах? Найдите 10 отличий:

int f(){
        return 7;
}

int main(){
        int a = f() - 1;
        int b = a + 1;
        return 0;
}
        .file   "testtr.c"
        .text
        .globl  f
        .type   f, @function
f:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $7, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   f, .-f
        .globl  main
        .type   main, @function
main:
.LFB1:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    $0, %eax
        call    f
        subl    $1, %eax
        movl    %eax, -4(%rbp)
        movl    -4(%rbp), %eax
        addl    $1, %eax
        movl    %eax, -8(%rbp)
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1:
        .size   main, .-main
        .ident  "GCC: (GNU) 6.3.0"
        .section        .note.GNU-stack,"",@progbits

saahriktu ★★★★★
() автор топика
Ответ на: комментарий от saahriktu

Если вы про код, генерируемый без использования регистров при отключенной оптимизации, то это сделано специально для отладочных целей - так удобнее отлаживать, когда построчно код предсказуем, а не свёрнут до move r, 7 без call.

vodz ★★★★★
()
Ответ на: комментарий от vodz

Мда. Такого я не ожидал.

Ну, собственно, я уже выпилил все char'ы.

saahriktu ★★★★★
() автор топика
Последнее исправление: saahriktu (всего исправлений: 1)
Ответ на: комментарий от saahriktu

Потому, что в Unix'ах всё является файлом.

Ок, ждём твоей православной версии string.h на файловых потоках.

Deleted
()
Ответ на: комментарий от Deleted

Вот так и изобретаются такие вещи как какой-нибудь strdrv. В смысле отдельной софтины, которая читает из stdin задание на обработку строк функциями из string.h и сами строки, обрабатывает, а затем выводит результат на stdout.

saahriktu ★★★★★
() автор топика

Чем это лучше iconv -f koi8-r -t utf8? При необходимости, в сочетании с мультилайновым регкспом типа s/"([^"]*)"/«\1»/g ?

Xenius ★★★★★
()
Ответ на: комментарий от Xenius

Тем, что это низкоуровневая реализация.

saahriktu ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.