summaryrefslogtreecommitdiff
path: root/transcode.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-09-12 12:58:23 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-09-12 12:58:23 +0000
commit89a5c998c7297f9f565e434dfae8d03765e3c393 (patch)
treea2b4fe2e79471fa2b28d268db1384c8ebc803364 /transcode.c
parent19438eee8b6b0a51768c49e3b7b3f6070ef64c7d (diff)
* transcode.c (rb_econv_t): new field: num_allocated.
(rb_econv_alloc): extracted from rb_econv_open_by_transcoder_entries. (rb_econv_add_transcoder_at): extracted from rb_econv_decorate_at and generalized (rb_econv_open_by_transcoder_entries): use rb_econv_alloc and rb_econv_add_transcoder_at. (rb_econv_add_converter): extracted from rb_econv_decorate_at. (rb_econv_decorate_at): use rb_econv_add_converter. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19304 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'transcode.c')
-rw-r--r--transcode.c133
1 files changed, 77 insertions, 56 deletions
diff --git a/transcode.c b/transcode.c
index 19b5c55678..d4f349327f 100644
--- a/transcode.c
+++ b/transcode.c
@@ -109,6 +109,7 @@ struct rb_econv_t {
unsigned char *in_data_end;
unsigned char *in_buf_end;
rb_econv_elem_t *elems;
+ int num_allocated;
int num_trans;
int num_finished;
struct rb_transcoding *last_tc;
@@ -774,17 +775,12 @@ rb_transcoding_close(rb_transcoding *tc)
}
static rb_econv_t *
-rb_econv_open_by_transcoder_entries(int n, transcoder_entry_t **entries)
+rb_econv_alloc(int n_hint)
{
rb_econv_t *ec;
- int i;
- for (i = 0; i < n; i++) {
- const rb_transcoder *tr;
- tr = load_transcoder_entry(entries[i]);
- if (!tr)
- return NULL;
- }
+ if (n_hint <= 0)
+ n_hint = 1;
ec = ALLOC(rb_econv_t);
ec->flags = 0;
@@ -799,8 +795,9 @@ rb_econv_open_by_transcoder_entries(int n, transcoder_entry_t **entries)
ec->in_data_start = NULL;
ec->in_data_end = NULL;
ec->in_buf_end = NULL;
- ec->num_trans = n;
- ec->elems = ALLOC_N(rb_econv_elem_t, ec->num_trans);
+ ec->num_allocated = n_hint;
+ ec->num_trans = 0;
+ ec->elems = ALLOC_N(rb_econv_elem_t, ec->num_allocated);
ec->num_finished = 0;
ec->last_tc = NULL;
ec->last_error.result = econv_source_buffer_empty;
@@ -812,26 +809,70 @@ rb_econv_open_by_transcoder_entries(int n, transcoder_entry_t **entries)
ec->last_error.readagain_len = 0;
ec->source_encoding = NULL;
ec->destination_encoding = NULL;
- for (i = 0; i < ec->num_trans; i++) {
- const rb_transcoder *tr = load_transcoder_entry(entries[i]);
- ec->elems[i].tc = rb_transcoding_open_by_transcoder(tr, 0);
- ec->elems[i].out_buf_start = NULL;
- ec->elems[i].out_data_start = NULL;
- ec->elems[i].out_data_end = NULL;
- ec->elems[i].out_buf_end = NULL;
- ec->elems[i].last_result = econv_source_buffer_empty;
+ return ec;
+}
+
+static int
+rb_econv_add_transcoder_at(rb_econv_t *ec, const rb_transcoder *tr, int i)
+{
+ int n, j;
+ int bufsize = 4096;
+ unsigned char *p;
+
+ if (ec->num_trans == ec->num_allocated) {
+ n = ec->num_allocated * 2;
+ REALLOC_N(ec->elems, rb_econv_elem_t, n);
+ ec->num_allocated = n;
}
- if (ec->num_trans)
- ec->last_tc = ec->elems[ec->num_trans-1].tc;
- for (i = 0; i < ec->num_trans; i++) {
- int bufsize = 4096;
- unsigned char *p;
- p = xmalloc(bufsize);
- ec->elems[i].out_buf_start = p;
- ec->elems[i].out_buf_end = p + bufsize;
- ec->elems[i].out_data_start = p;
- ec->elems[i].out_data_end = p;
+ p = xmalloc(bufsize);
+
+ MEMMOVE(ec->elems+i+1, ec->elems+i, rb_econv_elem_t, ec->num_trans-i);
+
+ ec->elems[i].tc = rb_transcoding_open_by_transcoder(tr, 0);
+ ec->elems[i].out_buf_start = p;
+ ec->elems[i].out_buf_end = p + bufsize;
+ ec->elems[i].out_data_start = p;
+ ec->elems[i].out_data_end = p;
+ ec->elems[i].last_result = econv_source_buffer_empty;
+
+ ec->num_trans++;
+
+ if (!SUPPLEMENTAL_CONVERSION(tr->src_encoding, tr->dst_encoding))
+ for (j = ec->num_trans-1; n <= j; j--) {
+ rb_transcoding *tc = ec->elems[j].tc;
+ const rb_transcoder *tr2 = tc->transcoder;
+ if (!SUPPLEMENTAL_CONVERSION(tr2->src_encoding, tr2->dst_encoding)) {
+ ec->last_tc = tc;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static rb_econv_t *
+rb_econv_open_by_transcoder_entries(int n, transcoder_entry_t **entries)
+{
+ rb_econv_t *ec;
+ int i, ret;
+
+ for (i = 0; i < n; i++) {
+ const rb_transcoder *tr;
+ tr = load_transcoder_entry(entries[i]);
+ if (!tr)
+ return NULL;
+ }
+
+ ec = rb_econv_alloc(n);
+
+ for (i = 0; i < n; i++) {
+ const rb_transcoder *tr = load_transcoder_entry(entries[i]);
+ ret = rb_econv_add_transcoder_at(ec, tr, ec->num_trans);
+ if (ret == -1) {
+ rb_econv_close(ec);
+ return NULL;
+ }
}
return ec;
@@ -904,13 +945,6 @@ rb_econv_open0(const char *sname, const char *dname, int ecflags)
ec->source_encoding_name = sname;
ec->destination_encoding_name = dname;
- if (num_trans == 0) {
- ec->last_tc = NULL;
- }
- else {
- ec->last_tc = ec->elems[ec->num_trans-1].tc;
- }
-
return ec;
}
@@ -1728,18 +1762,15 @@ rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
}
static int
-rb_econv_decorate_at(rb_econv_t *ec, const char *decorator_name, int n)
+rb_econv_add_converter(rb_econv_t *ec, const char *sname, const char *dname, int n)
{
transcoder_entry_t *entry;
const rb_transcoder *tr;
- rb_transcoding *tc;
- unsigned char *p;
- int bufsize = 4096;
if (ec->started != 0)
return -1;
- entry = get_transcoder_entry("", decorator_name);
+ entry = get_transcoder_entry(sname, dname);
if (!entry)
return -1;
@@ -1747,23 +1778,13 @@ rb_econv_decorate_at(rb_econv_t *ec, const char *decorator_name, int n)
if (!entry)
return -1;
- tc = rb_transcoding_open_by_transcoder(tr, 0);
-
- REALLOC_N(ec->elems, rb_econv_elem_t, ec->num_trans+1);
- MEMMOVE(ec->elems+n+1, ec->elems+n, rb_econv_elem_t, ec->num_trans-n);
- ec->num_trans++;
-
- ec->elems[n].tc = tc;
-
- bufsize = 4096;
- p = xmalloc(bufsize);
- ec->elems[n].out_buf_start = p;
- ec->elems[n].out_data_start = p;
- ec->elems[n].out_data_end = p;
- ec->elems[n].out_buf_end = p + bufsize;
- ec->elems[n].last_result = econv_source_buffer_empty;
+ return rb_econv_add_transcoder_at(ec, tr, n);
+}
- return 0;
+static int
+rb_econv_decorate_at(rb_econv_t *ec, const char *decorator_name, int n)
+{
+ return rb_econv_add_converter(ec, "", decorator_name, n);
}
int