|
ビッグエンディアンとリトルエンディアンで処理を分けてもコード量も可読性もたいして悪化しないことがわかったので、
エンディアンごとに処理を分ける方法をとることにしました。
"%04X"や"%08lX"は使わずすべてバイトごとの出力なので、double等の浮動小数点数型にも対応できました。
[test.c]
#include <stdio.h>
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;
#define ARRAYSIZE(array) (sizeof(array) / sizeof((array)[0]))
#pragma pack(1)
typedef struct {
char c;
short s;
long l;
} st_t;
#pragma pack()
char var_char = 0x11;
short var_short = 0x2233;
long var_long = 0x44556677;
st_t var_st = {0x88, 0x99AA, 0xBBCCDDEE};
char arr_char[2] = {0xFF, 0x11};
short arr_short[2] = {0x2233, 0x4455};
long arr_long[2] = {0x66778899, 0xAABBCCDD};
st_t arr_st[2] = {{0xEE, 0xFF11, 0x22334455}, {0x66, 0x7788, 0x99AABBCC}};
char arr2_char[3][2] = {{0xDD, 0xEE}, {0xFF, 0x11}, {0x22, 0x33}};
short arr2_short[3][2] = {{0x4455, 0x6677}, {0x8899, 0xAABB}, {0xCCDD, 0xEEFF}};
long arr2_long[3][2] = {{0x11223344, 0x55667788}, {0x99AABBCC, 0xDDEEFF11}, {0x22334455, 0x66778899}};
st_t arr2_st[3][2] = {{{0xAA, 0xBBCC, 0xDDEEFF11}, {0x22, 0x3344, 0x55667788}},
{{0x99, 0xAABB, 0xCCDDEEFF}, {0x11, 0x2233, 0x44556677}},
{{0x88, 0x99AA, 0xBBCCDDEE}, {0xFF, 0x1122, 0x33445566}}};
float var_float = 5.5411644e+33; /* 0x778899AA */
double var_double = -1.22256195700545978e-20; /* 0xBBCCDDEEFF112233 */
typedef struct area_tag {
void *begin; /* 開始アドレス */
int size; /* 要素サイズ */
int num; /* 要素数 */
int (*put)(const struct area_tag *area, char *buf); /* 16進出力関数 */
} area_t;
int put_bytes(const void *src, int size, char *buf)
{
static const int endian_test = 1;
const uchar *it;
const uchar *end;
char *p;
p = buf;
if (*(char *)&endian_test) {
/* リトルエンディアン */
for (end = src, it = end + size - 1; it >= end; it--) {
p += sprintf(p, "%02X", *it);
}
}
else {
/* ビッグエンディアン */
for (it = src, end = it + size; it < end; it++) {
p += sprintf(p, "%02X", *it);
}
}
return (p - buf == size * 2) ? p - buf : 0;
}
int put_simple_t(const area_t *area, char *buf)
{
const uchar *it;
const uchar *end;
int entire_size = area->size * area->num;
char *p;
p = buf;
for (it = area->begin, end = it + entire_size; it < end; it += area->size) {
p += put_bytes(it, area->size, p);
}
return (p - buf == entire_size * 2) ? p - buf : 0;
}
int put_st_t(const area_t *area, char *buf)
{
const st_t *it;
const st_t *end;
int entire_size = area->size * area->num;
char *p;
p = buf;
for (it = area->begin, end = it + area->num; it < end; it++) {
p += put_bytes(&it->c, sizeof(it->c), p);
p += put_bytes(&it->s, sizeof(it->s), p);
p += put_bytes(&it->l, sizeof(it->l), p);
}
return (p - buf == entire_size * 2) ? p - buf : 0;
}
const area_t table[] = {
{ &var_char, sizeof(var_char), 1, put_simple_t, }, /* 0 */
{ &var_short, sizeof(var_short), 1, put_simple_t, }, /* 1 */
{ &var_long, sizeof(var_long), 1, put_simple_t, }, /* 2 */
{ &var_st, sizeof(var_st), 1, put_st_t, }, /* 3 */
{ &arr_char[0], sizeof(arr_char[0]), sizeof(arr_char)/sizeof(arr_char[0]), put_simple_t, }, /* 4 */
{ &arr_short[0], sizeof(arr_short[0]), sizeof(arr_short)/sizeof(arr_short[0]), put_simple_t, }, /* 5 */
{ &arr_long[0], sizeof(arr_long[0]), sizeof(arr_long)/sizeof(arr_long[0]), put_simple_t, }, /* 6 */
{ &arr_st[0], sizeof(arr_st[0]), sizeof(arr_st)/sizeof(arr_st[0]), put_st_t, }, /* 7 */
{ &arr2_char[0][0], sizeof(arr2_char[0][0]), sizeof(arr2_char)/sizeof(arr2_char[0][0]), put_simple_t, }, /* 8 */
{ &arr2_short[0][0], sizeof(arr2_short[0][0]), sizeof(arr2_short)/sizeof(arr2_short[0][0]), put_simple_t, }, /* 9 */
{ &arr2_long[0][0], sizeof(arr2_long[0][0]), sizeof(arr2_long)/sizeof(arr2_long[0][0]), put_simple_t, }, /* 10 */
{ &arr2_st[0][0], sizeof(arr2_st[0][0]), sizeof(arr2_st)/sizeof(arr2_st[0][0]), put_st_t, }, /* 11 */
{ &var_float, sizeof(var_float), 1, put_simple_t, }, /* 12 */
{ &var_double, sizeof(var_double), 1, put_simple_t, }, /* 13 */
};
int main(void)
{
char buf[512];
char *p;
int n;
int i;
p = buf;
for (i = 0; i < ARRAYSIZE(table); i++) {
n = table[i].put(&table[i], p);
if (n == 0) return 1;
printf("[%2d] %s\n", i, p); /* デバッグ用 */
p += n;
}
puts("---");
puts(buf);
return 0;
}
|