Представьте себе, что у вас есть такие: СтруктурыКастинг указатель на структуру, чтобы указатель на структуру с сопзЬ членом
struct nix_codec {
nix_uint8 state;
nix_uint8 mode;
nix_uint8 flags;
nix_size offset;
nix_uint32 codepage;
nix_utf8 const *const *aliases;
void (*delete)(
struct nix_codec *codec,
struct nix_error *error
);
struct nix_codec* (*clone)(
struct nix_codec const *codec,
nix_int8 mode,
struct nix_error *error
);
nix_size (*decode)(
struct nix_codec *codec,
nix_byte const *bdata,
nix_size bsize,
nix_rune *udata,
nix_size usize,
struct nix_error *error
);
nix_size (*encode)(
struct nix_codec *codec,
nix_rune const *udata,
nix_size usize,
nix_byte *bdata,
nix_size bsize,
struct nix_error *error
);
};
typedef struct {
nix_uint8 const state;
nix_uint8 const mode;
nix_uint8 const flags;
nix_size const offset;
nix_uint32 const codepage;
nix_utf8 const *const *const aliases;
} nix_codec;
Один имеет также несколько функций, которые используются для создания nix_codec*
экземпляров, например, для UTF-8 кодека будет выглядеть следующим образом:
static nix_size self_decode
(
struct nix_codec *codec,
nix_byte const *bdata,
nix_size bsize,
nix_rune *udata,
nix_size usize,
struct nix_error *error
)
{ /* UTF-8 decode function, too long to post here */}
static nix_utf8 const *const aliases[] = {
"UTF-8",
"UTF8",
"CP65001",
NULL,
};
nix_codec *nix_codec_utf8
(
nix_int8 mode,
struct nix_error *error
)
{
struct nix_codec *codec = NULL;
if ((mode != NIX_CODEC_STRICT) && (mode != NIX_CODEC_ESCAPE)
&& (mode != NIX_CODEC_REPLACE) && (mode != NIX_CODEC_IGNORE)) {
return NULL;
}
codec = calloc(1, sizeof(struct nix_codec));
if (codec == NULL) {
return NULL;
}
codec->mode = mode;
codec->codepage = 65001;
codec->aliases = aliases;
codec->decode = &self_decode;
codec->encode = &self_encode;
codec->flags = (NIX_CODEC_COMPATIBLE | NIX_CODEC_MULTIBYTE | NIX_CODEC_ABSOLUTE);
return (nix_codec*)codec;
}
Функция для устаревших однобайтных кодировок на основе таких структур:
struct nix_sbmap {
nix_uint8 byte;
nix_rune rune;
};
struct nix_sbcodec {
struct nix_codec base;
struct nix_sbmap const *entries;
nix_size count;
};
Обратите внимание, что struct nix_sbcodec
и struct nix_sbmap
объявлены в исходных файлах , а не в заголовках, поэтому нет необходимости использовать шаблон variant
. Соответствующая функция, например. nix_codec_koi8r()
, назначает struct nix_sbcodec
, устанавливает base
, entries
и count
членов, а затем бросает его на nix_codec
и возвращает его. Каждые фактические encode()
и decode()
вызовов выполняется с помощью этой общественной функции:
nix_size nix_codec_decode
(
nix_codec *codec,
nix_byte const *bdata,
nix_size bsize,
nix_rune *udata,
nix_size usize,
struct nix_error *error
)
{
nix_size result = 0;
struct nix_codec *self = (struct nix_codec*)codec;
return self->decode(self, bdata, bsize, udata, usize, error);
}
Обратите внимание, что state
, mode
, flags
и offset
членов могут быть интересными для любого, используя любой кодек (большая часть из них находится в кодеке функции создателя , offset
изменяется после вызовов на encode()
и decode()
функций и представляет собой количество символов байт/Unicode, которые были успешно обработаны, прежде чем функция завершается. Каждый кодек имеет свою собственную encode()
и decode()
функции, как вы видите.
Теперь вопрос: этот трюк правильный и гарантированно работает по стандарту C?
Заранее благодарен!
В чем вопрос? – IdeaHat
'класс'? в 'c'? –
Это C не C++ правильно? Зачем ты это делаешь? Это откровенно несчастный случай, ожидающий своего служения. Что вы ожидаете от компилятора, если вы присваиваете один «my_object» другому? (Подсказка: 'memcpy (b, a, sizeof (my_object)') –