stk_conv_init(struct stk_conv_context *c, byte *s, uns in_cs, uns out_cs)
{
uns l = strlen(s);
- c->count = 0;
-
- /* For in_cs == out_cs, we emulate stk_strdup */
if (in_cs == out_cs)
{
- c->size[0] = c->request = l + 1;
- c->buf[0] = s;
- c->c.source = NULL;
+ c->c.source = s;
+ c->c.source_end = NULL;
+ c->len = l + 1;
return;
}
-
- /* Initialization */
conv_init(&c->c);
conv_set_charset(&c->c, in_cs, out_cs);
c->c.source = s;
c->c.source_end = s + l + 1;
- c->sum = 0;
-
- /* Size of the first buffer */
if (l < (INITIAL_MIN_SIZE - 1) / INITIAL_SCALE)
- c->request = INITIAL_MIN_SIZE;
+ c->len = INITIAL_MIN_SIZE;
else
- c->request = l * INITIAL_SCALE + 1;
+ c->len = l * INITIAL_SCALE + 1;
+ c->len = 1;
}
int
stk_conv_step(struct stk_conv_context *c, byte *buf)
{
- /* Merge all buffers to the new one and exit */
- if (!c->c.source)
+ if (!c->c.source_end)
{
+ memcpy(buf, c->c.source, c->len);
c->c.dest_start = buf;
- for (uns i = 0; i <= c->count; i++)
- {
- memcpy(buf, c->buf[i], c->size[i]);
- buf += c->size[i];
- }
return 0;
}
-
- /* Run conv_run using the new buffer */
- c->buf[c->count] = c->c.dest_start = c->c.dest = buf;
- c->c.dest_end = buf + c->request;
- if (!(conv_run(&c->c) & CONV_SOURCE_END))
+ if (c->c.dest_start)
{
-
- /* Buffer is too small, continue with a new one */
- c->size[c->count++] = c->request;
- c->sum += c->request;
- c->request <<= 1; /* This can be freely changed */
- return 1;
+ uns l = c->c.dest_end - c->c.dest_start;
+ memcpy(buf, c->c.dest_start, l);
+ c->c.dest = buf + l;
}
-
- /* We have used only one buffer for the conversion, no merges are needed */
- if (!c->count)
- return 0;
-
- /* We can merge everything to the current buffer ... */
- uns s = c->c.dest - c->c.dest_start;
- if (c->sum + s <= c->request)
- {
- memmove(buf + c->sum, buf, s);
- for (uns i = 0; i < c->count; i++)
- {
- memcpy(buf, c->buf[i], c->size[i]);
- buf += c->size[i];
- }
- return 0;
- }
-
- /* ... or we allocate a new one */
else
- {
- c->request = c->sum + s;
- c->size[c->count] = s;
- c->c.source = NULL;
- return 1;
- }
+ c->c.dest = buf;
+ c->c.dest_start = buf;
+ c->c.dest_end = buf + c->len;
+ if ((conv_run(&c->c) & CONV_SOURCE_END))
+ return 0;
+ c->len <<= 1;
+ return 1;
}
#define stk_conv(s, cs_in, cs_out) \
({ struct stk_conv_context _c; stk_conv_init(&_c, (s), (cs_in), (cs_out)); \
- while (stk_conv_step(&_c, alloca(_c.request))); _c.c.dest_start; })
+ while (stk_conv_step(&_c, alloca(_c.len))); _c.c.dest_start; })
#define stk_conv_to_utf8(s, cs_in) stk_conv(s, cs_in, CONV_CHARSET_UTF8)
#define stk_conv_from_utf8(s, cs_out) stk_conv(s, CONV_CHARSET_UTF8, cs_out)
struct stk_conv_context {
struct conv_context c;
- uns count;
- uns sum;
- uns request;
- byte *buf[16];
- uns size[16];
+ uns len;
};
void stk_conv_init(struct stk_conv_context *c, byte *s, uns cs_in, uns cs_out);