* Sherlock Library -- Character Conversion with Allocation on a Memory Pool
*
* (c) 2006 Pavel Charvat <pchar@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
*/
#include "lib/lib.h"
#include "lib/mempool.h"
#include "charset/mp-charconv.h"
-#include "charset/stk-charconv.h"
+#include <string.h>
+#include <alloca.h>
byte *
mp_conv(struct mempool *mp, byte *s, uns in_cs, uns out_cs)
{
- return mp_strdup(mp, stk_conv(s, in_cs, out_cs));
+ if (in_cs == out_cs)
+ return mp_strdup(mp, s);
+
+ struct conv_context c;
+ char *b[32];
+ uns bs[32], n = 0, sum = 0;
+ uns l = strlen(s) + 1;
+
+ conv_init(&c);
+ conv_set_charset(&c, in_cs, out_cs);
+ c.source = s;
+ c.source_end = s + l;
+
+ for (;;)
+ {
+ l <<= 1;
+ c.dest_start = c.dest = b[n] = alloca(l);
+ c.dest_end = c.dest_start+ l;
+ uns r = conv_run(&c);
+ sum += bs[n++] = c.dest - c.dest_start;
+ if (r & CONV_SOURCE_END)
+ {
+ c.dest_start = c.dest = mp_alloc(mp, sum);
+ for (uns i = 0; i < n; i++)
+ {
+ memcpy(c.dest, b[i], bs[i]);
+ c.dest += bs[i];
+ }
+ return c.dest_start;
+ }
+ }
}
+
* Sherlock Library -- Character Conversion with Allocation on a Memory Pool
*
* (c) 2006 Pavel Charvat <pchar@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
*/
#ifndef _CHARSET_MP_CHARCONV_H
* Sherlock Library -- Character Conversion with Allocation on the Stack
*
* (c) 2006 Pavel Charvat <pchar@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
*/
#include "lib/lib.h"
#define INITIAL_MIN_SIZE 16
#define INITIAL_SCALE 2
-void
-stk_conv_init(struct stk_conv_context *c, byte *s, uns in_cs, uns out_cs)
+uns
+stk_conv_init(struct conv_context *c, byte *s, uns in_cs, uns out_cs)
{
uns l = strlen(s);
if (in_cs == out_cs)
{
- c->c.source = s;
- c->c.source_end = NULL;
- c->len = l + 1;
- return;
+ c->source = s;
+ c->source_end = NULL;
+ return l + 1;
}
- conv_init(&c->c);
- conv_set_charset(&c->c, in_cs, out_cs);
- c->c.source = s;
- c->c.source_end = s + l + 1;
+ conv_init(c);
+ conv_set_charset(c, in_cs, out_cs);
+ c->source = s;
+ c->source_end = s + l + 1;
if (l < (INITIAL_MIN_SIZE - 1) / INITIAL_SCALE)
- c->len = INITIAL_MIN_SIZE;
+ return INITIAL_MIN_SIZE;
else
- c->len = l * INITIAL_SCALE + 1;
- c->len = 1;
+ return l * INITIAL_SCALE + 1;
}
-int
-stk_conv_step(struct stk_conv_context *c, byte *buf)
+uns
+stk_conv_step(struct conv_context *c, byte *buf, uns len)
{
- if (!c->c.source_end)
+ if (!c->source_end)
{
- memcpy(buf, c->c.source, c->len);
- c->c.dest_start = buf;
+ memcpy(buf, c->source, len);
+ c->dest_start = buf;
return 0;
}
- if (c->c.dest_start)
+ if (c->dest_start)
{
- uns l = c->c.dest_end - c->c.dest_start;
- memcpy(buf, c->c.dest_start, l);
- c->c.dest = buf + l;
+ uns l = c->dest_end - c->dest_start;
+ memcpy(buf, c->dest_start, l);
+ c->dest = buf + l;
}
else
- c->c.dest = buf;
- c->c.dest_start = buf;
- c->c.dest_end = buf + c->len;
- if ((conv_run(&c->c) & CONV_SOURCE_END))
+ c->dest = buf;
+ c->dest_start = buf;
+ c->dest_end = buf + len;
+ if (conv_run(c) & CONV_SOURCE_END)
return 0;
- c->len <<= 1;
- return 1;
+ return len << 1;
}
* Sherlock Library -- Character Conversion with Allocation on the Stack
*
* (c) 2006 Pavel Charvat <pchar@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
*/
#ifndef _CHARSET_STK_CHARCONV_H
/* The following macros convert strings between given charsets (CONV_CHARSET_x). */
#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.len))); _c.c.dest_start; })
+ ({ struct conv_context _c; uns _l=stk_conv_init(&_c, (s), (cs_in), (cs_out)); \
+ while (_l) _l=stk_conv_step(&_c, alloca(_l), _l); _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)
-/* Internal structure and routines. */
-
-struct stk_conv_context {
- struct conv_context c;
- uns len;
-};
+/* Internals */
-void stk_conv_init(struct stk_conv_context *c, byte *s, uns cs_in, uns cs_out);
-int stk_conv_step(struct stk_conv_context *c, byte *buf);
+uns stk_conv_init(struct conv_context *c, byte *s, uns cs_in, uns cs_out);
+uns stk_conv_step(struct conv_context *c, byte *buf, uns len);
#endif