diff --git a/.clang-format b/.clang-format index 6389e3b123..90ab29d69e 100644 --- a/.clang-format +++ b/.clang-format @@ -16,6 +16,7 @@ AlignAfterOpenBracket: true AlignConsecutiveMacros: AcrossEmptyLines AllowAllArgumentsOnNextLine: false +AllowShortEnumsOnASingleLine: false AllowShortIfStatementsOnASingleLine: WithoutElse AlwaysBreakAfterReturnType: All BinPackArguments: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0fcc066791..2e6be30daa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,6 +26,7 @@ repos: ?lib/ctx\.c| ?lib/db\.c| ?lib/grn_ii\.h| + ?lib/grn_io\.h| ?lib/grn_proc\.h| ?lib/highlighter\.c| ?lib/ii\.c| diff --git a/lib/grn_io.h b/lib/grn_io.h index 515761da06..0acfa4a409 100644 --- a/lib/grn_io.h +++ b/lib/grn_io.h @@ -27,9 +27,9 @@ extern "C" { #endif #ifdef WIN32 -# define GRN_IO_FILE_CREATE_MODE (GENERIC_READ | GENERIC_WRITE) +# define GRN_IO_FILE_CREATE_MODE (GENERIC_READ | GENERIC_WRITE) #else /* WIN32 */ -# define GRN_IO_FILE_CREATE_MODE 0644 +# define GRN_IO_FILE_CREATE_MODE 0644 #endif /* WIN32 */ typedef enum { @@ -110,26 +110,39 @@ struct _grn_io { uint32_t *lock; }; -GRN_API grn_io *grn_io_create(grn_ctx *ctx, const char *path, - uint32_t header_size, uint32_t segment_size, - uint32_t max_segment, grn_io_mode mode, - unsigned int flags); -grn_io *grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode); -GRN_API grn_rc grn_io_close(grn_ctx *ctx, grn_io *io); -grn_rc grn_io_remove(grn_ctx *ctx, const char *path); -grn_rc grn_io_remove_if_exist(grn_ctx *ctx, const char *path); -grn_rc grn_io_size(grn_ctx *ctx, grn_io *io, uint64_t *size); -grn_rc grn_io_rename(grn_ctx *ctx, const char *old_name, const char *new_name); -GRN_API void *grn_io_header(grn_io *io); - -void *grn_io_win_map(grn_ctx *ctx, - grn_io *io, - grn_io_win *iw, - uint32_t segment, - uint32_t offset, - uint32_t size, - grn_io_rw_mode mode); -grn_rc grn_io_win_unmap(grn_ctx *ctx, grn_io_win *iw); +GRN_API grn_io * +grn_io_create(grn_ctx *ctx, + const char *path, + uint32_t header_size, + uint32_t segment_size, + uint32_t max_segment, + grn_io_mode mode, + unsigned int flags); +grn_io * +grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode); +GRN_API grn_rc +grn_io_close(grn_ctx *ctx, grn_io *io); +grn_rc +grn_io_remove(grn_ctx *ctx, const char *path); +grn_rc +grn_io_remove_if_exist(grn_ctx *ctx, const char *path); +grn_rc +grn_io_size(grn_ctx *ctx, grn_io *io, uint64_t *size); +grn_rc +grn_io_rename(grn_ctx *ctx, const char *old_name, const char *new_name); +GRN_API void * +grn_io_header(grn_io *io); + +void * +grn_io_win_map(grn_ctx *ctx, + grn_io *io, + grn_io_win *iw, + uint32_t segment, + uint32_t offset, + uint32_t size, + grn_io_rw_mode mode); +grn_rc +grn_io_win_unmap(grn_ctx *ctx, grn_io_win *iw); typedef struct _grn_io_ja_einfo grn_io_ja_einfo; typedef struct _grn_io_ja_ehead grn_io_ja_ehead; @@ -144,27 +157,45 @@ struct _grn_io_ja_ehead { uint32_t key; }; -grn_rc grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos, - uint32_t key, uint32_t segment, uint32_t offset, - void **value, uint32_t *value_len); -grn_rc grn_io_write_ja(grn_io *io, grn_ctx *ctx, - uint32_t key, uint32_t segment, uint32_t offset, - void *value, uint32_t value_len); - -grn_rc grn_io_write_ja_ehead(grn_io *io, grn_ctx *ctx, uint32_t key, - uint32_t segment, uint32_t offset, uint32_t value_len); - -#define GRN_TABLE_ADD (0x01<<6) -#define GRN_TABLE_ADDED (0x01<<7) - -#define GRN_IO_MAX_RETRY (0x10000) -#define GRN_IO_MAX_REF (0x80000000) - -#define GRN_IO_EXPIRE_GTICK (0x01) -#define GRN_IO_EXPIRE_SEGMENT (0x02) -#define GRN_IO_TEMPORARY (0x04) - -void grn_io_seg_map_(grn_ctx *ctx, grn_io *io, uint32_t segno, grn_io_mapinfo *info); +grn_rc +grn_io_read_ja(grn_io *io, + grn_ctx *ctx, + grn_io_ja_einfo *einfo, + uint32_t epos, + uint32_t key, + uint32_t segment, + uint32_t offset, + void **value, + uint32_t *value_len); +grn_rc +grn_io_write_ja(grn_io *io, + grn_ctx *ctx, + uint32_t key, + uint32_t segment, + uint32_t offset, + void *value, + uint32_t value_len); + +grn_rc +grn_io_write_ja_ehead(grn_io *io, + grn_ctx *ctx, + uint32_t key, + uint32_t segment, + uint32_t offset, + uint32_t value_len); + +#define GRN_TABLE_ADD (0x01 << 6) +#define GRN_TABLE_ADDED (0x01 << 7) + +#define GRN_IO_MAX_RETRY (0x10000) +#define GRN_IO_MAX_REF (0x80000000) + +#define GRN_IO_EXPIRE_GTICK (0x01) +#define GRN_IO_EXPIRE_SEGMENT (0x02) +#define GRN_IO_TEMPORARY (0x04) + +void +grn_io_seg_map_(grn_ctx *ctx, grn_io *io, uint32_t segno, grn_io_mapinfo *info); /* * io mustn't be NULL; @@ -195,8 +226,11 @@ grn_io_seg_ref(grn_ctx *ctx, grn_io *io, uint32_t segno) if (nref) { GRN_ATOMIC_ADD_EX(pnref, -1, nref); if (retry >= GRN_IO_MAX_RETRY) { - GRN_LOG(ctx, GRN_LOG_CRIT, - "deadlock detected! in grn_io_seg_ref(%p, %u)", io, segno); + GRN_LOG(ctx, + GRN_LOG_CRIT, + "deadlock detected! in grn_io_seg_ref(%p, %u)", + io, + segno); break; } GRN_FUTEX_WAIT(pnref); @@ -229,9 +263,12 @@ grn_io_seg_ref(grn_ctx *ctx, grn_io *io, uint32_t segno) if (nref >= GRN_IO_MAX_REF) { GRN_ATOMIC_ADD_EX(pnref, -1, nref); if (retry >= GRN_IO_MAX_RETRY) { - GRN_LOG(ctx, GRN_LOG_CRIT, + GRN_LOG(ctx, + GRN_LOG_CRIT, "deadlock detected!! in grn_io_seg_ref(%p, %u, %u)", - io, segno, nref); + io, + segno, + nref); *pnref = 0; /* force reset */ break; } @@ -240,15 +277,20 @@ grn_io_seg_ref(grn_ctx *ctx, grn_io *io, uint32_t segno) } if (nref >= 0x40000000) { ALERT("strange nref value!! in grn_io_seg_ref(%p, %u, %u)", - io, segno, nref); + io, + segno, + nref); } if (!info->map) { if (nref) { GRN_ATOMIC_ADD_EX(pnref, -1, nref); if (retry >= GRN_IO_MAX_RETRY) { - GRN_LOG(ctx, GRN_LOG_CRIT, + GRN_LOG(ctx, + GRN_LOG_CRIT, "deadlock detected!!! in grn_io_seg_ref(%p, %u, %u)", - io, segno, nref); + io, + segno, + nref); break; } GRN_FUTEX_WAIT(pnref); @@ -284,9 +326,11 @@ grn_io_seg_ref(grn_ctx *ctx, grn_io *io, uint32_t segno) if (nref) { GRN_ATOMIC_ADD_EX(pnref, -1, nref); if (retry >= GRN_IO_MAX_RETRY) { - GRN_LOG(ctx, GRN_LOG_CRIT, + GRN_LOG(ctx, + GRN_LOG_CRIT, "deadlock detected!!!! in grn_io_seg_ref(%p, %u)", - io, segno); + io, + segno); break; } GRN_FUTEX_WAIT(pnref); @@ -321,14 +365,16 @@ static grn_inline void grn_io_seg_unref(grn_ctx *ctx, grn_io *io, uint32_t segno) { if (GRN_IO_EXPIRE_SEGMENT == - (io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) { + (io->flags & (GRN_IO_EXPIRE_GTICK | GRN_IO_EXPIRE_SEGMENT))) { uint32_t nref, *pnref = &(io)->maps[segno].nref; GRN_ATOMIC_ADD_EX(pnref, -1, nref); } } -uint32_t grn_io_base_seg(grn_io *io); -const char *grn_io_path(grn_io *io); +uint32_t +grn_io_base_seg(grn_io *io); +const char * +grn_io_path(grn_io *io); typedef struct _grn_io_array_spec grn_io_array_spec; @@ -346,34 +392,46 @@ struct _grn_io_array_info { void **addrs; }; -grn_io *grn_io_create_with_array(grn_ctx *ctx, const char *path, uint32_t header_size, - uint32_t segment_size, grn_io_mode mode, - uint32_t n_arrays, grn_io_array_spec *array_specs); - -void grn_io_segment_alloc(grn_ctx *ctx, grn_io *io, grn_io_array_info *ai, - uint32_t lseg, int *flags, void **p); - -GRN_API grn_rc grn_io_lock(grn_ctx *ctx, grn_io *io, int timeout); -GRN_API void grn_io_unlock(grn_ctx *ctx, grn_io *io); -void grn_io_clear_lock(grn_io *io); -uint32_t grn_io_is_locked(grn_io *io); -grn_bool grn_io_is_corrupt(grn_ctx *ctx, grn_io *io); -size_t grn_io_get_disk_usage(grn_ctx *ctx, grn_io *io); +grn_io * +grn_io_create_with_array(grn_ctx *ctx, + const char *path, + uint32_t header_size, + uint32_t segment_size, + grn_io_mode mode, + uint32_t n_arrays, + grn_io_array_spec *array_specs); + +void +grn_io_segment_alloc(grn_ctx *ctx, + grn_io *io, + grn_io_array_info *ai, + uint32_t lseg, + int *flags, + void **p); + +GRN_API grn_rc +grn_io_lock(grn_ctx *ctx, grn_io *io, int timeout); +GRN_API void +grn_io_unlock(grn_ctx *ctx, grn_io *io); +void +grn_io_clear_lock(grn_io *io); +uint32_t +grn_io_is_locked(grn_io *io); +grn_bool +grn_io_is_corrupt(grn_ctx *ctx, grn_io *io); +size_t +grn_io_get_disk_usage(grn_ctx *ctx, grn_io *io); static grn_inline void * -grn_io_array_at(grn_ctx *ctx, - grn_io *io, - uint32_t array, - uint64_t offset, - int *flags) +grn_io_array_at( + grn_ctx *ctx, grn_io *io, uint32_t array, uint64_t offset, int *flags) { grn_io_array_info *ainfo = &(io->ainfo[array]); uint32_t lseg = (uint32_t)(offset >> ainfo->w_of_elm_in_a_segment); if (lseg >= ainfo->max_n_segments) { ERR(GRN_NO_MEMORY_AVAILABLE, "[io][array][at] too large offset: %" GRN_FMT_INT64U - ": max=%" GRN_FMT_INT64D - ": nth=%u" + ": max=%" GRN_FMT_INT64D ": nth=%u" ": path=<%s>", offset, (int64_t)((ainfo->max_n_segments << ainfo->w_of_elm_in_a_segment) - 1), @@ -384,50 +442,76 @@ grn_io_array_at(grn_ctx *ctx, void **p_ = &ainfo->addrs[lseg]; if (!*p_) { grn_io_segment_alloc(ctx, io, ainfo, lseg, flags, p_); - if (!*p_) { return NULL; } + if (!*p_) { + return NULL; + } } return (((byte *)*p_) + ((offset & ainfo->elm_mask_in_a_segment) * ainfo->element_size)); } -#define GRN_IO_ARRAY_BIT_AT(io,array,offset,res) do {\ - int flags_ = 0;\ - uint8_t *ptr_ = grn_io_array_at(ctx, (io), (array), ((offset) >> 3) + 1, &flags_,);\ - res = ptr_ ? ((*ptr_ >> ((offset) & 7)) & 1) : 0;\ -} while (0) - -#define GRN_IO_ARRAY_BIT_ON(io,array,offset) do {\ - int flags_ = GRN_TABLE_ADD;\ - uint8_t *ptr_ = grn_io_array_at(ctx, (io), (array), ((offset) >> 3) + 1, &flags_);\ - if (ptr_) { *ptr_ |= (1 << ((offset) & 7)); }\ -} while (0) - -#define GRN_IO_ARRAY_BIT_OFF(io,array,offset) do {\ - int flags_ = GRN_TABLE_ADD;\ - uint8_t *ptr = grn_io_array_at(ctx, (io), (array), ((offset) >> 3) + 1, &flags_);\ - if (ptr_) { *ptr_ &= ~(1 << ((offset) & 7)); }\ -} while (0) - -#define GRN_IO_ARRAY_BIT_FLIP(io,array,offset) do {\ - int flags_ = GRN_TABLE_ADD;\ - uint8_t *ptr_ = grn_io_array_at((io), (array), ((offset) >> 3) + 1, &flags_);\ - if (ptr_) { *ptr_ ^= (1 << ((offset) & 7)); }\ -} while (0) - -void *grn_io_anon_map(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length); -void grn_io_anon_unmap(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length); -uint32_t grn_io_detect_type(grn_ctx *ctx, const char *path); -grn_rc grn_io_set_type(grn_io *io, uint32_t type); -uint32_t grn_io_get_type(grn_io *io); - -void grn_io_init_from_env(void); - -uint32_t grn_io_expire(grn_ctx *ctx, grn_io *io, uint32_t count_thresh, uint32_t limit); - -grn_rc grn_io_flush(grn_ctx *ctx, grn_io *io); - -bool grn_io_warm_path(grn_ctx *ctx, grn_io *io, const char *path); -grn_rc grn_io_warm(grn_ctx *ctx, grn_io *io); +#define GRN_IO_ARRAY_BIT_AT(io, array, offset, res) \ + do { \ + int flags_ = 0; \ + uint8_t *ptr_ = \ + grn_io_array_at(ctx, (io), (array), ((offset) >> 3) + 1, &flags_, ); \ + res = ptr_ ? ((*ptr_ >> ((offset)&7)) & 1) : 0; \ + } while (0) + +#define GRN_IO_ARRAY_BIT_ON(io, array, offset) \ + do { \ + int flags_ = GRN_TABLE_ADD; \ + uint8_t *ptr_ = \ + grn_io_array_at(ctx, (io), (array), ((offset) >> 3) + 1, &flags_); \ + if (ptr_) { \ + *ptr_ |= (1 << ((offset)&7)); \ + } \ + } while (0) + +#define GRN_IO_ARRAY_BIT_OFF(io, array, offset) \ + do { \ + int flags_ = GRN_TABLE_ADD; \ + uint8_t *ptr = \ + grn_io_array_at(ctx, (io), (array), ((offset) >> 3) + 1, &flags_); \ + if (ptr_) { \ + *ptr_ &= ~(1 << ((offset)&7)); \ + } \ + } while (0) + +#define GRN_IO_ARRAY_BIT_FLIP(io, array, offset) \ + do { \ + int flags_ = GRN_TABLE_ADD; \ + uint8_t *ptr_ = \ + grn_io_array_at((io), (array), ((offset) >> 3) + 1, &flags_); \ + if (ptr_) { \ + *ptr_ ^= (1 << ((offset)&7)); \ + } \ + } while (0) + +void * +grn_io_anon_map(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length); +void +grn_io_anon_unmap(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length); +uint32_t +grn_io_detect_type(grn_ctx *ctx, const char *path); +grn_rc +grn_io_set_type(grn_io *io, uint32_t type); +uint32_t +grn_io_get_type(grn_io *io); + +void +grn_io_init_from_env(void); + +uint32_t +grn_io_expire(grn_ctx *ctx, grn_io *io, uint32_t count_thresh, uint32_t limit); + +grn_rc +grn_io_flush(grn_ctx *ctx, grn_io *io); + +bool +grn_io_warm_path(grn_ctx *ctx, grn_io *io, const char *path); +grn_rc +grn_io_warm(grn_ctx *ctx, grn_io *io); /* encode/decode */ @@ -476,117 +560,125 @@ grn_rc grn_io_warm(grn_ctx *ctx, grn_io *io); * C = (v >> 8) & 0xff * D = (v & 0xff) * */ -#define GRN_B_ENC(v,p) do {\ - uint8_t *_p = (uint8_t *)p; \ - uint32_t _v = v; \ - if (_v < 0x8f) { \ - *_p++ = (uint8_t)_v; \ - } else if (_v < 0x408f) { \ - _v -= 0x8f; \ - *_p++ = (uint8_t)(0xc0 + (_v >> 8)); \ - *_p++ = _v & 0xff; \ - } else if (_v < 0x20408f) { \ - _v -= 0x408f; \ - *_p++ = (uint8_t)(0xa0 + (_v >> 16)); \ - *_p++ = (_v >> 8) & 0xff; \ - *_p++ = _v & 0xff; \ - } else if (_v < 0x1020408f) { \ - _v -= 0x20408f; \ - *_p++ = (uint8_t)(0x90 + (_v >> 24)); \ - *_p++ = (_v >> 16) & 0xff; \ - *_p++ = (_v >> 8) & 0xff; \ - *_p++ = _v & 0xff; \ - } else { \ - *_p++ = 0x8f; \ - grn_memcpy(_p, &_v, sizeof(uint32_t));\ - _p += sizeof(uint32_t); \ - } \ - p = _p; \ -} while (0) - -#define GRN_B_ENC_SIZE(v) \ - ((v) < 0x8f ? 1 : ((v) < 0x408f ? 2 : ((v) < 0x20408f ? 3 : ((v) < 0x1020408f ? 4 : 5)))) - -#define GRN_B_DEC(v,p) do { \ - uint8_t *_p = (uint8_t *)p; \ - uint32_t _v = *_p++; \ - switch (_v >> 4) { \ - case 0x08 : \ - if (_v == 0x8f) { \ - grn_memcpy(&_v, _p, sizeof(uint32_t));\ - _p += sizeof(uint32_t); \ - } \ - break; \ - case 0x09 : \ - _v = (_v - 0x90) * 0x100 + *_p++; \ - _v = _v * 0x100 + *_p++; \ - _v = _v * 0x100 + *_p++ + 0x20408f; \ - break; \ - case 0x0a : \ - case 0x0b : \ - _v = (_v - 0xa0) * 0x100 + *_p++; \ - _v = _v * 0x100 + *_p++ + 0x408f; \ - break; \ - case 0x0c : \ - case 0x0d : \ - case 0x0e : \ - case 0x0f : \ - _v = (_v - 0xc0) * 0x100 + *_p++ + 0x8f; \ - break; \ - } \ - v = _v; \ - p = _p; \ -} while (0) - -#define GRN_B_SKIP(p) do { \ - uint8_t *_p = (uint8_t *)p; \ - uint32_t _v = *_p++; \ - switch (_v >> 4) { \ - case 0x08 : \ - if (_v == 0x8f) { \ - _p += sizeof(uint32_t); \ - } \ - break; \ - case 0x09 : \ - _p += 3; \ - break; \ - case 0x0a : \ - case 0x0b : \ - _p += 2; \ - break; \ - case 0x0c : \ - case 0x0d : \ - case 0x0e : \ - case 0x0f : \ - _p += 1; \ - break; \ - } \ - p = _p; \ -} while (0) - -#define GRN_B_COPY(p2,p1) do { \ - uint32_t size = 0, _v = *p1++; \ - *p2++ = _v; \ - switch (_v >> 4) { \ - case 0x08 : \ - size = (_v == 0x8f) ? 4 : 0; \ - break; \ - case 0x09 : \ - size = 3; \ - break; \ - case 0x0a : \ - case 0x0b : \ - size = 2; \ - break; \ - case 0x0c : \ - case 0x0d : \ - case 0x0e : \ - case 0x0f : \ - size = 1; \ - break; \ - } \ - while (size--) { *p2++ = *p1++; } \ -} while (0) +#define GRN_B_ENC(v, p) \ + do { \ + uint8_t *_p = (uint8_t *)p; \ + uint32_t _v = v; \ + if (_v < 0x8f) { \ + *_p++ = (uint8_t)_v; \ + } else if (_v < 0x408f) { \ + _v -= 0x8f; \ + *_p++ = (uint8_t)(0xc0 + (_v >> 8)); \ + *_p++ = _v & 0xff; \ + } else if (_v < 0x20408f) { \ + _v -= 0x408f; \ + *_p++ = (uint8_t)(0xa0 + (_v >> 16)); \ + *_p++ = (_v >> 8) & 0xff; \ + *_p++ = _v & 0xff; \ + } else if (_v < 0x1020408f) { \ + _v -= 0x20408f; \ + *_p++ = (uint8_t)(0x90 + (_v >> 24)); \ + *_p++ = (_v >> 16) & 0xff; \ + *_p++ = (_v >> 8) & 0xff; \ + *_p++ = _v & 0xff; \ + } else { \ + *_p++ = 0x8f; \ + grn_memcpy(_p, &_v, sizeof(uint32_t)); \ + _p += sizeof(uint32_t); \ + } \ + p = _p; \ + } while (0) + +#define GRN_B_ENC_SIZE(v) \ + ((v) < 0x8f \ + ? 1 \ + : ((v) < 0x408f ? 2 : ((v) < 0x20408f ? 3 : ((v) < 0x1020408f ? 4 : 5)))) + +#define GRN_B_DEC(v, p) \ + do { \ + uint8_t *_p = (uint8_t *)p; \ + uint32_t _v = *_p++; \ + switch (_v >> 4) { \ + case 0x08: \ + if (_v == 0x8f) { \ + grn_memcpy(&_v, _p, sizeof(uint32_t)); \ + _p += sizeof(uint32_t); \ + } \ + break; \ + case 0x09: \ + _v = (_v - 0x90) * 0x100 + *_p++; \ + _v = _v * 0x100 + *_p++; \ + _v = _v * 0x100 + *_p++ + 0x20408f; \ + break; \ + case 0x0a: \ + case 0x0b: \ + _v = (_v - 0xa0) * 0x100 + *_p++; \ + _v = _v * 0x100 + *_p++ + 0x408f; \ + break; \ + case 0x0c: \ + case 0x0d: \ + case 0x0e: \ + case 0x0f: \ + _v = (_v - 0xc0) * 0x100 + *_p++ + 0x8f; \ + break; \ + } \ + v = _v; \ + p = _p; \ + } while (0) + +#define GRN_B_SKIP(p) \ + do { \ + uint8_t *_p = (uint8_t *)p; \ + uint32_t _v = *_p++; \ + switch (_v >> 4) { \ + case 0x08: \ + if (_v == 0x8f) { \ + _p += sizeof(uint32_t); \ + } \ + break; \ + case 0x09: \ + _p += 3; \ + break; \ + case 0x0a: \ + case 0x0b: \ + _p += 2; \ + break; \ + case 0x0c: \ + case 0x0d: \ + case 0x0e: \ + case 0x0f: \ + _p += 1; \ + break; \ + } \ + p = _p; \ + } while (0) + +#define GRN_B_COPY(p2, p1) \ + do { \ + uint32_t size = 0, _v = *p1++; \ + *p2++ = _v; \ + switch (_v >> 4) { \ + case 0x08: \ + size = (_v == 0x8f) ? 4 : 0; \ + break; \ + case 0x09: \ + size = 3; \ + break; \ + case 0x0a: \ + case 0x0b: \ + size = 2; \ + break; \ + case 0x0c: \ + case 0x0d: \ + case 0x0e: \ + case 0x0f: \ + size = 1; \ + break; \ + } \ + while (size--) { \ + *p2++ = *p1++; \ + } \ + } while (0) #ifdef __cplusplus }