rubysl-iconv 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/ext/rubysl/iconv/extconf.rb +51 -0
- data/ext/rubysl/iconv/iconv.c +927 -0
- data/lib/iconv.rb +1 -0
- data/lib/rubysl/iconv.rb +2 -0
- data/lib/rubysl/iconv/version.rb +5 -0
- data/rubysl-iconv.gemspec +23 -0
- data/spec/charset_map_spec.rb +20 -0
- data/spec/close_spec.rb +24 -0
- data/spec/conv_spec.rb +32 -0
- data/spec/failure/failed_spec.rb +53 -0
- data/spec/failure/inspect_spec.rb +22 -0
- data/spec/failure/success_spec.rb +51 -0
- data/spec/failure_spec.rb +30 -0
- data/spec/fixtures/classes.rb +11 -0
- data/spec/iconv_spec.rb +211 -0
- data/spec/new_spec.rb +8 -0
- data/spec/open_spec.rb +29 -0
- data/spec/shared/initialize_exceptions.rb +13 -0
- data/spec/shared/new.rb +33 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b996f2c507adb4ba7d797f82968121e4f4878430
|
4
|
+
data.tar.gz: 88c863f3933a15ce5b24e212a61cf39cc55b8214
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d353a1064d680991c841d91120fb8acb6749f2c081a29b37263bd92e11581e15f6dba715a0b665fbffbc7564e15624ffb8035bf05cae6a460422a53ee21c3b12
|
7
|
+
data.tar.gz: 0243ca3bcaf43e5a44a5f54f7fcfb8475e6183dd928e785ebb488eb1cc2586a8fc58058f64e9c68c6393858958b5465bd9d46750689f8d27d41c476fb88d8860
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2013, Brian Shirai
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
3. Neither the name of the library nor the names of its contributors may be
|
13
|
+
used to endorse or promote products derived from this software without
|
14
|
+
specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
17
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
18
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT,
|
20
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
21
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
22
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
23
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
24
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
25
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Rubysl::Iconv
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'rubysl-iconv'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rubysl-iconv
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
dir_config("iconv")
|
4
|
+
|
5
|
+
conf = File.exist?(File.join($srcdir, "config.charset"))
|
6
|
+
conf = with_config("config-charset", enable_config("config-charset", conf))
|
7
|
+
|
8
|
+
if have_func("iconv", "iconv.h") or
|
9
|
+
have_library("iconv", "iconv", "iconv.h")
|
10
|
+
if checking_for("const of iconv() 2nd argument") do
|
11
|
+
create_tmpsrc(cpp_include("iconv.h") + "---> iconv(cd,0,0,0,0) <---")
|
12
|
+
src = xpopen(cpp_command("")) {|f|f.read}
|
13
|
+
if !(func = src[/^--->\s*(\w+).*\s*<---/, 1])
|
14
|
+
Logging::message "iconv function name not found"
|
15
|
+
false
|
16
|
+
elsif !(second = src[%r"\b#{func}\s*\(.*?,(.*?),.*?\)\s*;"m, 1])
|
17
|
+
Logging::message "prototype for #{func}() not found"
|
18
|
+
false
|
19
|
+
else
|
20
|
+
Logging::message $&+"\n"
|
21
|
+
/\bconst\b/ =~ second
|
22
|
+
end
|
23
|
+
end
|
24
|
+
$defs.push('-DICONV_INPTR_CONST')
|
25
|
+
end
|
26
|
+
if conf
|
27
|
+
prefix = '$(srcdir)'
|
28
|
+
prefix = $nmake ? "{#{prefix}}" : "#{prefix}/"
|
29
|
+
if $extout
|
30
|
+
wrapper = "$(RUBYARCHDIR)/iconv.rb"
|
31
|
+
else
|
32
|
+
wrapper = "./iconv.rb"
|
33
|
+
$INSTALLFILES = [[wrapper, "$(RUBYARCHDIR)"]]
|
34
|
+
end
|
35
|
+
if String === conf
|
36
|
+
require 'uri'
|
37
|
+
scheme = URI.parse(conf).scheme
|
38
|
+
else
|
39
|
+
conf = "$(srcdir)/config.charset"
|
40
|
+
end
|
41
|
+
$cleanfiles << wrapper
|
42
|
+
end
|
43
|
+
create_makefile("iconv/iconv")
|
44
|
+
if conf
|
45
|
+
open("Makefile", "a") do |mf|
|
46
|
+
mf.print("\nall: #{wrapper}\n\n#{wrapper}: #{prefix}charset_alias.rb")
|
47
|
+
mf.print(" ", conf) unless scheme
|
48
|
+
mf.print("\n\t$(RUBY) $(srcdir)/charset_alias.rb #{conf} $@\n")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,927 @@
|
|
1
|
+
/* -*- mode:c; c-file-style:"ruby" -*- */
|
2
|
+
/**********************************************************************
|
3
|
+
|
4
|
+
iconv.c -
|
5
|
+
|
6
|
+
$Author$
|
7
|
+
$Date$
|
8
|
+
created at: Wed Dec 1 20:28:09 JST 1999
|
9
|
+
|
10
|
+
All the files in this distribution are covered under the Ruby's
|
11
|
+
license (see the file COPYING).
|
12
|
+
|
13
|
+
Documentation by Yukihiro Matsumoto and Gavin Sinclair.
|
14
|
+
|
15
|
+
**********************************************************************/
|
16
|
+
|
17
|
+
#include "ruby.h"
|
18
|
+
#include <errno.h>
|
19
|
+
#include <iconv.h>
|
20
|
+
#include <assert.h>
|
21
|
+
#include "st.h"
|
22
|
+
#include "intern.h"
|
23
|
+
|
24
|
+
/*
|
25
|
+
* Document-class: Iconv
|
26
|
+
*
|
27
|
+
* == Summary
|
28
|
+
*
|
29
|
+
* Ruby extension for charset conversion.
|
30
|
+
*
|
31
|
+
* == Abstract
|
32
|
+
*
|
33
|
+
* Iconv is a wrapper class for the UNIX 95 <tt>iconv()</tt> function family,
|
34
|
+
* which translates string between various encoding systems.
|
35
|
+
*
|
36
|
+
* See Open Group's on-line documents for more details.
|
37
|
+
* * <tt>iconv.h</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.h.html
|
38
|
+
* * <tt>iconv_open()</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv_open.html
|
39
|
+
* * <tt>iconv()</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.html
|
40
|
+
* * <tt>iconv_close()</tt>: http://www.opengroup.org/onlinepubs/007908799/xsh/iconv_close.html
|
41
|
+
*
|
42
|
+
* Which coding systems are available is platform-dependent.
|
43
|
+
*
|
44
|
+
* == Examples
|
45
|
+
*
|
46
|
+
* 1. Simple conversion between two charsets.
|
47
|
+
*
|
48
|
+
* converted_text = Iconv.conv('iso-8859-15', 'utf-8', text)
|
49
|
+
*
|
50
|
+
* 2. Instantiate a new Iconv and use method Iconv#iconv.
|
51
|
+
*
|
52
|
+
* cd = Iconv.new(to, from)
|
53
|
+
* begin
|
54
|
+
* input.each { |s| output << cd.iconv(s) }
|
55
|
+
* output << cd.iconv(nil) # Don't forget this!
|
56
|
+
* ensure
|
57
|
+
* cd.close
|
58
|
+
* end
|
59
|
+
*
|
60
|
+
* 3. Invoke Iconv.open with a block.
|
61
|
+
*
|
62
|
+
* Iconv.open(to, from) do |cd|
|
63
|
+
* input.each { |s| output << cd.iconv(s) }
|
64
|
+
* output << cd.iconv(nil)
|
65
|
+
* end
|
66
|
+
*
|
67
|
+
* 4. Shorthand for (3).
|
68
|
+
*
|
69
|
+
* Iconv.iconv(to, from, *input.to_a)
|
70
|
+
*/
|
71
|
+
|
72
|
+
/* Invalid value for iconv_t is -1 but 0 for VALUE, I hope VALUE is
|
73
|
+
big enough to keep iconv_t */
|
74
|
+
#define VALUE2ICONV(v) ((iconv_t)((VALUE)(v) ^ -1))
|
75
|
+
#define ICONV2VALUE(c) ((VALUE)(c) ^ -1)
|
76
|
+
|
77
|
+
struct iconv_env_t
|
78
|
+
{
|
79
|
+
iconv_t cd;
|
80
|
+
int argc;
|
81
|
+
VALUE *argv;
|
82
|
+
VALUE ret;
|
83
|
+
VALUE (*append)_((VALUE, VALUE));
|
84
|
+
};
|
85
|
+
|
86
|
+
static VALUE rb_eIconvInvalidEncoding;
|
87
|
+
static VALUE rb_eIconvFailure;
|
88
|
+
static VALUE rb_eIconvIllegalSeq;
|
89
|
+
static VALUE rb_eIconvInvalidChar;
|
90
|
+
static VALUE rb_eIconvOutOfRange;
|
91
|
+
static VALUE rb_eIconvBrokenLibrary;
|
92
|
+
|
93
|
+
static ID rb_success, rb_failed;
|
94
|
+
static VALUE iconv_fail _((VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env, const char *mesg));
|
95
|
+
static VALUE iconv_fail_retry _((VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env, const char *mesg));
|
96
|
+
static VALUE iconv_failure_initialize _((VALUE error, VALUE mesg, VALUE success, VALUE failed));
|
97
|
+
static VALUE iconv_failure_success _((VALUE self));
|
98
|
+
static VALUE iconv_failure_failed _((VALUE self));
|
99
|
+
|
100
|
+
static iconv_t iconv_create _((VALUE to, VALUE from));
|
101
|
+
static void iconv_dfree _((void *cd));
|
102
|
+
static VALUE iconv_free _((VALUE cd));
|
103
|
+
static VALUE iconv_try _((iconv_t cd, const char **inptr, size_t *inlen, char **outptr, size_t *outlen));
|
104
|
+
static VALUE rb_str_derive _((VALUE str, const char* ptr, int len));
|
105
|
+
static VALUE iconv_convert _((iconv_t cd, VALUE str, long start, long length, struct iconv_env_t* env));
|
106
|
+
static VALUE iconv_s_allocate _((VALUE klass));
|
107
|
+
static VALUE iconv_initialize _((VALUE self, VALUE to, VALUE from));
|
108
|
+
static VALUE iconv_s_open _((VALUE self, VALUE to, VALUE from));
|
109
|
+
static VALUE iconv_s_convert _((struct iconv_env_t* env));
|
110
|
+
static VALUE iconv_s_iconv _((int argc, VALUE *argv, VALUE self));
|
111
|
+
static VALUE iconv_init_state _((VALUE cd));
|
112
|
+
static VALUE iconv_finish _((VALUE self));
|
113
|
+
static VALUE iconv_iconv _((int argc, VALUE *argv, VALUE self));
|
114
|
+
|
115
|
+
static VALUE charset_map;
|
116
|
+
|
117
|
+
/*
|
118
|
+
* Document-method: charset_map
|
119
|
+
* call-seq: Iconv.charset_map
|
120
|
+
*
|
121
|
+
* Returns the map from canonical name to system dependent name.
|
122
|
+
*/
|
123
|
+
static VALUE charset_map_get _((void))
|
124
|
+
{
|
125
|
+
return charset_map;
|
126
|
+
}
|
127
|
+
|
128
|
+
static char *
|
129
|
+
map_charset(VALUE *code)
|
130
|
+
{
|
131
|
+
VALUE val = StringValue(*code);
|
132
|
+
|
133
|
+
if (RHASH_SIZE(charset_map)) {
|
134
|
+
VALUE key = rb_funcall2(val, rb_intern("downcase"), 0, 0);
|
135
|
+
StringValuePtr(key);
|
136
|
+
VALUE data = rb_hash_aref(charset_map, key);
|
137
|
+
if (data != Qnil) {
|
138
|
+
*code = data;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
return StringValuePtr(*code);
|
142
|
+
}
|
143
|
+
|
144
|
+
NORETURN(static void rb_iconv_sys_fail(const char *s));
|
145
|
+
static void
|
146
|
+
rb_iconv_sys_fail(const char *s)
|
147
|
+
{
|
148
|
+
if (errno == 0) {
|
149
|
+
rb_exc_raise(iconv_fail(rb_eIconvBrokenLibrary, Qnil, Qnil, NULL, s));
|
150
|
+
}
|
151
|
+
rb_sys_fail(s);
|
152
|
+
}
|
153
|
+
|
154
|
+
#define rb_sys_fail(s) rb_iconv_sys_fail(s)
|
155
|
+
|
156
|
+
static iconv_t
|
157
|
+
iconv_create
|
158
|
+
#ifdef HAVE_PROTOTYPES
|
159
|
+
(VALUE to, VALUE from)
|
160
|
+
#else /* HAVE_PROTOTYPES */
|
161
|
+
(to, from)
|
162
|
+
VALUE to;
|
163
|
+
VALUE from;
|
164
|
+
#endif /* HAVE_PROTOTYPES */
|
165
|
+
{
|
166
|
+
const char* tocode = map_charset(&to);
|
167
|
+
const char* fromcode = map_charset(&from);
|
168
|
+
|
169
|
+
iconv_t cd = iconv_open(tocode, fromcode);
|
170
|
+
|
171
|
+
if (cd == (iconv_t)-1) {
|
172
|
+
switch (errno) {
|
173
|
+
case EMFILE:
|
174
|
+
case ENFILE:
|
175
|
+
case ENOMEM:
|
176
|
+
rb_gc();
|
177
|
+
cd = iconv_open(tocode, fromcode);
|
178
|
+
}
|
179
|
+
if (cd == (iconv_t)-1) {
|
180
|
+
int inval = errno == EINVAL;
|
181
|
+
const char *s = inval ? "invalid encoding " : "iconv";
|
182
|
+
volatile VALUE msg = rb_str_new(0, strlen(s) + RSTRING(to)->len +
|
183
|
+
RSTRING(from)->len + 8);
|
184
|
+
|
185
|
+
sprintf(RSTRING(msg)->ptr, "%s(\"%s\", \"%s\")",
|
186
|
+
s, RSTRING(to)->ptr, RSTRING(from)->ptr);
|
187
|
+
s = RSTRING(msg)->ptr;
|
188
|
+
RSTRING(msg)->len = strlen(s);
|
189
|
+
if (!inval) rb_sys_fail(s);
|
190
|
+
rb_exc_raise(iconv_fail(rb_eIconvInvalidEncoding, Qnil,
|
191
|
+
rb_ary_new3(2, to, from), NULL, s));
|
192
|
+
}
|
193
|
+
}
|
194
|
+
|
195
|
+
return cd;
|
196
|
+
}
|
197
|
+
|
198
|
+
static void
|
199
|
+
iconv_dfree
|
200
|
+
#ifdef HAVE_PROTOTYPES
|
201
|
+
(void *cd)
|
202
|
+
#else /* HAVE_PROTOTYPES */
|
203
|
+
(cd)
|
204
|
+
void *cd;
|
205
|
+
#endif /* HAVE_PROTOTYPES */
|
206
|
+
{
|
207
|
+
iconv_close(VALUE2ICONV(cd));
|
208
|
+
}
|
209
|
+
|
210
|
+
#define ICONV_FREE iconv_dfree
|
211
|
+
|
212
|
+
static VALUE
|
213
|
+
iconv_free
|
214
|
+
#ifdef HAVE_PROTOTYPES
|
215
|
+
(VALUE cd)
|
216
|
+
#else /* HAVE_PROTOTYPES */
|
217
|
+
(cd)
|
218
|
+
VALUE cd;
|
219
|
+
#endif /* HAVE_PROTOTYPES */
|
220
|
+
{
|
221
|
+
if (cd && iconv_close(VALUE2ICONV(cd)) == -1)
|
222
|
+
rb_sys_fail("iconv_close");
|
223
|
+
return Qnil;
|
224
|
+
}
|
225
|
+
|
226
|
+
static VALUE
|
227
|
+
check_iconv
|
228
|
+
#ifdef HAVE_PROTOTYPES
|
229
|
+
(VALUE obj)
|
230
|
+
#else /* HAVE_PROTOTYPES */
|
231
|
+
(obj)
|
232
|
+
VALUE obj;
|
233
|
+
#endif /* HAVE_PROTOTYPES */
|
234
|
+
{
|
235
|
+
Check_Type(obj, T_DATA);
|
236
|
+
if (RDATA(obj)->dfree != ICONV_FREE) {
|
237
|
+
rb_raise(rb_eArgError, "Iconv expected (%s)", rb_class2name(CLASS_OF(obj)));
|
238
|
+
}
|
239
|
+
return (VALUE)DATA_PTR(obj);
|
240
|
+
}
|
241
|
+
|
242
|
+
static VALUE
|
243
|
+
iconv_try
|
244
|
+
#ifdef HAVE_PROTOTYPES
|
245
|
+
(iconv_t cd, const char **inptr, size_t *inlen, char **outptr, size_t *outlen)
|
246
|
+
#else /* HAVE_PROTOTYPES */
|
247
|
+
(cd, inptr, inlen, outptr, outlen)
|
248
|
+
iconv_t cd;
|
249
|
+
const char **inptr;
|
250
|
+
size_t *inlen;
|
251
|
+
char **outptr;
|
252
|
+
size_t *outlen;
|
253
|
+
#endif /* HAVE_PROTOTYPES */
|
254
|
+
{
|
255
|
+
#ifdef ICONV_INPTR_CONST
|
256
|
+
#define ICONV_INPTR_CAST
|
257
|
+
#else
|
258
|
+
#define ICONV_INPTR_CAST (char **)
|
259
|
+
#endif
|
260
|
+
size_t ret;
|
261
|
+
|
262
|
+
errno = 0;
|
263
|
+
ret = iconv(cd, ICONV_INPTR_CAST inptr, inlen, outptr, outlen);
|
264
|
+
if (ret == (size_t)-1) {
|
265
|
+
if (!*inlen)
|
266
|
+
return Qfalse;
|
267
|
+
switch (errno) {
|
268
|
+
case E2BIG:
|
269
|
+
/* try the left in next loop */
|
270
|
+
break;
|
271
|
+
case EILSEQ:
|
272
|
+
return rb_eIconvIllegalSeq;
|
273
|
+
case EINVAL:
|
274
|
+
return rb_eIconvInvalidChar;
|
275
|
+
case 0:
|
276
|
+
return rb_eIconvBrokenLibrary;
|
277
|
+
default:
|
278
|
+
rb_sys_fail("iconv");
|
279
|
+
}
|
280
|
+
}
|
281
|
+
else if (*inlen > 0) {
|
282
|
+
/* something goes wrong */
|
283
|
+
return rb_eIconvIllegalSeq;
|
284
|
+
}
|
285
|
+
else if (ret) {
|
286
|
+
return Qnil; /* conversion */
|
287
|
+
}
|
288
|
+
return Qfalse;
|
289
|
+
}
|
290
|
+
|
291
|
+
#define FAILED_MAXLEN 16
|
292
|
+
|
293
|
+
static VALUE iconv_failure_initialize
|
294
|
+
#ifdef HAVE_PROTOTYPES
|
295
|
+
(VALUE error, VALUE mesg, VALUE success, VALUE failed)
|
296
|
+
#else /* HAVE_PROTOTYPES */
|
297
|
+
(error, mesg, success, failed)
|
298
|
+
VALUE error, mesg, success, failed;
|
299
|
+
#endif /* HAVE_PROTOTYPES */
|
300
|
+
{
|
301
|
+
rb_call_super(1, &mesg);
|
302
|
+
rb_ivar_set(error, rb_success, success);
|
303
|
+
rb_ivar_set(error, rb_failed, failed);
|
304
|
+
return error;
|
305
|
+
}
|
306
|
+
|
307
|
+
static VALUE
|
308
|
+
iconv_fail
|
309
|
+
#ifdef HAVE_PROTOTYPES
|
310
|
+
(VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env, const char *mesg)
|
311
|
+
#else /* HAVE_PROTOTYPES */
|
312
|
+
(error, success, failed, env, mesg)
|
313
|
+
VALUE error, success, failed;
|
314
|
+
struct iconv_env_t *env;
|
315
|
+
const char *mesg;
|
316
|
+
#endif /* HAVE_PROTOTYPES */
|
317
|
+
{
|
318
|
+
VALUE args[3];
|
319
|
+
|
320
|
+
if (mesg && *mesg) {
|
321
|
+
args[0] = rb_str_new2(mesg);
|
322
|
+
}
|
323
|
+
else if (TYPE(failed) != T_STRING || RSTRING(failed)->len < FAILED_MAXLEN) {
|
324
|
+
args[0] = rb_inspect(failed);
|
325
|
+
}
|
326
|
+
else {
|
327
|
+
args[0] = rb_inspect(rb_str_substr(failed, 0, FAILED_MAXLEN));
|
328
|
+
rb_str_cat2(args[0], "...");
|
329
|
+
}
|
330
|
+
args[1] = success;
|
331
|
+
args[2] = failed;
|
332
|
+
if (env) {
|
333
|
+
args[1] = env->append(rb_obj_dup(env->ret), success);
|
334
|
+
if (env->argc > 0) {
|
335
|
+
*(env->argv) = failed;
|
336
|
+
args[2] = rb_ary_new4(env->argc, env->argv);
|
337
|
+
}
|
338
|
+
}
|
339
|
+
return rb_class_new_instance(3, args, error);
|
340
|
+
}
|
341
|
+
|
342
|
+
static VALUE
|
343
|
+
iconv_fail_retry(VALUE error, VALUE success, VALUE failed, struct iconv_env_t* env, const char *mesg)
|
344
|
+
{
|
345
|
+
error = iconv_fail(error, success, failed, env, mesg);
|
346
|
+
if (!rb_block_given_p()) rb_exc_raise(error);
|
347
|
+
rb_set_errinfo(error);
|
348
|
+
return rb_yield(failed);
|
349
|
+
}
|
350
|
+
|
351
|
+
static VALUE
|
352
|
+
rb_str_derive
|
353
|
+
#ifdef HAVE_PROTOTYPES
|
354
|
+
(VALUE str, const char* ptr, int len)
|
355
|
+
#else /* HAVE_PROTOTYPES */
|
356
|
+
(str, ptr, len)
|
357
|
+
VALUE str;
|
358
|
+
const char *ptr;
|
359
|
+
int len;
|
360
|
+
#endif /* HAVE_PROTOTYPES */
|
361
|
+
{
|
362
|
+
VALUE ret;
|
363
|
+
|
364
|
+
if (NIL_P(str))
|
365
|
+
return rb_str_new(ptr, len);
|
366
|
+
if (RSTRING(str)->ptr == ptr && RSTRING(str)->len == len)
|
367
|
+
return str;
|
368
|
+
if (RSTRING(str)->ptr + RSTRING(str)->len == ptr + len)
|
369
|
+
ret = rb_str_substr(str, ptr - RSTRING(str)->ptr, len);
|
370
|
+
else
|
371
|
+
ret = rb_str_new(ptr, len);
|
372
|
+
OBJ_INFECT(ret, str);
|
373
|
+
return ret;
|
374
|
+
}
|
375
|
+
|
376
|
+
static VALUE
|
377
|
+
iconv_convert
|
378
|
+
#ifdef HAVE_PROTOTYPES
|
379
|
+
(iconv_t cd, VALUE str, long start, long length, struct iconv_env_t* env)
|
380
|
+
#else /* HAVE_PROTOTYPES */
|
381
|
+
(cd, str, start, length, env)
|
382
|
+
iconv_t cd;
|
383
|
+
VALUE str;
|
384
|
+
long start;
|
385
|
+
long length;
|
386
|
+
struct iconv_env_t *env;
|
387
|
+
#endif /* HAVE_PROTOTYPES */
|
388
|
+
{
|
389
|
+
VALUE ret = Qfalse;
|
390
|
+
VALUE error = Qfalse;
|
391
|
+
VALUE rescue;
|
392
|
+
const char *inptr, *instart;
|
393
|
+
size_t inlen;
|
394
|
+
/* I believe ONE CHARACTER never exceed this. */
|
395
|
+
char buffer[BUFSIZ];
|
396
|
+
char *outptr;
|
397
|
+
size_t outlen;
|
398
|
+
|
399
|
+
if (cd == (iconv_t)-1)
|
400
|
+
rb_raise(rb_eArgError, "closed iconv");
|
401
|
+
|
402
|
+
if (NIL_P(str)) {
|
403
|
+
/* Reset output pointer or something. */
|
404
|
+
inptr = "";
|
405
|
+
inlen = 0;
|
406
|
+
outptr = buffer;
|
407
|
+
outlen = sizeof(buffer);
|
408
|
+
error = iconv_try(cd, &inptr, &inlen, &outptr, &outlen);
|
409
|
+
if (RTEST(error)) {
|
410
|
+
unsigned int i;
|
411
|
+
rescue = iconv_fail_retry(error, Qnil, Qnil, env, 0);
|
412
|
+
if (TYPE(rescue) == T_ARRAY) {
|
413
|
+
str = RARRAY_LEN(rescue) > 0 ? rb_ary_entry(rescue, 0) : Qnil;
|
414
|
+
}
|
415
|
+
if (FIXNUM_P(str) && (i = FIX2INT(str)) <= 0xff) {
|
416
|
+
char c = i;
|
417
|
+
str = rb_str_new(&c, 1);
|
418
|
+
}
|
419
|
+
else if (!NIL_P(str)) {
|
420
|
+
StringValue(str);
|
421
|
+
}
|
422
|
+
}
|
423
|
+
|
424
|
+
inptr = NULL;
|
425
|
+
length = 0;
|
426
|
+
}
|
427
|
+
else {
|
428
|
+
int slen;
|
429
|
+
|
430
|
+
StringValue(str);
|
431
|
+
slen = RSTRING(str)->len;
|
432
|
+
inptr = RSTRING(str)->ptr;
|
433
|
+
|
434
|
+
inptr += start;
|
435
|
+
if (length < 0 || length > start + slen)
|
436
|
+
length = slen - start;
|
437
|
+
}
|
438
|
+
instart = inptr;
|
439
|
+
inlen = length;
|
440
|
+
|
441
|
+
do {
|
442
|
+
char errmsg[50];
|
443
|
+
const char *tmpstart = inptr;
|
444
|
+
outptr = buffer;
|
445
|
+
outlen = sizeof(buffer);
|
446
|
+
|
447
|
+
errmsg[0] = 0;
|
448
|
+
error = iconv_try(cd, &inptr, &inlen, &outptr, &outlen);
|
449
|
+
|
450
|
+
if (0 <= outlen && outlen <= sizeof(buffer)) {
|
451
|
+
outlen = sizeof(buffer) - outlen;
|
452
|
+
if (NIL_P(error) || /* something converted */
|
453
|
+
outlen > inptr - tmpstart || /* input can't contain output */
|
454
|
+
(outlen < inptr - tmpstart && inlen > 0) || /* something skipped */
|
455
|
+
memcmp(buffer, tmpstart, outlen)) /* something differs */
|
456
|
+
{
|
457
|
+
if (NIL_P(str)) {
|
458
|
+
ret = rb_str_new(buffer, outlen);
|
459
|
+
}
|
460
|
+
else {
|
461
|
+
if (ret) {
|
462
|
+
ret = rb_str_buf_cat(ret, instart, tmpstart - instart);
|
463
|
+
}
|
464
|
+
else {
|
465
|
+
ret = rb_str_new(instart, tmpstart - instart);
|
466
|
+
OBJ_INFECT(ret, str);
|
467
|
+
}
|
468
|
+
ret = rb_str_buf_cat(ret, buffer, outlen);
|
469
|
+
instart = inptr;
|
470
|
+
}
|
471
|
+
}
|
472
|
+
else if (!inlen) {
|
473
|
+
inptr = tmpstart + outlen;
|
474
|
+
}
|
475
|
+
}
|
476
|
+
else {
|
477
|
+
/* Some iconv() have a bug, return *outlen out of range */
|
478
|
+
sprintf(errmsg, "bug?(output length = %ld)", (long)(sizeof(buffer) - outlen));
|
479
|
+
error = rb_eIconvOutOfRange;
|
480
|
+
}
|
481
|
+
|
482
|
+
if (RTEST(error)) {
|
483
|
+
long len = 0;
|
484
|
+
|
485
|
+
if (!ret)
|
486
|
+
ret = rb_str_derive(str, instart, inptr - instart);
|
487
|
+
else if (inptr > instart)
|
488
|
+
rb_str_cat(ret, instart, inptr - instart);
|
489
|
+
str = rb_str_derive(str, inptr, inlen);
|
490
|
+
rescue = iconv_fail_retry(error, ret, str, env, errmsg);
|
491
|
+
if (TYPE(rescue) == T_ARRAY) {
|
492
|
+
if ((len = RARRAY_LEN(rescue)) > 0)
|
493
|
+
rb_str_concat(ret, rb_ary_entry(rescue, 0));
|
494
|
+
if (len > 1 && !NIL_P(str = rb_ary_entry(rescue, 1))) {
|
495
|
+
StringValue(str);
|
496
|
+
inlen = length = RSTRING(str)->len;
|
497
|
+
instart = inptr = RSTRING(str)->ptr;
|
498
|
+
continue;
|
499
|
+
}
|
500
|
+
}
|
501
|
+
else if (!NIL_P(rescue)) {
|
502
|
+
rb_str_concat(ret, rescue);
|
503
|
+
}
|
504
|
+
break;
|
505
|
+
}
|
506
|
+
} while (inlen > 0);
|
507
|
+
|
508
|
+
if (!ret)
|
509
|
+
ret = rb_str_derive(str, instart, inptr - instart);
|
510
|
+
else if (inptr > instart)
|
511
|
+
rb_str_cat(ret, instart, inptr - instart);
|
512
|
+
return ret;
|
513
|
+
}
|
514
|
+
|
515
|
+
static VALUE
|
516
|
+
iconv_s_allocate
|
517
|
+
#ifdef HAVE_PROTOTYPES
|
518
|
+
(VALUE klass)
|
519
|
+
#else /* HAVE_PROTOTYPES */
|
520
|
+
(klass)
|
521
|
+
VALUE klass;
|
522
|
+
#endif /* HAVE_PROTOTYPES */
|
523
|
+
{
|
524
|
+
return Data_Wrap_Struct(klass, 0, ICONV_FREE, 0);
|
525
|
+
}
|
526
|
+
|
527
|
+
/*
|
528
|
+
* Document-method: new
|
529
|
+
* call-seq: Iconv.new(to, from)
|
530
|
+
*
|
531
|
+
* Creates new code converter from a coding-system designated with +from+
|
532
|
+
* to another one designated with +to+.
|
533
|
+
*
|
534
|
+
* === Parameters
|
535
|
+
*
|
536
|
+
* +to+:: encoding name for destination
|
537
|
+
* +from+:: encoding name for source
|
538
|
+
*
|
539
|
+
* === Exceptions
|
540
|
+
*
|
541
|
+
* TypeError:: if +to+ or +from+ aren't String
|
542
|
+
* InvalidEncoding:: if designated converter couldn't find out
|
543
|
+
* SystemCallError:: if <tt>iconv_open(3)</tt> fails
|
544
|
+
*/
|
545
|
+
static VALUE
|
546
|
+
iconv_initialize
|
547
|
+
#ifdef HAVE_PROTOTYPES
|
548
|
+
(VALUE self, VALUE to, VALUE from)
|
549
|
+
#else /* HAVE_PROTOTYPES */
|
550
|
+
(self, to, from)
|
551
|
+
VALUE self;
|
552
|
+
VALUE to;
|
553
|
+
VALUE from;
|
554
|
+
#endif /* HAVE_PROTOTYPES */
|
555
|
+
{
|
556
|
+
iconv_free(check_iconv(self));
|
557
|
+
DATA_PTR(self) = NULL;
|
558
|
+
DATA_PTR(self) = (void *)ICONV2VALUE(iconv_create(to, from));
|
559
|
+
return self;
|
560
|
+
}
|
561
|
+
|
562
|
+
/*
|
563
|
+
* Document-method: open
|
564
|
+
* call-seq: Iconv.open(to, from) { |iconv| ... }
|
565
|
+
*
|
566
|
+
* Equivalent to Iconv.new except that when it is called with a block, it
|
567
|
+
* yields with the new instance and closes it, and returns the result which
|
568
|
+
* returned from the block.
|
569
|
+
*/
|
570
|
+
static VALUE
|
571
|
+
iconv_s_open
|
572
|
+
#ifdef HAVE_PROTOTYPES
|
573
|
+
(VALUE self, VALUE to, VALUE from)
|
574
|
+
#else /* HAVE_PROTOTYPES */
|
575
|
+
(self, to, from)
|
576
|
+
VALUE self;
|
577
|
+
VALUE to;
|
578
|
+
VALUE from;
|
579
|
+
#endif /* HAVE_PROTOTYPES */
|
580
|
+
{
|
581
|
+
VALUE cd = ICONV2VALUE(iconv_create(to, from));
|
582
|
+
|
583
|
+
self = Data_Wrap_Struct(self, NULL, ICONV_FREE, (void *)cd);
|
584
|
+
if (rb_block_given_p()) {
|
585
|
+
return rb_ensure(rb_yield, self, (VALUE(*)())iconv_finish, self);
|
586
|
+
}
|
587
|
+
else {
|
588
|
+
return self;
|
589
|
+
}
|
590
|
+
}
|
591
|
+
|
592
|
+
static VALUE
|
593
|
+
iconv_s_convert
|
594
|
+
#ifdef HAVE_PROTOTYPES
|
595
|
+
(struct iconv_env_t* env)
|
596
|
+
#else /* HAVE_PROTOTYPES */
|
597
|
+
(env)
|
598
|
+
struct iconv_env_t *env;
|
599
|
+
#endif /* HAVE_PROTOTYPES */
|
600
|
+
{
|
601
|
+
VALUE last = 0;
|
602
|
+
|
603
|
+
for (; env->argc > 0; --env->argc, ++env->argv) {
|
604
|
+
VALUE s = iconv_convert(env->cd, last = *(env->argv), 0, -1, env);
|
605
|
+
env->append(env->ret, s);
|
606
|
+
}
|
607
|
+
|
608
|
+
if (!NIL_P(last)) {
|
609
|
+
VALUE s = iconv_convert(env->cd, Qnil, 0, 0, env);
|
610
|
+
if (RSTRING(s)->len)
|
611
|
+
env->append(env->ret, s);
|
612
|
+
}
|
613
|
+
|
614
|
+
return env->ret;
|
615
|
+
}
|
616
|
+
|
617
|
+
/*
|
618
|
+
* Document-method: Iconv::iconv
|
619
|
+
* call-seq: Iconv.iconv(to, from, *strs)
|
620
|
+
*
|
621
|
+
* Shorthand for
|
622
|
+
* Iconv.open(to, from) { |cd|
|
623
|
+
* (strs + [nil]).collect { |s| cd.iconv(s) }
|
624
|
+
* }
|
625
|
+
*
|
626
|
+
* === Parameters
|
627
|
+
*
|
628
|
+
* <tt>to, from</tt>:: see Iconv.new
|
629
|
+
* <tt>strs</tt>:: strings to be converted
|
630
|
+
*
|
631
|
+
* === Exceptions
|
632
|
+
*
|
633
|
+
* Exceptions thrown by Iconv.new, Iconv.open and Iconv#iconv.
|
634
|
+
*/
|
635
|
+
static VALUE
|
636
|
+
iconv_s_iconv
|
637
|
+
#ifdef HAVE_PROTOTYPES
|
638
|
+
(int argc, VALUE *argv, VALUE self)
|
639
|
+
#else /* HAVE_PROTOTYPES */
|
640
|
+
(argc, argv, self)
|
641
|
+
int argc;
|
642
|
+
VALUE *argv;
|
643
|
+
VALUE self;
|
644
|
+
#endif /* HAVE_PROTOTYPES */
|
645
|
+
{
|
646
|
+
struct iconv_env_t arg;
|
647
|
+
|
648
|
+
if (argc < 2) /* needs `to' and `from' arguments at least */
|
649
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, 2);
|
650
|
+
|
651
|
+
arg.argc = argc -= 2;
|
652
|
+
arg.argv = argv + 2;
|
653
|
+
arg.append = rb_ary_push;
|
654
|
+
arg.ret = rb_ary_new2(argc);
|
655
|
+
arg.cd = iconv_create(argv[0], argv[1]);
|
656
|
+
return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
|
657
|
+
}
|
658
|
+
|
659
|
+
/*
|
660
|
+
* Document-method: Iconv::conv
|
661
|
+
* call-seq: Iconv.conv(to, from, str)
|
662
|
+
*
|
663
|
+
* Shorthand for
|
664
|
+
* Iconv.iconv(to, from, str).join
|
665
|
+
* See Iconv.iconv.
|
666
|
+
*/
|
667
|
+
static VALUE
|
668
|
+
iconv_s_conv
|
669
|
+
#ifdef HAVE_PROTOTYPES
|
670
|
+
(VALUE self, VALUE to, VALUE from, VALUE str)
|
671
|
+
#else /* HAVE_PROTOTYPES */
|
672
|
+
(self, to, from, str)
|
673
|
+
VALUE self, to, from, str;
|
674
|
+
#endif /* HAVE_PROTOTYPES */
|
675
|
+
{
|
676
|
+
struct iconv_env_t arg;
|
677
|
+
|
678
|
+
arg.argc = 1;
|
679
|
+
arg.argv = &str;
|
680
|
+
arg.append = rb_str_append;
|
681
|
+
arg.ret = rb_str_new(0, 0);
|
682
|
+
arg.cd = iconv_create(to, from);
|
683
|
+
return rb_ensure(iconv_s_convert, (VALUE)&arg, iconv_free, ICONV2VALUE(arg.cd));
|
684
|
+
}
|
685
|
+
|
686
|
+
/*
|
687
|
+
* Document-method: close
|
688
|
+
*
|
689
|
+
* Finishes conversion.
|
690
|
+
*
|
691
|
+
* After calling this, calling Iconv#iconv will cause an exception, but
|
692
|
+
* multiple calls of #close are guaranteed to end successfully.
|
693
|
+
*
|
694
|
+
* Returns a string containing the byte sequence to change the output buffer to
|
695
|
+
* its initial shift state.
|
696
|
+
*/
|
697
|
+
static VALUE
|
698
|
+
iconv_init_state
|
699
|
+
#ifdef HAVE_PROTOTYPES
|
700
|
+
(VALUE cd)
|
701
|
+
#else /* HAVE_PROTOTYPES */
|
702
|
+
(cd)
|
703
|
+
VALUE cd;
|
704
|
+
#endif /* HAVE_PROTOTYPES */
|
705
|
+
{
|
706
|
+
return iconv_convert(VALUE2ICONV(cd), Qnil, 0, 0, NULL);
|
707
|
+
}
|
708
|
+
|
709
|
+
static VALUE
|
710
|
+
iconv_finish
|
711
|
+
#ifdef HAVE_PROTOTYPES
|
712
|
+
(VALUE self)
|
713
|
+
#else /* HAVE_PROTOTYPES */
|
714
|
+
(self)
|
715
|
+
VALUE self;
|
716
|
+
#endif /* HAVE_PROTOTYPES */
|
717
|
+
{
|
718
|
+
VALUE cd = check_iconv(self);
|
719
|
+
|
720
|
+
if (!cd) return Qnil;
|
721
|
+
DATA_PTR(self) = NULL;
|
722
|
+
|
723
|
+
return rb_ensure(iconv_init_state, cd, iconv_free, cd);
|
724
|
+
}
|
725
|
+
|
726
|
+
/*
|
727
|
+
* Document-method: Iconv#iconv
|
728
|
+
* call-seq: iconv(str, start=0, length=-1)
|
729
|
+
*
|
730
|
+
* Converts string and returns the result.
|
731
|
+
* * If +str+ is a String, converts <tt>str[start, length]</tt> and returns the converted string.
|
732
|
+
* * If +str+ is +nil+, places converter itself into initial shift state and
|
733
|
+
* just returns a string containing the byte sequence to change the output
|
734
|
+
* buffer to its initial shift state.
|
735
|
+
* * Otherwise, raises an exception.
|
736
|
+
*
|
737
|
+
* === Parameters
|
738
|
+
*
|
739
|
+
* str:: string to be converted, or nil
|
740
|
+
* start:: starting offset
|
741
|
+
* length:: conversion length; nil or -1 means whole the string from start
|
742
|
+
*
|
743
|
+
* === Exceptions
|
744
|
+
*
|
745
|
+
* * IconvIllegalSequence
|
746
|
+
* * IconvInvalidCharacter
|
747
|
+
* * IconvOutOfRange
|
748
|
+
*
|
749
|
+
* === Examples
|
750
|
+
*
|
751
|
+
* See the Iconv documentation.
|
752
|
+
*/
|
753
|
+
static VALUE
|
754
|
+
iconv_iconv
|
755
|
+
#ifdef HAVE_PROTOTYPES
|
756
|
+
(int argc, VALUE *argv, VALUE self)
|
757
|
+
#else /* HAVE_PROTOTYPES */
|
758
|
+
(argc, argv, self)
|
759
|
+
int argc;
|
760
|
+
VALUE *argv;
|
761
|
+
VALUE self;
|
762
|
+
#endif /* HAVE_PROTOTYPES */
|
763
|
+
{
|
764
|
+
VALUE str, n1, n2;
|
765
|
+
VALUE cd = check_iconv(self);
|
766
|
+
long start = 0, length = 0, slen = 0;
|
767
|
+
|
768
|
+
rb_scan_args(argc, argv, "12", &str, &n1, &n2);
|
769
|
+
if (!NIL_P(str)) slen = RSTRING_LEN(StringValue(str));
|
770
|
+
if (argc != 2 || !RTEST(rb_range_beg_len(n1, &start, &length, slen, 0))) {
|
771
|
+
if (NIL_P(n1) || ((start = NUM2LONG(n1)) < 0 ? (start += slen) >= 0 : start < slen)) {
|
772
|
+
if (NIL_P(n2)) {
|
773
|
+
length = -1;
|
774
|
+
}
|
775
|
+
else if ((length = NUM2LONG(n2)) >= slen - start) {
|
776
|
+
length = slen - start;
|
777
|
+
}
|
778
|
+
}
|
779
|
+
}
|
780
|
+
|
781
|
+
return iconv_convert(VALUE2ICONV(cd), str, start, length, NULL);
|
782
|
+
}
|
783
|
+
|
784
|
+
/*
|
785
|
+
* Document-class: Iconv::Failure
|
786
|
+
*
|
787
|
+
* Base attributes for Iconv exceptions.
|
788
|
+
*/
|
789
|
+
|
790
|
+
/*
|
791
|
+
* Document-method: success
|
792
|
+
* call-seq: success
|
793
|
+
*
|
794
|
+
* Returns string(s) translated successfully until the exception occurred.
|
795
|
+
* * In the case of failure occurred within Iconv.iconv, returned
|
796
|
+
* value is an array of strings translated successfully preceding
|
797
|
+
* failure and the last element is string on the way.
|
798
|
+
*/
|
799
|
+
static VALUE
|
800
|
+
iconv_failure_success
|
801
|
+
#ifdef HAVE_PROTOTYPES
|
802
|
+
(VALUE self)
|
803
|
+
#else /* HAVE_PROTOTYPES */
|
804
|
+
(self)
|
805
|
+
VALUE self;
|
806
|
+
#endif /* HAVE_PROTOTYPES */
|
807
|
+
{
|
808
|
+
return rb_attr_get(self, rb_success);
|
809
|
+
}
|
810
|
+
|
811
|
+
/*
|
812
|
+
* Document-method: failed
|
813
|
+
* call-seq: failed
|
814
|
+
*
|
815
|
+
* Returns substring of the original string passed to Iconv that starts at the
|
816
|
+
* character caused the exception.
|
817
|
+
*/
|
818
|
+
static VALUE
|
819
|
+
iconv_failure_failed
|
820
|
+
#ifdef HAVE_PROTOTYPES
|
821
|
+
(VALUE self)
|
822
|
+
#else /* HAVE_PROTOTYPES */
|
823
|
+
(self)
|
824
|
+
VALUE self;
|
825
|
+
#endif /* HAVE_PROTOTYPES */
|
826
|
+
{
|
827
|
+
return rb_attr_get(self, rb_failed);
|
828
|
+
}
|
829
|
+
|
830
|
+
/*
|
831
|
+
* Document-method: inspect
|
832
|
+
* call-seq: inspect
|
833
|
+
*
|
834
|
+
* Returns inspected string like as: #<_class_: _success_, _failed_>
|
835
|
+
*/
|
836
|
+
static VALUE
|
837
|
+
iconv_failure_inspect
|
838
|
+
#ifdef HAVE_PROTOTYPES
|
839
|
+
(VALUE self)
|
840
|
+
#else /* HAVE_PROTOTYPES */
|
841
|
+
(self)
|
842
|
+
VALUE self;
|
843
|
+
#endif /* HAVE_PROTOTYPES */
|
844
|
+
{
|
845
|
+
const char *cname = rb_class2name(CLASS_OF(self));
|
846
|
+
VALUE success = rb_attr_get(self, rb_success);
|
847
|
+
VALUE failed = rb_attr_get(self, rb_failed);
|
848
|
+
VALUE str = rb_str_buf_cat2(rb_str_new2("#<"), cname);
|
849
|
+
str = rb_str_buf_cat(str, ": ", 2);
|
850
|
+
str = rb_str_buf_append(str, rb_inspect(success));
|
851
|
+
str = rb_str_buf_cat(str, ", ", 2);
|
852
|
+
str = rb_str_buf_append(str, rb_inspect(failed));
|
853
|
+
return rb_str_buf_cat(str, ">", 1);
|
854
|
+
}
|
855
|
+
|
856
|
+
/*
|
857
|
+
* Document-class: Iconv::InvalidEncoding
|
858
|
+
*
|
859
|
+
* Requested coding-system is not available on this system.
|
860
|
+
*/
|
861
|
+
|
862
|
+
/*
|
863
|
+
* Document-class: Iconv::IllegalSequence
|
864
|
+
*
|
865
|
+
* Input conversion stopped due to an input byte that does not belong to
|
866
|
+
* the input codeset, or the output codeset does not contain the
|
867
|
+
* character.
|
868
|
+
*/
|
869
|
+
|
870
|
+
/*
|
871
|
+
* Document-class: Iconv::InvalidCharacter
|
872
|
+
*
|
873
|
+
* Input conversion stopped due to an incomplete character or shift
|
874
|
+
* sequence at the end of the input buffer.
|
875
|
+
*/
|
876
|
+
|
877
|
+
/*
|
878
|
+
* Document-class: Iconv::OutOfRange
|
879
|
+
*
|
880
|
+
* Iconv library internal error. Must not occur.
|
881
|
+
*/
|
882
|
+
|
883
|
+
/*
|
884
|
+
* Document-class: Iconv::BrokenLibrary
|
885
|
+
*
|
886
|
+
* Detected a bug of underlying iconv(3) libray.
|
887
|
+
* * returns an error without setting errno properly
|
888
|
+
*/
|
889
|
+
|
890
|
+
void
|
891
|
+
Init_iconv _((void))
|
892
|
+
{
|
893
|
+
VALUE rb_cIconv = rb_define_class("Iconv", rb_cData);
|
894
|
+
|
895
|
+
rb_define_alloc_func(rb_cIconv, iconv_s_allocate);
|
896
|
+
rb_define_singleton_method(rb_cIconv, "open", iconv_s_open, 2);
|
897
|
+
rb_define_singleton_method(rb_cIconv, "iconv", iconv_s_iconv, -1);
|
898
|
+
rb_define_singleton_method(rb_cIconv, "conv", iconv_s_conv, 3);
|
899
|
+
rb_define_method(rb_cIconv, "initialize", iconv_initialize, 2);
|
900
|
+
rb_define_method(rb_cIconv, "close", iconv_finish, 0);
|
901
|
+
rb_define_method(rb_cIconv, "iconv", iconv_iconv, -1);
|
902
|
+
|
903
|
+
rb_eIconvFailure = rb_define_module_under(rb_cIconv, "Failure");
|
904
|
+
rb_define_method(rb_eIconvFailure, "initialize", iconv_failure_initialize, 3);
|
905
|
+
rb_define_method(rb_eIconvFailure, "success", iconv_failure_success, 0);
|
906
|
+
rb_define_method(rb_eIconvFailure, "failed", iconv_failure_failed, 0);
|
907
|
+
rb_define_method(rb_eIconvFailure, "inspect", iconv_failure_inspect, 0);
|
908
|
+
|
909
|
+
rb_eIconvInvalidEncoding = rb_define_class_under(rb_cIconv, "InvalidEncoding", rb_eArgError);
|
910
|
+
rb_eIconvIllegalSeq = rb_define_class_under(rb_cIconv, "IllegalSequence", rb_eArgError);
|
911
|
+
rb_eIconvInvalidChar = rb_define_class_under(rb_cIconv, "InvalidCharacter", rb_eArgError);
|
912
|
+
rb_eIconvOutOfRange = rb_define_class_under(rb_cIconv, "OutOfRange", rb_eRuntimeError);
|
913
|
+
rb_eIconvBrokenLibrary = rb_define_class_under(rb_cIconv, "BrokenLibrary", rb_eRuntimeError);
|
914
|
+
rb_include_module(rb_eIconvInvalidEncoding, rb_eIconvFailure);
|
915
|
+
rb_include_module(rb_eIconvIllegalSeq, rb_eIconvFailure);
|
916
|
+
rb_include_module(rb_eIconvInvalidChar, rb_eIconvFailure);
|
917
|
+
rb_include_module(rb_eIconvOutOfRange, rb_eIconvFailure);
|
918
|
+
rb_include_module(rb_eIconvBrokenLibrary, rb_eIconvFailure);
|
919
|
+
|
920
|
+
rb_success = rb_intern("success");
|
921
|
+
rb_failed = rb_intern("failed");
|
922
|
+
|
923
|
+
rb_gc_register_address(&charset_map);
|
924
|
+
charset_map = rb_hash_new();
|
925
|
+
rb_define_singleton_method(rb_cIconv, "charset_map", charset_map_get, 0);
|
926
|
+
}
|
927
|
+
|