Всеми привет!
Я пишу конвертер из древнего формата Лексера и нашел библиотеку, которая дружит с ним. Она возвращает несколько событий на каждый знак в файле .lex. Вот одно из событий это символ, в оригинале он хранится в кодировке CP866, написал маленькую функцию, которая конвертирует текущий символ в ютф, но половину символов iconv просто игнорирует и не может прочитать :(
Код представляет собой франкинштейна, поэтому не ругайте за это пожалуйста
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "liblex.h"
#include <iconv.h>
#include <errno.h>
#include <err.h>
#define ROW_SIZE 512
void parse_callback( struct parser_event *pe, void *userdata )
{
iconv_t foo = iconv_open("CP866", "UTF-8");
if((int) foo == -1) {
if (errno == EINVAL) {
fprintf(stderr,
"Conversion is not supported");
} else {
fprintf(stderr, "Initialization failure:\n");
}
}
// calloc fills memory with 0 bytes. we alloc two -
// one for the 'ö' and one for the ending delimeter
char *iso = calloc(2, sizeof(char));
// the converted string can be four times larger
// then the original, as the largest known char width is 4 bytes.
char *converted = calloc(5, sizeof(char));
// we need to store an additional pointer that targets the
// start of converted. (iconv modifies the original 'converted')
char *converted_start = converted;
size_t ibl = 2; // len of iso
size_t obl = 5; // len of converted
// do it!
switch ( pe->event ) {
case EVENT_RUNE:
iso[0] = pe->rune;
int ret = iconv(foo, &iso, &ibl, &converted, &obl);
// if iconv fails it returns -1
if(ret == (iconv_t)-1) {
perror("iconv");
iconv_close(foo);
} else {
// other wise the number of converted bytes
printf("%i bytes converted\n", ret);
printf("result: '%s'\n", converted_start);
iconv_close(foo);
}
fprintf( stdout, "debug: event = RUNE, data = %c\n", iso);
break;
case EVENT_FONT:
fprintf( stderr, "FUCK FONT\n");
fprintf( stdout, "debug: event = FONT, data = %d\n", pe->font_id );
break;
case EVENT_ERROR:
fprintf( stderr, "FUCK ERROR\n");
fprintf( stdout, "debug: event = ERROR\n" );
break;
default:
fprintf( stdout, "debug: event = UNKNOWN\n" );
}
}
int main()
{
int err = 0;
struct parser *p;
struct parser_event pe;
int fd;
uint8_t row[ROW_SIZE];
ssize_t size;
fprintf( stderr, "FUCK IM STARTED BITCH\n");
/* Create new parser */
err = parser_create( &p );
if ( err ) {
fprintf( stderr, "error: Unable to create parser\n" );
goto out;
}
fprintf( stderr, "FUCK PARSER\n");
fd = open("example.lex", O_RDONLY);
if ( fd == -1 ) {
fprintf( stderr, "error: Unable to open stream\n" );
goto out;
}
fprintf( stderr, "FUCK FILES\n");
err = parser_set_callback( p, parse_callback, NULL );
if ( err ) {
fprintf( stderr, "error: Unable to setup callback\n" );
goto out;
}
fprintf( stderr, "FUCK IT CALLBACK\n");
for ( ;5; ) {
/* Read */
size = read( fd, row, ROW_SIZE );
if ( size == 0 ) {
goto out;
}
if ( size == -1 ) { /* Some error when reading */
fprintf( stderr, "error: Unable to read bytes\n" );
goto out;
}
/* Parse */
err = parser_parse( p, row, size );
if ( err ) {
fprintf(stderr, "error: Unable to parsing row\n");
goto out;
}
}
out:
/* Close stream */
if ( fd != -1 ) {
close( fd );
}
/* Dispose reader */
parser_dispose( p );
return err;
}