summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorser <ser@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-09-22 12:40:45 +0000
committerser <ser@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-09-22 12:40:45 +0000
commit8b53e39a2e6110cf13827c88673a3ef2667991cf (patch)
treeeb1fa37c2a675b75c295285b5c313ba05801c2b8
parentf36a3f0ea57aa05a72cb58937c7a737455a98a38 (diff)
downloadruby-rexml_adds_tests.tar.gz
Second merge from trunk.rexml_adds_tests
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/rexml_adds_tests@19455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog787
-rw-r--r--bignum.c10
-rw-r--r--common.mk4
-rw-r--r--complex.c374
-rw-r--r--configure.in11
-rw-r--r--dln.c3
-rw-r--r--enc/big5.c4
-rw-r--r--enc/cp949.c4
-rw-r--r--enc/euc_jp.c4
-rw-r--r--enc/euc_kr.c4
-rw-r--r--enc/euc_tw.c4
-rw-r--r--enc/gb18030.c2
-rw-r--r--enc/gbk.c4
-rw-r--r--enc/shift_jis.c4
-rw-r--r--enc/utf_16be.c2
-rw-r--r--enc/utf_16le.c2
-rw-r--r--enc/utf_32be.c2
-rw-r--r--enc/utf_32le.c2
-rw-r--r--enc/utf_8.c2
-rw-r--r--encoding.c69
-rw-r--r--error.c4
-rw-r--r--eval.c3
-rw-r--r--ext/bigdecimal/bigdecimal.c31
-rw-r--r--ext/json/ext/generator/extconf.rb5
-rw-r--r--ext/json/ext/generator/generator.c13
-rw-r--r--ext/json/ext/generator/unicode.c2
-rw-r--r--ext/json/ext/parser/extconf.rb5
-rw-r--r--ext/json/ext/parser/parser.c631
-rw-r--r--ext/json/ext/parser/parser.rl62
-rw-r--r--ext/json/ext/parser/unicode.c4
-rw-r--r--ext/json/lib/json/add/core.rb41
-rw-r--r--ext/json/lib/json/common.rb10
-rw-r--r--ext/json/lib/json/editor.rb1
-rw-r--r--ext/json/lib/json/pure/parser.rb5
-rw-r--r--ext/json/lib/json/version.rb2
-rw-r--r--ext/nkf/nkf-utf8/nkf.c32
-rw-r--r--ext/openssl/ossl_pkey_ec.c11
-rw-r--r--ext/socket/getaddrinfo.c2
-rw-r--r--ext/socket/getnameinfo.c2
-rw-r--r--ext/socket/mkconstants.rb15
-rw-r--r--ext/socket/socket.c2
-rw-r--r--ext/win32ole/win32ole.c4
-rw-r--r--gc.c4
-rw-r--r--hash.c4
-rw-r--r--include/ruby/defines.h2
-rw-r--r--include/ruby/encoding.h10
-rw-r--r--include/ruby/oniguruma.h20
-rw-r--r--include/ruby/ruby.h5
-rw-r--r--inits.c2
-rw-r--r--io.c79
-rw-r--r--lib/cmath.rb66
-rw-r--r--lib/complex.rb18
-rw-r--r--lib/csv.rb706
-rw-r--r--lib/mathn.rb14
-rw-r--r--lib/matrix.rb20
-rw-r--r--lib/open-uri.rb12
-rw-r--r--lib/optparse.rb9
-rw-r--r--lib/pathname.rb10
-rw-r--r--lib/pp.rb54
-rw-r--r--lib/prettyprint.rb14
-rwxr-xr-xlib/rake.rb642
-rw-r--r--lib/rake/loaders/makefile.rb23
-rw-r--r--lib/rake/packagetask.rb1
-rw-r--r--lib/rake/rdoctask.rb14
-rw-r--r--lib/rake/tasklib.rb11
-rw-r--r--lib/rake/testtask.rb7
-rw-r--r--lib/resolv.rb40
-rw-r--r--lib/time.rb38
-rw-r--r--lib/tsort.rb20
-rw-r--r--lib/uri/common.rb2
-rw-r--r--load.c2
-rw-r--r--marshal.c2
-rw-r--r--math.c2
-rw-r--r--numeric.c82
-rw-r--r--object.c9
-rw-r--r--parse.y10
-rw-r--r--prec.c138
-rw-r--r--rational.c92
-rw-r--r--re.c40
-rw-r--r--regenc.c25
-rw-r--r--regenc.h2
-rw-r--r--regexec.c97
-rw-r--r--regparse.c2
-rw-r--r--ruby.c11
-rw-r--r--st.c7
-rw-r--r--string.c573
-rw-r--r--test/bigdecimal/test_bigdecimal.rb689
-rw-r--r--test/csv/tc_csv_parsing.rb32
-rw-r--r--test/csv/tc_csv_writing.rb3
-rw-r--r--test/csv/tc_data_converters.rb3
-rw-r--r--test/csv/tc_features.rb100
-rw-r--r--test/csv/tc_headers.rb29
-rw-r--r--test/csv/tc_interface.rb79
-rw-r--r--test/csv/tc_row.rb23
-rw-r--r--test/csv/tc_serialization.rb3
-rw-r--r--test/csv/tc_table.rb16
-rw-r--r--test/csv/ts_all.rb4
-rw-r--r--test/json/fixtures/fail18.json2
-rwxr-xr-xtest/json/runner.rb1
-rwxr-xr-xtest/json/test_json.rb64
-rwxr-xr-xtest/json/test_json_addition.rb38
-rw-r--r--test/json/test_json_generate.rb19
-rw-r--r--test/json/test_json_rails.rb11
-rwxr-xr-xtest/json/test_json_unicode.rb5
-rw-r--r--test/matrix/test_matrix.rb49
-rw-r--r--test/matrix/test_vector.rb49
-rw-r--r--test/ruby/test_complex.rb290
-rw-r--r--test/ruby/test_fixnum.rb9
-rw-r--r--test/ruby/test_float.rb7
-rw-r--r--test/ruby/test_integer.rb6
-rw-r--r--test/ruby/test_io.rb30
-rw-r--r--test/ruby/test_io_m17n.rb40
-rw-r--r--test/ruby/test_m17n.rb51
-rw-r--r--test/ruby/test_m17n_comb.rb87
-rw-r--r--test/ruby/test_math.rb1
-rw-r--r--test/ruby/test_mixed_unicode_escapes.rb6
-rw-r--r--test/ruby/test_numeric.rb4
-rw-r--r--test/ruby/test_prec.rb21
-rw-r--r--test/ruby/test_rational.rb97
-rw-r--r--test/ruby/test_transcode.rb178
-rw-r--r--transcode.c129
-rw-r--r--transcode_data.h14
-rw-r--r--version.h6
-rw-r--r--vm.c7
124 files changed, 5045 insertions, 2283 deletions
diff --git a/ChangeLog b/ChangeLog
index 0a36a94a8a..bc577b284e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,787 @@
+Sun Sep 21 21:52:41 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * math.c (math_log): should check argc.
+
+Sun Sep 21 21:20:24 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: added two macros.
+
+ * rational.c: ditto.
+
+Sun Sep 21 18:06:38 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_s_convert): checks argc.
+
+ * rational.c (nurat_s_convert): ditto.
+
+Sun Sep 21 10:19:04 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_s_canonicalize_internal): checks exactness of
+ imag only.
+
+ * rational.c (nurat_s_convert): accepts non real value
+ (Rational(a,b) as a/b).
+
+ * complex.c (nucomp_s_convert): refined.
+
+Sun Sep 21 09:37:57 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ * lib/csv/csv.rb: Reworked CSV's parser and generator to be m17n. Data
+ is now parsed in the Encoding it is in without need for translation.
+ * lib/csv/csv.rb: Improved inspect() messages for better IRb support.
+ * lib/csv/csv.rb: Fixed header writing bug reported by Dov Murik.
+ * lib/csv/csv.rb: Use custom separators in parsing header Strings as
+ suggested by Shmulik Regev.
+ * lib/csv/csv.rb: Added a :write_headers option for outputting headers.
+ * lib/csv/csv.rb: Handle open() calls in binary mode whenever we can to
+ workaround a Windows issue where line-ending translation can cause an
+ off-by-one error in seeking back to a non-zero starting position after
+ auto-discovery for :row_sep as suggested by Robert Battle.
+ * lib/csv/csv.rb: Improved the parser to fail faster when fed some forms
+ of invalid CSV that can be detected without reading ahead.
+ * lib/csv/csv.rb: Added a :field_size_limit option to control CSV's
+ lookahead and prevent the parser from biting off more data than
+ it can chew.
+ * lib/csv/csv.rb: Added readers for CSV attributes: col_sep(), row_sep(),
+ quote_char(), field_size_limit(), converters(), unconverted_fields?(),
+ headers(), return_headers?(), write_headers?(), header_converters(),
+ skip_blanks?(), and force_quotes?().
+ * lib/csv/csv.rb: Cleaned up code syntax to be more inline with
+ Ruby 1.9 than 1.8.
+
+Sun Sep 21 07:43:16 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: an instance method image has been removed and
+ uses "imag" instead of "image".
+
+ * complex.c: two instance method re and im are removed.
+
+ * rational.c: follows the above changes.
+
+ * include/ruby/ruby.h: ditto.
+
+ * gc.c: ditto.
+
+ * lib/cmath.rb: ditto.
+
+ * lib/mathn.rb: ditto.
+
+ * lib/complex.rb: ditto. and provides some obsolate methods.
+
+Sun Sep 21 02:48:45 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json/ext/parser/parse.c: use ruby_xfree().
+
+ * ext/json/ext/parser/parse.rl: ditto.
+
+ * ext/json/ext/parser/unicode.c: ditto.
+
+Sun Sep 21 02:40:20 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json: import JSON v 1.1.3.
+
+Sat Sep 20 11:43:08 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * lib/optparse.rb (summarize): separator "" should output new line.
+
+Sat Sep 20 08:07:34 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * parse.y: strings which contain only US-ASCII don't force to have
+ US-ASCII encoding. [ruby-dev:36400]
+
+Sat Sep 20 07:59:31 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * re.c (rb_reg_desc): Regexps of ASCII Compatible encoding may
+ contain non-ASCII characters. So in that case its encoding
+ must keep original encoding.
+
+Sat Sep 20 07:44:56 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * common.mk: prec.c is removed.
+
+Fri Sep 19 22:37:25 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: uses f_(in)?exact_p macro.
+
+ * rational.c: ditto.
+
+ * bignum.c (rb_big_pow): bignum**bignum - should calculate without
+ rational.
+
+ * lib/complex.rb: should override Math module at most once.
+
+ * lib/mathn.rb: requires 'cmath' directly.
+
+Fri Sep 19 20:48:06 2008 Yuki Sonoda <yugui@yugui.jp>
+
+ * prec.c: removed. Precision will be redesigned and be back again.
+ c.f. [ruby-dev:36352].
+
+ * common.mk (COMMON_OBJS): removed prec.o.
+
+ * inits.c (rb_call_inits): removed Init_Precision.
+
+ * numeric.c (Init_Numeric): removed inclusion of Precision.
+ removed #induced_from from each class.
+
+ * rational.c: ditto.
+
+ * ext/bigdecimal/bigdecimal.c: ditto.
+
+ * lib/rdoc/knwon_classes.rb: removed the entry for Precision.
+
+ * test/ruby/test_prec.rb: removed.
+
+ * test/ruby/test_integer.rb: removed tests for Precision.
+
+ * test/ruby/test_fixnum.rb: ditto.
+
+ * test/ruby/test_float.rb: ditto.
+
+ * test/ruby/test_rational.rb: ditto.
+
+ * test/ruby/test_complex.rb: ditto.
+
+ * test/bigdecimal/test_bigdecimal.rb: ditto.
+
+Fri Sep 19 19:43:40 2008 Yuki Sonoda <yugui@yugui.jp>
+
+ * common.mk : Reverts the changeset 18994.
+ Uses the official repository of rubyspec again.
+
+Fri Sep 19 17:41:56 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * configure.in: applied OS/2 support patch from Brendan Oakley
+ <gentux2@gmail.com> in [ruby-core:18707].
+
+Fri Sep 19 09:29:26 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dln.c: newer BeOS support. a patch from Pete Goodeve
+ <pete.goodeve at computer.org> in [ruby-core:18712].
+
+Fri Sep 19 03:41:25 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c: fix memory violation. mentioned by mame [ruby-dev:36373]
+
+Fri Sep 19 01:07:36 2008 Tanaka Akira <akr@fsij.org>
+
+ * regexec.c (string_cmp_ic): add text_end argument.
+ (slow_search): call enclen with real string end.
+ (map_search): add text_end argument.
+
+Thu Sep 18 22:54:39 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * ext/openssl/ossl_pkey_ec.c (ossl_ec_key_to_string): comment out
+ fragments of unused code.
+
+Thu Sep 18 22:35:03 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * ext/bigdecimal/bigdecimal.c (VpCtoV): 1E1000...000 is interpreted as
+ Infinity. [ruby-dev:36159]
+
+ * ext/bigdecimal/bigdecimal.c (VpPower): Infinity ** 1 returns
+ Infinity instead of NaN. [ruby-dev:36159]
+
+ * test/bigdecimal/test_bigdecimal.rb: add tests for above.
+
+Thu Sep 18 21:57:32 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_comparable): make ascii8bit string to be
+ compatible with any other encoding.
+
+ * string.c (rb_str_cmp): use rb_str_comparable() instead of
+ rb_enc_compatible() since <=> is a comparison anyway.
+
+Thu Sep 18 21:37:14 2008 Tanaka Akira <akr@fsij.org>
+
+ * grapheme cluster implementation reverted. [ruby-dev:36375]
+
+Thu Sep 18 20:50:36 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rake.rb (Rake::Application#standard_exception_handling):
+ replaced magic numbers for exit status.
+
+Thu Sep 18 20:37:59 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::ParseError#set_backtrace): omits
+ OptionParser internal backtraces unless debug flag is set.
+
+Thu Sep 18 20:02:48 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * lib/uri/common.rb (unescape): skip '%' to make String#hex work
+ correctly.
+
+Thu Sep 18 19:51:11 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (big2str_karatsuba): free internal buffer eagerly.
+ a patch from TOYOFUKU Chikanobu <nobu_toyofuku at nifty.com>
+ in [ruby-dev:36217].
+
+ * bignum.c (rb_big2str0): ditto.
+
+Thu Sep 18 19:43:04 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * st.c (new_size): raise RuntimeError when st_table is too big.
+ [ruby-dev:36354]
+
+Thu Sep 18 18:23:23 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (enc_arg): must take pointer argument to avoid GC
+ problem. StringValueCStr modifies the argument and it should be
+ preserved while the string StringValueCStr returns is used.
+ Since the string is used by caller, the modified argument should be
+ hold by caller. Actually
+ GC.stress = true
+ def (o=Object.new).to_str()
+ "universal"+"_newline"
+ end
+ "\u3042".encode(o, "")
+ causes curious warning:
+ rb_define_const: invalid name `' for constant
+
+Thu Sep 18 17:32:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * transcode.c: add "Error" suffix for Encoding exception classes.
+ a patch from Tadashi Saito <shiba at mail2.accsnet.ne.jp> in
+ [ruby-dev:36346].
+
+ * encoding.c (Init_Encoding): rename EncodingCompatibilityError to
+ Encoding::CompatibilityError. [ruby-dev:36366]
+
+Thu Sep 18 17:18:35 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * transcode.c (enc_arg): revert last change. too early exception
+ raising.
+
+ * transcode.c (enc_arg): need not to take pointer argument.
+
+Sun Sep 18 02:22:15 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/bigdecimal/test_bigdecimal.rb: add tests to achieve over 90%
+ test coverage of bigdecimal.
+
+Wed Sep 17 21:50:14 2008 Tanaka Akira <akr@fsij.org>
+
+ * string.c (rb_str_casecmp): don't use rb_enc_codepoint.
+
+Wed Sep 17 19:55:33 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_s_convert): accepts complex
+ value (Complex(a,b) as a+bi).
+
+Wed Sep 17 19:16:47 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/ruby/test_io.rb (TestIO#test_dup): avoid infinite loop.
+ [ruby-dev:36326]
+
+ * test/ruby/test_io.rb (TestIO#test_dup): remove needless open.
+ [ruby-dev:35957]
+
+Wed Sep 17 17:44:59 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_extract_modeenc): process option mode: and perm: as
+ well.
+
+ * io.c (open_key_args): move mode: and perm: related code to
+ rb_io_extract_modeenc().
+
+Wed Sep 17 13:42:59 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/html.rb (checkbox_group,radio_group): bug fix
+ use size instead of bytesize.
+
+ * test/cgi/test_cgi_tag_helper.rb: test for checkbox_group,radio_group.
+
+Wed Sep 17 06:58:31 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * numeric.c: provides predicate real? instead of scalar?.
+
+ * complex.c: follows the above change.
+
+ * lib/cmath.rb: ditto.
+
+Wed Sep 17 01:56:27 2008 Tanaka Akira <akr@fsij.org>
+
+ * test/ruby/test_io_m17n.rb: use __FILE__ instead of /dev/null.
+ [ruby-dev:36327]
+
+Wed Sep 17 01:33:11 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h (OnigEncodingTypeST): add precise_ret
+ argument for mbc_to_code.
+ (ONIGENC_MBC_TO_CODE): provide NULL for precise_ret.
+ (ONIGENC_MBC_PRECISE_CODEPOINT): defined.
+
+ * include/ruby/encoding.h (rb_enc_mbc_precise_codepoint): defined.
+
+ * regenc.h (onigenc_single_byte_mbc_to_code): precise_ret argument
+ added.
+ (onigenc_mbn_mbc_to_code): ditto.
+
+ * regenc.c (onigenc_single_byte_mbc_to_code): precise_ret argument
+ added.
+ (onigenc_mbn_mbc_to_code): ditto.
+
+ * string.c (count_utf8_lead_bytes_with_word): removed.
+ (str_utf8_nth): removed.
+ (str_utf8_offset): removed.
+ (str_strlen): UTF-8 codepoint oriented optimization removed.
+ (rb_str_substr): ditto.
+ (enc_succ_char): use rb_enc_mbc_precise_codepoint.
+ (enc_pred_char): ditto.
+ (rb_str_succ): ditto.
+
+ * encoding.c (rb_enc_ascget): check length with
+ rb_enc_mbc_precise_codepoint.
+ (rb_enc_codepoint): use rb_enc_mbc_precise_codepoint.
+
+ * regexec.c (string_cmp_ic): add text_end argument.
+ (match_at): check end of character after exact string matches.
+
+ * enc/utf_8.c (grapheme_table): defined for extended grapheme cluster
+ boundary.
+ (grapheme_cmp): defined.
+ (get_grapheme_properties): defined.
+ (grapheme_boundary_p): defined.
+ (MAX_BYTES_LENGTH): defined.
+ (comb_char_enc_len): defined.
+ (mbc_to_code0): extracted from mbc_to_code.
+ (mbc_to_code): use mbc_to_code0.
+ (left_adjust_combchar_head): defined.
+ (utf_8): use a extended grapheme cluster as a unit.
+
+ * enc/unicode.c (onigenc_unicode_mbc_case_fold): use
+ ONIGENC_MBC_PRECISE_CODEPOINT to extract codepoints.
+ (onigenc_unicode_get_case_fold_codes_by_str): ditto.
+
+ * enc/euc_jp.c (mbc_to_code): follow mbc_to_code field change.
+ use onigenc_mbn_mbc_to_code.
+
+ * enc/shift_jis.c (mbc_to_code): ditto.
+
+ * enc/emacs_mule.c (mbc_to_code): ditto.
+
+ * enc/gbk.c (gbk_mbc_to_code): follow mbc_to_code field and
+ onigenc_mbn_mbc_to_code change.
+
+ * enc/cp949.c (cp949_mbc_to_code): ditto.
+
+ * enc/big5.c (big5_mbc_to_code): ditto.
+
+ * enc/euc_tw.c (euctw_mbc_to_code): ditto.
+
+ * enc/euc_kr.c (euckr_mbc_to_code): ditto.
+
+ * enc/gb18030.c (gb18030_mbc_to_code): ditto.
+
+ * enc/utf_32be.c (utf32be_mbc_to_code): follow mbc_to_code field
+ change.
+
+ * enc/utf_16be.c (utf16be_mbc_to_code): ditto.
+
+ * enc/utf_32le.c (utf32le_mbc_to_code): ditto.
+
+ * enc/utf_16le.c (utf16le_mbc_to_code): ditto.
+
+Wed Sep 17 01:17:12 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * transcode.c (enc_arg): raise exception when unknown encoding is
+ given.
+
+Tue Sep 16 22:23:24 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/core.rb (CGI#header): performance improvement.
+ From CGIAlt http://cgialt.rubyforge.org/
+
+ * test/cgi/test_cgi_header.rb: exception class fixed.
+
+Tue Sep 16 22:21:33 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * string.c (rb_str_concat): fix rdoc. (codepoint is integer)
+
+ * string.c (rb_str_each_codepoint): use UINT2NUM.
+
+Tue Sep 16 21:48:55 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * re.c (rb_reg_desc): Regexp#inspect should be US-ASCII.
+
+Tue Sep 16 21:33:22 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_crypt): orthodox crypt() sees only first two bytes
+ of salt.
+
+Tue Sep 16 19:18:40 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_marshal_{dump,load}): preserve instance
+ variables.
+
+ * rational.c (nurat_marshal_{dump,load}): ditto.
+
+Tue Sep 16 18:28:52 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_gets_m): rdoc updated. limit counts in bytes.
+ [ruby-core:18617]
+
+ * io.c (rb_io_readlines, rb_f_gets): ditto.
+
+ * io.c (rb_io_readbyte): rdoc updated. [ruby-core:18617]
+
+Tue Sep 16 11:55:16 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_each_codepoint): add new methods, #codepoints
+ and #each_codepoint. a patch from Michael Selig
+ <michael.selig at fs.com.au> in [ruby-core:18532].
+
+Tue Sep 16 11:24:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/mkconstants.rb: add new constants. a patch from
+ IWAMURO Motonori <deenheart+ruby at gmail.com> in [ruby-dev:36309].
+
+Tue Sep 16 09:20:42 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/ruby/test_io.rb (TestIO#test_dup): exception should be
+ raised from IO#dup.
+
+Tue Sep 16 08:35:29 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/ruby/test_io.rb (TestIO#test_dup): this test might fail if
+ there are any garbage IO objects.
+
+Tue Sep 16 02:02:56 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * string.c (rb_str_buf_cat_ascii): codepoint is unsigned int.
+
+ * string.c (rb_str_concat): ditto.
+
+ * string.c (str_cat_char): ditto.
+
+ * string.c (prefix_escape): ditto.
+
+Tue Sep 16 01:47:07 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (single_byte_optimizable): make function inline. based
+ on a patch from Michael Selig <michael.selig at fs.com.au> in
+ [ruby-core:18532].
+
+ * string.c (str_modify_keep_cr): new function act as
+ rb_str_modify(), but don't clear coderange
+
+ * string.c (rb_str_casecmp): specialized for single byte strings.
+
+ * string.c (rb_str_splice): preserve coderange.
+
+ * string.c (rb_str_slice_bang, rb_str_reverse_bang,
+ rb_str_upcase_bang, rb_str_downcase_bang, tr_trans,
+ rb_str_capitalize_bang, rb_str_swapcase_bang,
+ rb_str_delete_bang, rb_str_chop_bang, rb_str_chomp_bang,
+ rb_str_lstrip_bang, rb_str_rstrip_bang): ditto.
+
+ * string.c (rb_str_clear): preset coderange.
+
+ * string.c (rb_str_split_m): specialized for splitting with a
+ string.
+
+Tue Sep 16 00:57:56 2008 Tanaka Akira <akr@fsij.org>
+
+ * re.c (rb_reg_quote): use rb_enc_mbcput to generate ASCII
+ incompatible characters properly.
+
+Tue Sep 16 00:51:59 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * encoding.c (Encoding#base_encoding): removed. [ruby-dev:36270]
+
+Tue Sep 16 00:40:56 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode_data.h (STR1_LENGTH): defined.
+ (makeSTR1LEN): defined.
+
+ * tool/transcode-tblgen.rb: use makeSTR1LEN. generate STR1 for 4 to
+ 259 bytes.
+
+ * transcode.c (rb_transcoding): new field: output_index.
+ (transcode_restartable0): use STR1_LENGTH.
+
+Mon Sep 15 23:52:45 2008 Koichi Sasada <ko1@atdot.net>
+
+ * gc.c, include/ruby/ruby.h: rename rb_register_mark_object()
+ to rb_gc_register_mark_object().
+
+ * eval.c, vm.c: initialize vm->mark_object_ary at
+ Init_top_self().
+
+ * bignum.c, complex.c, encoding.c, ext/win32ole/win32ole.c,
+ io.c, load.c, marshal.c, rational.c, ruby.c, vm.c:
+ use rb_gc_register_mark_object() instead of
+ rb_global_variable() or rb_gc_register_address().
+
+Mon Sep 15 23:37:15 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (econv_opts): don't use to_sym.
+
+Mon Sep 15 23:28:28 2008 Tanaka Akira <akr@fsij.org>
+
+ * encoding.c (rb_enc_get_index): don't return -1.
+
+ * io.c (rb_scan_open_args): call FilePathValue before encoding
+ conversion.
+
+Mon Sep 15 22:11:07 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_squeeze_bang): specialized for 7bit characters in
+ ASCII compatible strings.
+
+ * string.c (rb_str_count): ditto.
+
+ * string.c (tr_trans): preserve 7bit/valid coderange flag.
+
+ * string.c (rb_str_squeeze_bang): preserve previous coderange value.
+
+ * string.c (rb_str_lstrip_bang): ditto.
+
+ * string.c (rb_str_rstrip_bang): ditto.
+
+ * encoding.c (rb_default_external_encoding): preserve
+ default_external_encoding in a static variable.
+
+ * string.c (single_byte_optimizable): check coderange first, to
+ reduce number of calling rb_enc_from_index().
+
+Mon Sep 15 20:57:00 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * lib/matrix.rb (Matrix#eql?): fixed [ruby-dev:36298].
+ Reported by an anonymous user.
+
+ * lib/matrix.rb (Vector#eql?): ditto.
+
+ * (Matrix#compare_by_row_vectors): takes comparison
+ strategy as an optional parameter.
+
+ * (Vector#compare_by): ditto.
+
+Mon Sep 15 14:34:32 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * encoding.c (RUBY_MAX_CHAR_LEN): defined.
+
+ * encoding.c (str_cat_char): use RUBY_MAX_CHAR_LEN.
+
+Mon Sep 15 13:53:33 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * encoding.c (rb_enc_compatible): accept other than strings and
+ regexps. [ruby-core:18595]
+
+ * encoding.c (rb_enc_get_index): works files and encodings.
+
+Mon Sep 15 13:17:21 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_eql_p): new.
+
+ * complex.c (nucomp_hash): should use hash values of the elements.
+
+ * rational.c (nurat_hash): ditto.
+
+ * hash.c (rb_any_cmp): removed an unused variable.
+
+Mon Sep 15 11:11:04 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode_data.h (rb_transcoder): resetsize_func and resetstate_func
+ also returns ssize_t.
+
+ * enc/trans/iso2022.trans: follow the type change.
+
+Mon Sep 15 10:28:10 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * test/matrix/test_matrix.rb (setup): typo.
+ (test_equality): misdefinition of the expected working.
+ Reported by an anonymous user.
+ (test_hash): added.
+
+ * test/matrix/test_vector.rb: ditto.
+
+Mon Sep 15 03:33:10 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode_data.h: return output functions ssize_t.
+
+ * transcode.c (transcode_restartable0): don't need to cast the result
+ of output functions.
+
+ * enc/trans/newline.trans: follow the type change.
+
+ * enc/trans/escape.trans: ditto.
+
+ * enc/trans/utf_16_32.trans: ditto.
+
+ * enc/trans/iso2022.trans: ditto.
+
+ * enc/trans/japanese.trans: ditto.
+
+Mon Sep 15 03:04:29 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode_data.h: output function takes output buffer size.
+
+ * transcode.c: give output buffer size for output functions.
+
+ * enc/trans/newline.trans: follow the type change.
+
+ * enc/trans/escape.trans: ditto.
+
+ * enc/trans/utf_16_32.trans: ditto.
+
+ * enc/trans/iso2022.trans: ditto.
+
+ * enc/trans/japanese.trans: ditto.
+
+Mon Sep 15 02:37:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * transcode.c (str_encode): returns duplicated string if nothing
+ changed. [ruby-core:18578]
+
+Sun Sep 14 22:09:01 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/core.rb (CGI::parse): performance improvement
+
+Sun Sep 14 18:33:32 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: trivial changes.
+
+Sun Sep 14 16:15:22 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * lib/matrix.rb (Vector#eql?): typo of the method name as "eqn?".
+ (Vector#eqn?): removed. Defined by mistake.
+ Fixes [ruby-dev:36294]. Reported by weda <weda AT
+ issp.u-tokyo.ac.jp> and an anonymous user.
+
+ * test/matrix/test_matrix.rb: added.
+
+ * test/matrix/test_vector.rb: added.
+
+Sun Sep 14 16:07:04 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (process_options): associates the locale encoding with $0 as
+ well as ARGV.
+
+Sun Sep 14 13:48:03 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * object.c (Init_Object): added metameta-class initialization for
+ BasicObject, Object, and Module.
+ The metameta-classes of them are now the metaclass of Class, as the
+ metameta-class of Class is.
+
+ * object.c (boot_defmetametaclass): added.
+
+Sun Sep 14 10:10:43 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (f_{add,mul,sub}): omitted some shortcuts for preserving
+ signed zero anyway.
+
+ * complex.c (nucomp_negate): new.
+
+Sun Sep 14 04:15:16 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h (OnigEncodingTypeST): add end argument for
+ left_adjust_char_head.
+ (ONIGENC_LEFT_ADJUST_CHAR_HEAD): add end argument.
+ (onigenc_get_left_adjust_char_head): ditto.
+
+ * include/ruby/encoding.h (rb_enc_left_char_head): add end argument.
+
+ * regenc.h (onigenc_single_byte_left_adjust_char_head): ditto.
+
+ * regenc.c (onigenc_get_right_adjust_char_head): follow the interface
+ change.
+ (onigenc_get_right_adjust_char_head_with_prev): ditto.
+ (onigenc_get_prev_char_head): ditto.
+ (onigenc_step_back): ditto.
+ (onigenc_get_left_adjust_char_head): ditto.
+ (onigenc_single_byte_code_to_mbc): ditto.
+
+ * re.c: ditto.
+
+ * string.c: ditto.
+
+ * io.c: ditto.
+
+ * regexec.c: ditto.
+
+ * enc/euc_jp.c: ditto.
+
+ * enc/cp949.c: ditto.
+
+ * enc/shift_jis.c: ditto.
+
+ * enc/gbk.c: ditto.
+
+ * enc/big5.c: ditto.
+
+ * enc/euc_tw.c: ditto.
+
+ * enc/euc_kr.c: ditto.
+
+ * enc/emacs_mule.c: ditto.
+
+ * enc/gb18030.c: ditto.
+
+ * enc/utf_8.c: ditto.
+
+ * enc/utf_16le.c: ditto.
+
+ * enc/utf_16be.c: ditto.
+
+ * enc/utf_32le.c: ditto.
+
+ * enc/utf_32be.c: ditto.
+
+Sun Sep 14 03:43:27 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h (ONIGENC_STEP_BACK): add end argument.
+ (onigenc_step_back): ditto.
+
+ * regenc.c (onigenc_step_back): add end argument.
+
+ * regexec.c: follow the interface change.
+
+Sun Sep 14 03:20:03 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h (onigenc_get_prev_char_head): add end
+ argument.
+
+ * include/ruby/encoding.h (rb_enc_prev_char): ditto.
+
+ * regenc.c (onigenc_get_prev_char_head): add end argument.
+
+ * regparse.c: follow the interface change.
+
+ * regexec.c: ditto.
+
+ * string.c: ditto.
+
+ * parse.y: ditto.
+
+Sun Sep 14 02:04:28 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h
+ (onigenc_get_right_adjust_char_head_with_prev): add end argument.
+
+ * regenc.c (onigenc_get_right_adjust_char_head_with_prev): use end
+ argument.
+
+ * regexec.c (forward_search_range): follow the interface change.
+
+Sun Sep 14 01:38:26 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h (onigenc_get_right_adjust_char_head): add
+ end argument.
+
+ * include/ruby/encoding.h (rb_enc_right_char_head): add end argument.
+
+ * regenc.c (onigenc_get_right_adjust_char_head): use end argument.
+
+ * re.c (rb_reg_adjust_startpos): follow the interface change.
+
+ * string.c (rb_str_index): ditto.
+
+ * regexec.c (backward_search_range): ditto.
+ (onig_search): ditto.
+
Sun Sep 14 00:43:28 2008 Tanaka Akira <akr@fsij.org>
* ext/ripper/depend (ripper.o): it depends on ruby headers.
@@ -962,7 +1746,8 @@ Thu Sep 4 19:10:27 2008 Tanaka Akira <akr@fsij.org>
* include/ruby/encoding.h (ECONV_INVALID_IGNORE): removed because
it tend to cause security problem. If the behaviour is really
required, ECONV_INVALID_REPLACE with empty string can be used.
- For example, CVE-2006-2313, CVE-2008-1036, [ruby-core:15645]
+ For example, CVE-2006-2313, CVE-2008-1036, [ruby-core:15645],
+ http://unicode.org/reports/tr36/
(ECONV_UNDEF_IGNORE): ditto.
* transcode.c (rb_econv_convert): follow the above change.
diff --git a/bignum.c b/bignum.c
index a3f8d25a61..35db091454 100644
--- a/bignum.c
+++ b/bignum.c
@@ -774,7 +774,7 @@ power_cache_get_power0(int base, int i)
big2str_power_cache[base - 2][i] =
i == 0 ? rb_big_pow(rb_int2big(base), INT2FIX(KARATSUBA_DIGITS))
: bigsqr(power_cache_get_power0(base, i - 1));
- rb_global_variable(&big2str_power_cache[base - 2][i]);
+ rb_gc_register_mark_object(big2str_power_cache[base - 2][i]);
}
return big2str_power_cache[base - 2][i];
}
@@ -909,8 +909,10 @@ big2str_karatsuba(VALUE x, int base, char* ptr,
bigdivmod(x, b, &q, &r);
lh = big2str_karatsuba(q, base, ptr, (len - m1)/2,
len - m1, hbase, trim);
+ rb_big_resize(q, 0);
ll = big2str_karatsuba(r, base, ptr + lh, m1/2,
m1, hbase, !lh && trim);
+ rb_big_resize(r, 0);
return lh + ll;
}
@@ -953,6 +955,7 @@ rb_big2str0(VALUE x, int base, int trim)
len = off + big2str_karatsuba(xx, base, ptr + off, n1,
n2, hbase, trim);
}
+ rb_big_resize(xx, 0);
ptr[len] = '\0';
rb_str_resize(ss, len);
@@ -2099,9 +2102,6 @@ rb_big_pow(VALUE x, VALUE y)
break;
case T_BIGNUM:
- if (rb_funcall(y, '<', 1, INT2FIX(0)))
- return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
-
rb_warn("in a**b, b may be too big");
d = rb_big2dbl(y);
break;
@@ -2110,7 +2110,7 @@ rb_big_pow(VALUE x, VALUE y)
yy = FIX2LONG(y);
if (yy < 0)
- return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
+ return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
else {
VALUE z = 0;
SIGNED_VALUE mask;
diff --git a/common.mk b/common.mk
index ddf4815407..81653aec51 100644
--- a/common.mk
+++ b/common.mk
@@ -9,7 +9,7 @@ RUBYOPT = -
SPEC_GIT_BASE = git://github.com/rubyspec
MSPEC_GIT_URL = $(SPEC_GIT_BASE)/mspec.git
-RUBYSPEC_GIT_URL = git://github.com/yugui/rubyspec.git
+RUBYSPEC_GIT_URL = $(SPEC_GIT_BASE)/rubyspec.git
STATIC_RUBY = static-ruby
@@ -49,7 +49,6 @@ COMMONOBJS = array.$(OBJEXT) \
pack.$(OBJEXT) \
parse.$(OBJEXT) \
process.$(OBJEXT) \
- prec.$(OBJEXT) \
random.$(OBJEXT) \
range.$(OBJEXT) \
rational.$(OBJEXT) \
@@ -520,7 +519,6 @@ parse.$(OBJEXT): {$(VPATH)}parse.c {$(VPATH)}parse.y $(RUBY_H_INCLUDES) \
{$(VPATH)}oniguruma.h $(ID_H_INCLUDES) {$(VPATH)}regenc.h \
{$(VPATH)}regex.h {$(VPATH)}util.h {$(VPATH)}lex.c {$(VPATH)}keywords \
{$(VPATH)}debug.h {$(VPATH)}id.c
-prec.$(OBJEXT): {$(VPATH)}prec.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
proc.$(OBJEXT): {$(VPATH)}proc.c {$(VPATH)}eval_intern.h \
$(RUBY_H_INCLUDES) {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}util.h \
{$(VPATH)}vm_core.h {$(VPATH)}debug.h \
diff --git a/complex.c b/complex.c
index 4d7dc2901c..78593bd155 100644
--- a/complex.c
+++ b/complex.c
@@ -21,11 +21,10 @@
VALUE rb_cComplex;
-static ID id_Unify, id_abs, id_abs2, id_arg, id_cmp, id_conjugate,
- id_convert, id_denominator, id_divmod, id_equal_p, id_exact_p, id_expt,
- id_floor, id_format, id_idiv, id_inspect, id_negate, id_new, id_new_bang,
- id_numerator, id_polar, id_quo, id_scalar_p, id_to_f, id_to_i, id_to_r,
- id_to_s, id_truncate;
+static ID id_Unify, id_abs, id_abs2, id_arg, id_cmp, id_conj, id_convert,
+ id_denominator, id_divmod, id_equal_p, id_expt, id_floor, id_hash,
+ id_idiv, id_inspect, id_negate, id_numerator, id_polar, id_quo,
+ id_real_p, id_to_f, id_to_i, id_to_r, id_to_s;
#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
@@ -64,13 +63,17 @@ m_##n(VALUE x, VALUE y)\
return rb_funcall(rb_mMath, id_##n, 2, x, y);\
}
+#define PRESERVE_SIGNEDZERO
+
inline static VALUE
f_add(VALUE x, VALUE y)
{
+#ifndef PRESERVE_SIGNEDZERO
if (FIXNUM_P(y) && FIX2LONG(y) == 0)
return x;
else if (FIXNUM_P(x) && FIX2LONG(x) == 0)
return y;
+#endif
return rb_funcall(x, '+', 1, y);
}
@@ -117,6 +120,7 @@ binop(mod, '%')
inline static VALUE
f_mul(VALUE x, VALUE y)
{
+#ifndef PRESERVE_SIGNEDZERO
if (FIXNUM_P(y)) {
long iy = FIX2LONG(y);
if (iy == 0) {
@@ -135,14 +139,17 @@ f_mul(VALUE x, VALUE y)
else if (ix == 1)
return y;
}
+#endif
return rb_funcall(x, '*', 1, y);
}
inline static VALUE
f_sub(VALUE x, VALUE y)
{
+#ifndef PRESERVE_SIGNEDZERO
if (FIXNUM_P(y) && FIX2LONG(y) == 0)
return x;
+#endif
return rb_funcall(x, '-', 1, y);
}
@@ -151,23 +158,20 @@ binop(xor, '^')
fun1(abs)
fun1(abs2)
fun1(arg)
-fun1(conjugate)
+fun1(conj)
fun1(denominator)
-fun1(exact_p)
fun1(floor)
+fun1(hash)
fun1(inspect)
fun1(negate)
fun1(numerator)
fun1(polar)
-fun1(scalar_p)
-
-#define f_real_p f_scalar_p
+fun1(real_p)
fun1(to_f)
fun1(to_i)
fun1(to_r)
fun1(to_s)
-fun1(truncate)
fun2(divmod)
@@ -191,6 +195,8 @@ f_negative_p(VALUE x)
return rb_funcall(x, '<', 1, ZERO);
}
+#define f_positive_p(x) (!f_negative_p(x))
+
inline static VALUE
f_zero_p(VALUE x)
{
@@ -199,6 +205,8 @@ f_zero_p(VALUE x)
return rb_funcall(x, id_equal_p, 1, ZERO);
}
+#define f_nonzero_p(x) (!f_zero_p(x))
+
inline static VALUE
f_one_p(VALUE x)
{
@@ -243,6 +251,9 @@ k_complex_p(VALUE x)
return f_kind_of_p(x, rb_cComplex);
}
+#define k_exact_p(x) (!k_float_p(x))
+#define k_inexact_p(x) k_float_p(x)
+
#define get_dat1(x) \
struct RComplex *dat;\
dat = ((struct RComplex *)(x))
@@ -253,13 +264,13 @@ k_complex_p(VALUE x)
bdat = ((struct RComplex *)(y))
inline static VALUE
-nucomp_s_new_internal(VALUE klass, VALUE real, VALUE image)
+nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
{
NEWOBJ(obj, struct RComplex);
OBJSETUP(obj, klass, T_COMPLEX);
obj->real = real;
- obj->image = image;
+ obj->imag = imag;
return (VALUE)obj;
}
@@ -273,23 +284,23 @@ nucomp_s_alloc(VALUE klass)
static VALUE
nucomp_s_new_bang(int argc, VALUE *argv, VALUE klass)
{
- VALUE real, image;
+ VALUE real, imag;
- switch (rb_scan_args(argc, argv, "11", &real, &image)) {
+ switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
case 1:
if (!k_numeric_p(real))
real = f_to_i(real);
- image = ZERO;
+ imag = ZERO;
break;
default:
if (!k_numeric_p(real))
real = f_to_i(real);
- if (!k_numeric_p(image))
- image = f_to_i(image);
+ if (!k_numeric_p(imag))
+ imag = f_to_i(imag);
break;
}
- return nucomp_s_new_internal(klass, real, image);
+ return nucomp_s_new_internal(klass, real, imag);
}
inline static VALUE
@@ -325,39 +336,38 @@ nucomp_real_check(VALUE num)
}
inline static VALUE
-nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE image)
+nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
{
#define CL_CANON
#ifdef CL_CANON
- if (f_zero_p(image) && f_unify_p(klass) &&
- !k_float_p(real) && !k_float_p(image))
+ if (f_zero_p(imag) && k_exact_p(imag) && f_unify_p(klass))
return real;
#else
- if (f_zero_p(image) && f_unify_p(klass))
+ if (f_zero_p(imag) && f_unify_p(klass))
return real;
#endif
- else if (f_real_p(real) && f_real_p(image))
- return nucomp_s_new_internal(klass, real, image);
+ else if (f_real_p(real) && f_real_p(imag))
+ return nucomp_s_new_internal(klass, real, imag);
else if (f_real_p(real)) {
- get_dat1(image);
+ get_dat1(imag);
return nucomp_s_new_internal(klass,
- f_sub(real, dat->image),
+ f_sub(real, dat->imag),
f_add(ZERO, dat->real));
}
- else if (f_real_p(image)) {
+ else if (f_real_p(imag)) {
get_dat1(real);
return nucomp_s_new_internal(klass,
dat->real,
- f_add(dat->image, image));
+ f_add(dat->imag, imag));
}
else {
- get_dat2(real, image);
+ get_dat2(real, imag);
return nucomp_s_new_internal(klass,
- f_sub(adat->real, bdat->image),
- f_add(adat->image, bdat->real));
+ f_sub(adat->real, bdat->imag),
+ f_add(adat->imag, bdat->real));
}
}
@@ -365,36 +375,40 @@ nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE image)
static VALUE
nucomp_s_canonicalize(int argc, VALUE *argv, VALUE klass)
{
- VALUE real, image;
+ VALUE real, imag;
- switch (rb_scan_args(argc, argv, "11", &real, &image)) {
+ switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
case 1:
- image = ZERO;
+ nucomp_real_check(real);
+ imag = ZERO;
+ break;
+ default:
+ nucomp_real_check(real);
+ nucomp_real_check(imag);
break;
}
- nucomp_real_check(real);
- nucomp_real_check(image);
-
- return nucomp_s_canonicalize_internal(klass, real, image);
+ return nucomp_s_canonicalize_internal(klass, real, imag);
}
#endif
static VALUE
nucomp_s_new(int argc, VALUE *argv, VALUE klass)
{
- VALUE real, image;
+ VALUE real, imag;
- switch (rb_scan_args(argc, argv, "11", &real, &image)) {
+ switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
case 1:
- image = ZERO;
+ nucomp_real_check(real);
+ imag = ZERO;
+ break;
+ default:
+ nucomp_real_check(real);
+ nucomp_real_check(imag);
break;
}
- nucomp_real_check(real);
- nucomp_real_check(image);
-
- return nucomp_s_canonicalize_internal(klass, real, image);
+ return nucomp_s_canonicalize_internal(klass, real, imag);
}
inline static VALUE
@@ -446,44 +460,46 @@ m_log_bang(VALUE x)
static VALUE
m_cos(VALUE x)
{
- get_dat1(x);
-
if (f_real_p(x))
return m_cos_bang(x);
- return f_complex_new2(rb_cComplex,
- f_mul(m_cos_bang(dat->real),
- m_cosh_bang(dat->image)),
- f_mul(f_negate(m_sin_bang(dat->real)),
- m_sinh_bang(dat->image)));
+ {
+ get_dat1(x);
+ return f_complex_new2(rb_cComplex,
+ f_mul(m_cos_bang(dat->real),
+ m_cosh_bang(dat->imag)),
+ f_mul(f_negate(m_sin_bang(dat->real)),
+ m_sinh_bang(dat->imag)));
+ }
}
static VALUE
m_sin(VALUE x)
{
- get_dat1(x);
-
if (f_real_p(x))
return m_sin_bang(x);
- return f_complex_new2(rb_cComplex,
- f_mul(m_sin_bang(dat->real),
- m_cosh_bang(dat->image)),
- f_mul(m_cos_bang(dat->real),
- m_sinh_bang(dat->image)));
+ {
+ get_dat1(x);
+ return f_complex_new2(rb_cComplex,
+ f_mul(m_sin_bang(dat->real),
+ m_cosh_bang(dat->imag)),
+ f_mul(m_cos_bang(dat->real),
+ m_sinh_bang(dat->imag)));
+ }
}
static VALUE
m_sqrt(VALUE x)
{
if (f_real_p(x)) {
- if (!f_negative_p(x))
+ if (f_positive_p(x))
return m_sqrt_bang(x);
return f_complex_new2(rb_cComplex, ZERO, m_sqrt_bang(f_negate(x)));
}
else {
get_dat1(x);
- if (f_negative_p(dat->image))
- return f_conjugate(m_sqrt(f_conjugate(x)));
+ if (f_negative_p(dat->imag))
+ return f_conj(m_sqrt(f_conj(x)));
else {
VALUE a = f_abs(x);
return f_complex_new2(rb_cComplex,
@@ -517,30 +533,38 @@ nucomp_real(VALUE self)
}
static VALUE
-nucomp_image(VALUE self)
+nucomp_imag(VALUE self)
{
get_dat1(self);
- return dat->image;
+ return dat->imag;
+}
+
+static VALUE
+nucomp_negate(VALUE self)
+{
+ get_dat1(self);
+ return f_complex_new2(CLASS_OF(self),
+ f_negate(dat->real), f_negate(dat->imag));
}
static VALUE
nucomp_add(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
- VALUE real, image;
+ VALUE real, imag;
get_dat2(self, other);
real = f_add(adat->real, bdat->real);
- image = f_add(adat->image, bdat->image);
+ imag = f_add(adat->imag, bdat->imag);
- return f_complex_new2(CLASS_OF(self), real, image);
+ return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
- f_add(dat->real, other), dat->image);
+ f_add(dat->real, other), dat->imag);
}
return rb_num_coerce_bin(self, other, '+');
}
@@ -549,20 +573,20 @@ static VALUE
nucomp_sub(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
- VALUE real, image;
+ VALUE real, imag;
get_dat2(self, other);
real = f_sub(adat->real, bdat->real);
- image = f_sub(adat->image, bdat->image);
+ imag = f_sub(adat->imag, bdat->imag);
- return f_complex_new2(CLASS_OF(self), real, image);
+ return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
- f_sub(dat->real, other), dat->image);
+ f_sub(dat->real, other), dat->imag);
}
return rb_num_coerce_bin(self, other, '-');
}
@@ -571,23 +595,23 @@ static VALUE
nucomp_mul(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
- VALUE real, image;
+ VALUE real, imag;
get_dat2(self, other);
real = f_sub(f_mul(adat->real, bdat->real),
- f_mul(adat->image, bdat->image));
- image = f_add(f_mul(adat->real, bdat->image),
- f_mul(adat->image, bdat->real));
+ f_mul(adat->imag, bdat->imag));
+ imag = f_add(f_mul(adat->real, bdat->imag),
+ f_mul(adat->imag, bdat->real));
- return f_complex_new2(CLASS_OF(self), real, image);
+ return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
f_mul(dat->real, other),
- f_mul(dat->image, other));
+ f_mul(dat->imag, other));
}
return rb_num_coerce_bin(self, other, '*');
}
@@ -601,23 +625,23 @@ nucomp_div(VALUE self, VALUE other)
get_dat2(self, other);
if (TYPE(adat->real) == T_FLOAT ||
- TYPE(adat->image) == T_FLOAT ||
+ TYPE(adat->imag) == T_FLOAT ||
TYPE(bdat->real) == T_FLOAT ||
- TYPE(bdat->image) == T_FLOAT) {
- VALUE magn = m_hypot(bdat->real, bdat->image);
+ TYPE(bdat->imag) == T_FLOAT) {
+ VALUE magn = m_hypot(bdat->real, bdat->imag);
VALUE tmp = f_complex_new_bang2(CLASS_OF(self),
f_div(bdat->real, magn),
- f_div(bdat->image, magn));
- return f_div(f_mul(self, f_conjugate(tmp)), magn);
+ f_div(bdat->imag, magn));
+ return f_div(f_mul(self, f_conj(tmp)), magn);
}
- return f_div(f_mul(self, f_conjugate(other)), f_abs2(other));
+ return f_div(f_mul(self, f_conj(other)), f_abs2(other));
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
f_div(dat->real, other),
- f_div(dat->image, other));
+ f_div(dat->imag, other));
}
return rb_num_coerce_bin(self, other, '/');
}
@@ -632,13 +656,13 @@ nucomp_fdiv(VALUE self, VALUE other)
return f_div(f_complex_new2(CLASS_OF(self),
f_to_f(dat->real),
- f_to_f(dat->image)), other);
+ f_to_f(dat->imag)), other);
}
static VALUE
nucomp_expt(VALUE self, VALUE other)
{
- if (f_zero_p(other))
+ if (k_exact_p(other) && f_zero_p(other))
return f_complex_new_bang1(CLASS_OF(self), ONE);
if (k_rational_p(other) && f_one_p(f_denominator(other)))
@@ -654,7 +678,7 @@ nucomp_expt(VALUE self, VALUE other)
theta = RARRAY_PTR(a)[1];
ore = dat->real;
- oim = dat->image;
+ oim = dat->imag;
nr = m_exp_bang(f_sub(f_mul(ore, m_log_bang(r)),
f_mul(oim, theta)));
ntheta = f_add(f_mul(theta, ore), f_mul(oim, m_log_bang(r)));
@@ -668,7 +692,7 @@ nucomp_expt(VALUE self, VALUE other)
z = x;
n = f_sub(other, ONE);
- while (!f_zero_p(n)) {
+ while (f_nonzero_p(n)) {
VALUE a;
while (a = f_divmod(n, TWO),
@@ -677,8 +701,8 @@ nucomp_expt(VALUE self, VALUE other)
x = f_complex_new2(CLASS_OF(self),
f_sub(f_mul(dat->real, dat->real),
- f_mul(dat->image, dat->image)),
- f_mul(f_mul(TWO, dat->real), dat->image));
+ f_mul(dat->imag, dat->imag)),
+ f_mul(f_mul(TWO, dat->real), dat->imag));
n = RARRAY_PTR(a)[0];
}
z = f_mul(z, x);
@@ -707,12 +731,12 @@ nucomp_equal_p(VALUE self, VALUE other)
get_dat2(self, other);
return f_boolcast(f_equal_p(adat->real, bdat->real) &&
- f_equal_p(adat->image, bdat->image));
+ f_equal_p(adat->imag, bdat->imag));
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
- return f_boolcast(f_equal_p(dat->real, other) && f_zero_p(dat->image));
+ return f_boolcast(f_equal_p(dat->real, other) && f_zero_p(dat->imag));
}
return f_equal_p(other, self);
}
@@ -732,7 +756,7 @@ static VALUE
nucomp_abs(VALUE self)
{
get_dat1(self);
- return m_hypot(dat->real, dat->image);
+ return m_hypot(dat->real, dat->imag);
}
static VALUE
@@ -740,21 +764,21 @@ nucomp_abs2(VALUE self)
{
get_dat1(self);
return f_add(f_mul(dat->real, dat->real),
- f_mul(dat->image, dat->image));
+ f_mul(dat->imag, dat->imag));
}
static VALUE
nucomp_arg(VALUE self)
{
get_dat1(self);
- return m_atan2_bang(dat->image, dat->real);
+ return m_atan2_bang(dat->imag, dat->real);
}
static VALUE
nucomp_rect(VALUE self)
{
get_dat1(self);
- return rb_assoc_new(dat->real, dat->image);
+ return rb_assoc_new(dat->real, dat->imag);
}
static VALUE
@@ -764,10 +788,10 @@ nucomp_polar(VALUE self)
}
static VALUE
-nucomp_conjugate(VALUE self)
+nucomp_conj(VALUE self)
{
get_dat1(self);
- return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->image));
+ return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
#if 0
@@ -789,7 +813,7 @@ static VALUE
nucomp_exact_p(VALUE self)
{
get_dat1(self);
- return f_boolcast(f_exact_p(dat->real) && f_exact_p(dat->image));
+ return f_boolcast(f_exact_p(dat->real) && f_exact_p(dat->imag));
}
static VALUE
@@ -805,7 +829,7 @@ static VALUE
nucomp_denominator(VALUE self)
{
get_dat1(self);
- return rb_lcm(f_denominator(dat->real), f_denominator(dat->image));
+ return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
}
static VALUE
@@ -819,15 +843,29 @@ nucomp_numerator(VALUE self)
return f_complex_new2(CLASS_OF(self),
f_mul(f_numerator(dat->real),
f_div(cd, f_denominator(dat->real))),
- f_mul(f_numerator(dat->image),
- f_div(cd, f_denominator(dat->image))));
+ f_mul(f_numerator(dat->imag),
+ f_div(cd, f_denominator(dat->imag))));
}
static VALUE
nucomp_hash(VALUE self)
{
get_dat1(self);
- return f_xor(dat->real, dat->image);
+ return f_xor(f_hash(dat->real), f_hash(dat->imag));
+}
+
+static VALUE
+nucomp_eql_p(VALUE self, VALUE other)
+{
+ if (k_complex_p(other)) {
+ get_dat2(self, other);
+
+ return f_boolcast((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) &&
+ (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) &&
+ f_equal_p(self, other));
+
+ }
+ return Qfalse;
}
#ifndef HAVE_SIGNBIT
@@ -869,12 +907,12 @@ nucomp_to_s(VALUE self)
get_dat1(self);
- impos = f_tpositive_p(dat->image);
+ impos = f_tpositive_p(dat->imag);
s = f_to_s(dat->real);
rb_str_cat2(s, !impos ? "-" : "+");
- rb_str_concat(s, f_to_s(f_abs(dat->image)));
+ rb_str_concat(s, f_to_s(f_abs(dat->imag)));
rb_str_cat2(s, "i");
return s;
@@ -887,13 +925,13 @@ nucomp_inspect(VALUE self)
get_dat1(self);
- impos = f_tpositive_p(dat->image);
+ impos = f_tpositive_p(dat->imag);
s = rb_str_new2("(");
rb_str_concat(s, f_inspect(dat->real));
rb_str_cat2(s, !impos ? "-" : "+");
- rb_str_concat(s, f_inspect(f_abs(dat->image)));
+ rb_str_concat(s, f_inspect(f_abs(dat->imag)));
rb_str_cat2(s, "i)");
return s;
@@ -902,8 +940,12 @@ nucomp_inspect(VALUE self)
static VALUE
nucomp_marshal_dump(VALUE self)
{
+ VALUE a;
get_dat1(self);
- return rb_assoc_new(dat->real, dat->image);
+
+ a = rb_assoc_new(dat->real, dat->imag);
+ rb_copy_generic_ivar(a, self);
+ return a;
}
static VALUE
@@ -911,7 +953,8 @@ nucomp_marshal_load(VALUE self, VALUE a)
{
get_dat1(self);
dat->real = RARRAY_PTR(a)[0];
- dat->image = RARRAY_PTR(a)[1];
+ dat->imag = RARRAY_PTR(a)[1];
+ rb_copy_generic_ivar(self, a);
return self;
}
@@ -951,7 +994,7 @@ nucomp_to_i(VALUE self)
{
get_dat1(self);
- if (k_float_p(dat->image) || !f_zero_p(dat->image)) {
+ if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
VALUE s = f_to_s(self);
rb_raise(rb_eRangeError, "can't convert %s into Integer",
StringValuePtr(s));
@@ -964,7 +1007,7 @@ nucomp_to_f(VALUE self)
{
get_dat1(self);
- if (k_float_p(dat->image) || !f_zero_p(dat->image)) {
+ if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
VALUE s = f_to_s(self);
rb_raise(rb_eRangeError, "can't convert %s into Float",
StringValuePtr(s));
@@ -977,7 +1020,7 @@ nucomp_to_r(VALUE self)
{
get_dat1(self);
- if (k_float_p(dat->image) || !f_zero_p(dat->image)) {
+ if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
VALUE s = f_to_s(self);
rb_raise(rb_eRangeError, "can't convert %s into Rational",
StringValuePtr(s));
@@ -1021,29 +1064,29 @@ make_patterns(void)
if (comp_pat0) return;
comp_pat0 = rb_reg_new(comp_pat0_source, sizeof comp_pat0_source - 1, 0);
- rb_global_variable(&comp_pat0);
+ rb_gc_register_mark_object(comp_pat0);
comp_pat1 = rb_reg_new(comp_pat1_source, sizeof comp_pat1_source - 1, 0);
- rb_global_variable(&comp_pat1);
+ rb_gc_register_mark_object(comp_pat1);
comp_pat2 = rb_reg_new(comp_pat2_source, sizeof comp_pat2_source - 1, 0);
- rb_global_variable(&comp_pat2);
+ rb_gc_register_mark_object(comp_pat2);
a_slash = rb_str_new2("/");
- rb_global_variable(&a_slash);
+ rb_gc_register_mark_object(a_slash);
a_dot_and_an_e = rb_str_new2(".eE");
- rb_global_variable(&a_dot_and_an_e);
+ rb_gc_register_mark_object(a_dot_and_an_e);
null_string = rb_str_new2("");
- rb_global_variable(&null_string);
+ rb_gc_register_mark_object(null_string);
underscores_pat = rb_reg_new(underscores_pat_source,
sizeof underscores_pat_source - 1, 0);
- rb_global_variable(&underscores_pat);
+ rb_gc_register_mark_object(underscores_pat);
an_underscore = rb_str_new2("_");
- rb_global_variable(&an_underscore);
+ rb_gc_register_mark_object(an_underscore);
}
#define id_match rb_intern("match")
@@ -1109,9 +1152,8 @@ string_to_c_internal(VALUE self)
}
if (NIL_P(m)) {
m = f_match(comp_pat2, s);
- if (NIL_P(m)) {
+ if (NIL_P(m))
return rb_assoc_new(Qnil, self);
- }
sr = f_aref(m, INT2FIX(1));
if (NIL_P(f_aref(m, INT2FIX(2))))
si = Qnil;
@@ -1149,7 +1191,6 @@ string_to_c_internal(VALUE self)
return rb_assoc_new(rb_complex_polar(r, i), re);
else
return rb_assoc_new(rb_complex_new2(r, i), re);
-
}
}
@@ -1191,7 +1232,7 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
{
VALUE a1, a2, backref;
- rb_scan_args(argc, argv, "02", &a1, &a2);
+ rb_scan_args(argc, argv, "11", &a1, &a2);
backref = rb_backref_get();
rb_match_busy(backref);
@@ -1223,7 +1264,7 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
{
get_dat1(a1);
- if (!k_float_p(dat->image) && f_zero_p(dat->image))
+ if (k_exact_p(dat->imag) && f_zero_p(dat->imag))
a1 = dat->real;
}
}
@@ -1233,17 +1274,29 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
{
get_dat1(a2);
- if (!k_float_p(dat->image) && f_zero_p(dat->image))
+ if (k_exact_p(dat->imag) && f_zero_p(dat->imag))
a2 = dat->real;
}
}
switch (TYPE(a1)) {
case T_COMPLEX:
- if (NIL_P(a2) || f_zero_p(a2))
+ if (argc == 1 || (k_exact_p(a2) && f_zero_p(a2)))
return a1;
}
+ if (argc == 1) {
+ if (k_numeric_p(a1) && !f_real_p(a1))
+ return a1;
+ }
+ else {
+ if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
+ (!f_real_p(a1) || !f_real_p(a2)))
+ return f_add(a1,
+ f_mul(a2,
+ f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
+ }
+
{
VALUE argv2[2];
argv2[0] = a1;
@@ -1254,20 +1307,6 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
/* --- */
-#define id_Complex rb_intern("Complex")
-
-static VALUE
-numeric_re(VALUE self)
-{
- return rb_Complex1(self);
-}
-
-static VALUE
-numeric_im(VALUE self)
-{
- return rb_Complex2(ZERO, self);
-}
-
static VALUE
numeric_real(VALUE self)
{
@@ -1275,7 +1314,7 @@ numeric_real(VALUE self)
}
static VALUE
-numeric_image(VALUE self)
+numeric_imag(VALUE self)
{
return INT2FIX(0);
}
@@ -1291,7 +1330,7 @@ numeric_abs2(VALUE self)
static VALUE
numeric_arg(VALUE self)
{
- if (!f_negative_p(self))
+ if (f_positive_p(self))
return INT2FIX(0);
return rb_const_get(rb_mMath, id_PI);
}
@@ -1299,7 +1338,7 @@ numeric_arg(VALUE self)
static VALUE
numeric_rect(VALUE self)
{
- return rb_assoc_new(self, ZERO);
+ return rb_assoc_new(self, INT2FIX(0));
}
static VALUE
@@ -1309,7 +1348,7 @@ numeric_polar(VALUE self)
}
static VALUE
-numeric_conjugate(VALUE self)
+numeric_conj(VALUE self)
{
return self;
}
@@ -1327,29 +1366,25 @@ Init_Complex(void)
id_abs2 = rb_intern("abs2");
id_arg = rb_intern("arg");
id_cmp = rb_intern("<=>");
- id_conjugate = rb_intern("conjugate");
+ id_conj = rb_intern("conj");
id_convert = rb_intern("convert");
id_denominator = rb_intern("denominator");
id_divmod = rb_intern("divmod");
id_equal_p = rb_intern("==");
- id_exact_p = rb_intern("exact?");
id_expt = rb_intern("**");
id_floor = rb_intern("floor");
- id_format = rb_intern("format");
+ id_hash = rb_intern("hash");
id_idiv = rb_intern("div");
id_inspect = rb_intern("inspect");
id_negate = rb_intern("-@");
- id_new = rb_intern("new");
- id_new_bang = rb_intern("new!");
id_numerator = rb_intern("numerator");
id_polar = rb_intern("polar");
id_quo = rb_intern("quo");
- id_scalar_p = rb_intern("scalar?");
+ id_real_p = rb_intern("real?");
id_to_f = rb_intern("to_f");
id_to_i = rb_intern("to_i");
id_to_r = rb_intern("to_r");
id_to_s = rb_intern("to_s");
- id_truncate = rb_intern("truncate");
rb_cComplex = rb_define_class(COMPLEX_NAME, rb_cNumeric);
@@ -1390,9 +1425,10 @@ Init_Complex(void)
#endif
rb_define_method(rb_cComplex, "real", nucomp_real, 0);
- rb_define_method(rb_cComplex, "image", nucomp_image, 0);
- rb_define_method(rb_cComplex, "imag", nucomp_image, 0);
+ rb_define_method(rb_cComplex, "imaginary", nucomp_imag, 0);
+ rb_define_method(rb_cComplex, "imag", nucomp_imag, 0);
+ rb_define_method(rb_cComplex, "-@", nucomp_negate, 0);
rb_define_method(rb_cComplex, "+", nucomp_add, 1);
rb_define_method(rb_cComplex, "-", nucomp_sub, 1);
rb_define_method(rb_cComplex, "*", nucomp_mul, 1);
@@ -1413,24 +1449,24 @@ Init_Complex(void)
rb_define_method(rb_cComplex, "rectangular", nucomp_rect, 0);
rb_define_method(rb_cComplex, "rect", nucomp_rect, 0);
rb_define_method(rb_cComplex, "polar", nucomp_polar, 0);
- rb_define_method(rb_cComplex, "conjugate", nucomp_conjugate, 0);
- rb_define_method(rb_cComplex, "conj", nucomp_conjugate, 0);
+ rb_define_method(rb_cComplex, "conjugate", nucomp_conj, 0);
+ rb_define_method(rb_cComplex, "conj", nucomp_conj, 0);
#if 0
- rb_define_method(rb_cComplex, "~", nucomp_conjugate, 0); /* gcc */
+ rb_define_method(rb_cComplex, "~", nucomp_conj, 0); /* gcc */
#endif
-#if 0
rb_define_method(rb_cComplex, "real?", nucomp_false, 0);
+#if 0
rb_define_method(rb_cComplex, "complex?", nucomp_true, 0);
rb_define_method(rb_cComplex, "exact?", nucomp_exact_p, 0);
rb_define_method(rb_cComplex, "inexact?", nucomp_inexact_p, 0);
#endif
- rb_define_method(rb_cComplex, "scalar?", nucomp_false, 0);
rb_define_method(rb_cComplex, "numerator", nucomp_numerator, 0);
rb_define_method(rb_cComplex, "denominator", nucomp_denominator, 0);
rb_define_method(rb_cComplex, "hash", nucomp_hash, 0);
+ rb_define_method(rb_cComplex, "eql?", nucomp_eql_p, 1);
rb_define_method(rb_cComplex, "to_s", nucomp_to_s, 0);
rb_define_method(rb_cComplex, "inspect", nucomp_inspect, 0);
@@ -1456,11 +1492,9 @@ Init_Complex(void)
/* --- */
- rb_define_method(rb_cNumeric, "re", numeric_re, 0);
- rb_define_method(rb_cNumeric, "im", numeric_im, 0);
rb_define_method(rb_cNumeric, "real", numeric_real, 0);
- rb_define_method(rb_cNumeric, "image", numeric_image, 0);
- rb_define_method(rb_cNumeric, "imag", numeric_image, 0);
+ rb_define_method(rb_cNumeric, "imaginary", numeric_imag, 0);
+ rb_define_method(rb_cNumeric, "imag", numeric_imag, 0);
rb_define_method(rb_cNumeric, "abs2", numeric_abs2, 0);
rb_define_method(rb_cNumeric, "arg", numeric_arg, 0);
rb_define_method(rb_cNumeric, "angle", numeric_arg, 0);
@@ -1468,9 +1502,15 @@ Init_Complex(void)
rb_define_method(rb_cNumeric, "rectangular", numeric_rect, 0);
rb_define_method(rb_cNumeric, "rect", numeric_rect, 0);
rb_define_method(rb_cNumeric, "polar", numeric_polar, 0);
- rb_define_method(rb_cNumeric, "conjugate", numeric_conjugate, 0);
- rb_define_method(rb_cNumeric, "conj", numeric_conjugate, 0);
+ rb_define_method(rb_cNumeric, "conjugate", numeric_conj, 0);
+ rb_define_method(rb_cNumeric, "conj", numeric_conj, 0);
rb_define_const(rb_cComplex, "I",
f_complex_new_bang2(rb_cComplex, ZERO, ONE));
}
+
+/*
+Local variables:
+c-file-style: "ruby"
+End:
+*/
diff --git a/configure.in b/configure.in
index 327abb24eb..6783b82994 100644
--- a/configure.in
+++ b/configure.in
@@ -1423,10 +1423,12 @@ if test "$with_dln_a_out" != yes; then
powerpc*)
: ${LDSHARED="ld -xms"}
DLDFLAGS="$DLDFLAGS "'-export Init_$(TARGET) -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o'
- ;;
+ LDFLAGS="$LDFLAGS -L/boot/home/config/lib -lbe -lroot"
+ ;;
i586*)
: ${LDSHARED="ld -shared"}
- DLDFLAGS="$DLDFLAGS -L/boot/develop/lib/x86 -lbe -lroot"
+ DLDFLAGS="$DLDFLAGS -L/boot/develop/lib/x86 -L/boot/home/config/lib \$(topdir)/_APP_ -lbe -lroot"
+ LDFLAGS="$LDFLAGS -L/boot/develop/lib/x86 -L/boot/home/config/lib -lbe -lroot"
;;
esac
: ${LIBPATHENV=LIBRARY_PATH}
@@ -1455,7 +1457,7 @@ if test "$with_dln_a_out" != yes; then
hiuxmpp) : ${LDSHARED='ld -r'} ;;
atheos*) : ${LDSHARED="$CC -shared"}
rb_cv_dlopen=yes ;;
- os2-emx*) LDFLAGS="$LDFLAGS -Zbsd-signals"
+ os2-emx*) LDFLAGS="$LDFLAGS -Zomf"
;;
*) : ${LDSHARED='ld'} ;;
esac
@@ -1799,7 +1801,7 @@ case "$target_os" in
MINIDLNOBJ=dmydln.o
;;
os2-emx)
- CFLAGS="$CFLAGS -DOS2 -Zmts"
+ CFLAGS="$CFLAGS -DOS2"
LIBRUBY_A=`echo $LIBRUBY_A | sed 's/^lib//'`
LIBRUBY_SO=`echo $LIBRUBY_SO | sed 's/^lib//'`
LIBRUBY_ALIASES=`for i in $LIBRUBY_ALIASES; do echo "$i"; done | sed 's/^lib//'`
@@ -1826,6 +1828,7 @@ case "$target_os" in
CFLAGS="$CFLAGS -relax_pointers"
;;
esac
+ CPPFLAGS="$CPPFLAGS -I/boot/home/config/include"
;;
cygwin*|mingw*)
LIBRUBY_DLDFLAGS="${DLDFLAGS}"' -Wl,--out-implib=$(LIBRUBY)'
diff --git a/dln.c b/dln.c
index 6fc97787e6..db368662c3 100644
--- a/dln.c
+++ b/dln.c
@@ -1442,7 +1442,8 @@ dln_load(const char *file)
/* load extention module */
img_id = load_add_on(file);
if (img_id <= 0) {
- rb_loaderror("Failed to load %.200s", file);
+ rb_loaderror("Failed to load add_on %.200s error_code=%x",
+ file, img_id);
}
/* find symbol for module initialize function. */
diff --git a/enc/big5.c b/enc/big5.c
index 70a316ea2c..9993f472e1 100644
--- a/enc/big5.c
+++ b/enc/big5.c
@@ -165,7 +165,7 @@ static const char BIG5_CAN_BE_TRAIL_TABLE[256] = {
#define BIG5_ISMB_TRAIL(byte) BIG5_CAN_BE_TRAIL_TABLE[(byte)]
static UChar*
-big5_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+big5_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
int len;
@@ -181,7 +181,7 @@ big5_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
}
}
}
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/cp949.c b/enc/cp949.c
index 0046460625..009443aed4 100644
--- a/enc/cp949.c
+++ b/enc/cp949.c
@@ -165,7 +165,7 @@ cp949_is_code_ctype(OnigCodePoint code, unsigned int ctype, OnigEncoding enc)
}
static UChar*
-cp949_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+cp949_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
int len;
@@ -181,7 +181,7 @@ cp949_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc
}
}
}
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/euc_jp.c b/enc/euc_jp.c
index fb8bf41c25..21f30ad2f3 100644
--- a/enc/euc_jp.c
+++ b/enc/euc_jp.c
@@ -222,7 +222,7 @@ mbc_case_fold(OnigCaseFoldType flag,
}
static UChar*
-left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
/* In this encoding
mb-trail bytes doesn't mix with single bytes.
@@ -234,7 +234,7 @@ left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
p = s;
while (!eucjp_islead(*p) && p > start) p--;
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/euc_kr.c b/enc/euc_kr.c
index 1b5ec893c1..f20a57e69a 100644
--- a/enc/euc_kr.c
+++ b/enc/euc_kr.c
@@ -145,7 +145,7 @@ euckr_is_code_ctype(OnigCodePoint code, unsigned int ctype, OnigEncoding enc)
#define euckr_islead(c) ((c) < 0xa1 || (c) == 0xff)
static UChar*
-euckr_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+euckr_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
/* Assumed in this encoding,
mb-trail bytes don't mix with single bytes.
@@ -157,7 +157,7 @@ euckr_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc
p = s;
while (!euckr_islead(*p) && p > start) p--;
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/euc_tw.c b/enc/euc_tw.c
index ca38983d53..d025a0dd45 100644
--- a/enc/euc_tw.c
+++ b/enc/euc_tw.c
@@ -187,7 +187,7 @@ euctw_is_code_ctype(OnigCodePoint code, unsigned int ctype, OnigEncoding enc)
#define euctw_islead(c) ((UChar )((c) - 0xa1) > 0xfe - 0xa1)
static UChar*
-euctw_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+euctw_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
/* Assumed in this encoding,
mb-trail bytes don't mix with single bytes.
@@ -199,7 +199,7 @@ euctw_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc
p = s;
while (!euctw_islead(*p) && p > start) p--;
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/gb18030.c b/enc/gb18030.c
index 2b707d4a7d..16c8c1c17f 100644
--- a/enc/gb18030.c
+++ b/enc/gb18030.c
@@ -245,7 +245,7 @@ enum state {
};
static UChar*
-gb18030_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+gb18030_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
enum state state = S_START;
diff --git a/enc/gbk.c b/enc/gbk.c
index 8b45ed4dc9..3efb1bf636 100644
--- a/enc/gbk.c
+++ b/enc/gbk.c
@@ -165,7 +165,7 @@ gbk_is_code_ctype(OnigCodePoint code, unsigned int ctype, OnigEncoding enc)
}
static UChar*
-gbk_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+gbk_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
int len;
@@ -181,7 +181,7 @@ gbk_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
}
}
}
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/shift_jis.c b/enc/shift_jis.c
index f74afffa92..b4d8592a27 100644
--- a/enc/shift_jis.c
+++ b/enc/shift_jis.c
@@ -229,7 +229,7 @@ is_code_ctype(OnigCodePoint code, unsigned int ctype)
#endif
static UChar*
-left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
int len;
@@ -245,7 +245,7 @@ left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
}
}
}
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/utf_16be.c b/enc/utf_16be.c
index ccae9397bb..8d7c8e9b11 100644
--- a/enc/utf_16be.c
+++ b/enc/utf_16be.c
@@ -212,7 +212,7 @@ utf16be_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* e
#endif
static UChar*
-utf16be_left_adjust_char_head(const UChar* start, const UChar* s,
+utf16be_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end,
OnigEncoding enc ARG_UNUSED)
{
if (s <= start) return (UChar* )s;
diff --git a/enc/utf_16le.c b/enc/utf_16le.c
index c3712f4e18..c8a1e7a10a 100644
--- a/enc/utf_16le.c
+++ b/enc/utf_16le.c
@@ -204,7 +204,7 @@ utf16le_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp,
#endif
static UChar*
-utf16le_left_adjust_char_head(const UChar* start, const UChar* s,
+utf16le_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end,
OnigEncoding enc ARG_UNUSED)
{
if (s <= start) return (UChar* )s;
diff --git a/enc/utf_32be.c b/enc/utf_32be.c
index ed6c9b7f3b..61e7d0f1b5 100644
--- a/enc/utf_32be.c
+++ b/enc/utf_32be.c
@@ -152,7 +152,7 @@ utf32be_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* e
#endif
static UChar*
-utf32be_left_adjust_char_head(const UChar* start, const UChar* s,
+utf32be_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end,
OnigEncoding enc ARG_UNUSED)
{
int rem;
diff --git a/enc/utf_32le.c b/enc/utf_32le.c
index 53e3522070..3a0a41bba7 100644
--- a/enc/utf_32le.c
+++ b/enc/utf_32le.c
@@ -152,7 +152,7 @@ utf32le_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* e
#endif
static UChar*
-utf32le_left_adjust_char_head(const UChar* start, const UChar* s,
+utf32le_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end,
OnigEncoding enc ARG_UNUSED)
{
int rem;
diff --git a/enc/utf_8.c b/enc/utf_8.c
index b8ee92feb4..3b9387c613 100644
--- a/enc/utf_8.c
+++ b/enc/utf_8.c
@@ -405,7 +405,7 @@ get_ctype_code_range(OnigCtype ctype, OnigCodePoint *sb_out,
static UChar*
-left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc ARG_UNUSED)
+left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc ARG_UNUSED)
{
const UChar *p;
diff --git a/encoding.c b/encoding.c
index 3752d1c73a..78887de730 100644
--- a/encoding.c
+++ b/encoding.c
@@ -18,7 +18,7 @@
#endif
#include "ruby/util.h"
-static ID id_encoding, id_base_encoding;
+static ID id_encoding;
VALUE rb_cEncoding;
static VALUE rb_encoding_list;
@@ -42,7 +42,6 @@ void rb_enc_init(void);
#define enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
static int load_encoding(const char *name);
-static VALUE enc_base_encoding(VALUE self);
static void
enc_mark(void *ptr)
@@ -545,14 +544,31 @@ rb_id_encoding(void)
int
rb_enc_get_index(VALUE obj)
{
- int i;
-
- i = ENCODING_GET_INLINED(obj);
- if (i == ENCODING_INLINE_MAX) {
- VALUE iv;
+ int i = -1;
+ VALUE tmp;
- iv = rb_ivar_get(obj, rb_id_encoding());
- i = NUM2INT(iv);
+ switch (BUILTIN_TYPE(obj)) {
+ default:
+ case T_STRING:
+ case T_REGEXP:
+ i = ENCODING_GET_INLINED(obj);
+ if (i == ENCODING_INLINE_MAX) {
+ VALUE iv;
+
+ iv = rb_ivar_get(obj, rb_id_encoding());
+ i = NUM2INT(iv);
+ }
+ break;
+ case T_FILE:
+ tmp = rb_funcall(obj, rb_intern("internal_encoding"), 0, 0);
+ if (NIL_P(tmp)) obj = rb_funcall(obj, rb_intern("external_encoding"), 0, 0);
+ else obj = tmp;
+ if (NIL_P(obj)) break;
+ case T_DATA:
+ if (RDATA(obj)->dmark == enc_mark) {
+ i = enc_check_encoding(obj);
+ }
+ break;
}
return i;
}
@@ -631,9 +647,11 @@ rb_enc_compatible(VALUE str1, VALUE str2)
if (!rb_enc_asciicompat(enc1) || !rb_enc_asciicompat(enc2)) {
return 0;
}
- if (BUILTIN_TYPE(str2) == T_REGEXP && idx2 == ENCINDEX_US_ASCII)
+
+ /* objects whose encoding is the same of contents */
+ if (BUILTIN_TYPE(str2) != T_STRING && idx2 == ENCINDEX_US_ASCII)
return enc1;
- if (BUILTIN_TYPE(str1) == T_REGEXP && idx1 == ENCINDEX_US_ASCII)
+ if (BUILTIN_TYPE(str1) != T_STRING && idx1 == ENCINDEX_US_ASCII)
return enc2;
if (BUILTIN_TYPE(str1) != T_STRING) {
@@ -805,14 +823,6 @@ enc_name(VALUE self)
return rb_usascii_str_new2(rb_enc_name((rb_encoding*)DATA_PTR(self)));
}
-static VALUE
-enc_base_encoding(VALUE self)
-{
- rb_encoding *base = enc_table.list[must_encoding(self)].base;
- if (!base) return Qnil;
- return ENC_FROM_ENCODING(base);
-}
-
/*
* call-seq:
* Encoding.list => [enc1, enc2, ...]
@@ -880,14 +890,6 @@ enc_compatible_p(VALUE klass, VALUE str1, VALUE str2)
{
rb_encoding *enc;
- if (SPECIAL_CONST_P(str1) || TYPE(str1) != T_STRING && TYPE(str1) != T_REGEXP) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Regexp)",
- rb_obj_classname(str1));
- }
- if (SPECIAL_CONST_P(str2) || TYPE(str2) != T_STRING && TYPE(str2) != T_REGEXP) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Regexp)",
- rb_obj_classname(str2));
- }
if (!enc_capable(str1)) return Qnil;
if (!enc_capable(str2)) return Qnil;
enc = rb_enc_compatible(str1, str2);
@@ -986,11 +988,15 @@ rb_filesystem_encoding(void)
}
static int default_external_index;
+static rb_encoding *default_external;
rb_encoding *
rb_default_external_encoding(void)
{
- return rb_enc_from_index(default_external_index);
+ if (!default_external) {
+ default_external = rb_enc_from_index(default_external_index);
+ }
+ return default_external;
}
VALUE
@@ -1017,6 +1023,7 @@ void
rb_enc_set_default_external(VALUE encoding)
{
default_external_index = rb_enc_to_index(rb_to_encoding(encoding));
+ default_external = 0;
}
/*
@@ -1188,14 +1195,11 @@ Init_Encoding(void)
VALUE list;
int i;
- id_base_encoding = rb_intern("#base_encoding");
-
rb_cEncoding = rb_define_class("Encoding", rb_cObject);
rb_undef_alloc_func(rb_cEncoding);
rb_define_method(rb_cEncoding, "to_s", enc_name, 0);
rb_define_method(rb_cEncoding, "inspect", enc_inspect, 0);
rb_define_method(rb_cEncoding, "name", enc_name, 0);
- rb_define_method(rb_cEncoding, "base_encoding", enc_base_encoding, 0);
rb_define_method(rb_cEncoding, "dummy?", enc_dummy_p, 0);
rb_define_singleton_method(rb_cEncoding, "list", enc_list, 0);
rb_define_singleton_method(rb_cEncoding, "name_list", rb_enc_name_list, 0);
@@ -1209,10 +1213,11 @@ Init_Encoding(void)
rb_define_singleton_method(rb_cEncoding, "default_external", get_default_external, 0);
rb_define_singleton_method(rb_cEncoding, "locale_charmap", rb_locale_charmap, 0);
- rb_gc_register_address(&rb_encoding_list);
list = rb_ary_new2(enc_table.count);
RBASIC(list)->klass = 0;
rb_encoding_list = list;
+ rb_gc_register_mark_object(list);
+
for (i = 0; i < enc_table.count; ++i) {
rb_ary_push(list, enc_new(enc_table.list[i].enc));
}
diff --git a/error.c b/error.c
index 683828c934..4782cfa796 100644
--- a/error.c
+++ b/error.c
@@ -323,12 +323,12 @@ VALUE rb_eIndexError;
VALUE rb_eKeyError;
VALUE rb_eRangeError;
VALUE rb_eNameError;
+VALUE rb_eEncCompatError;
VALUE rb_eNoMethodError;
VALUE rb_eSecurityError;
VALUE rb_eNotImpError;
VALUE rb_eNoMemError;
VALUE rb_cNameErrorMesg;
-VALUE rb_eEncCompatError;
VALUE rb_eScriptError;
VALUE rb_eSyntaxError;
@@ -1033,7 +1033,6 @@ Init_Exception(void)
rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
rb_eKeyError = rb_define_class("KeyError", rb_eIndexError);
rb_eRangeError = rb_define_class("RangeError", rb_eStandardError);
- rb_eEncCompatError = rb_define_class("EncodingCompatibilityError", rb_eStandardError);
rb_eScriptError = rb_define_class("ScriptError", rb_eException);
rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
@@ -1057,6 +1056,7 @@ Init_Exception(void)
rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
+ rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eStandardError);
syserr_tbl = st_init_numtable();
rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
diff --git a/eval.c b/eval.c
index 5a78841cdb..038198c895 100644
--- a/eval.c
+++ b/eval.c
@@ -1129,9 +1129,6 @@ rb_f_method_name(void)
void
Init_eval(void)
{
- /* TODO: fix position */
- GET_THREAD()->vm->mark_object_ary = rb_ary_new();
-
rb_define_virtual_variable("$@", errat_getter, errat_setter);
rb_define_virtual_variable("$!", errinfo_getter, 0);
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 754c319991..fbc2474edf 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -579,13 +579,6 @@ BigDecimal_to_i(VALUE self)
return rb_cstr2inum(psz,10);
}
-static VALUE
-BigDecimal_induced_from(VALUE self, VALUE x)
-{
- Real *p = GetVpValue(x,1);
- return p->obj;
-}
-
/* Returns a new Float object having approximately the same value as the
* BigDecimal number. Normal accuracy limits and built-in errors of binary
* Float arithmetic apply.
@@ -1807,7 +1800,6 @@ Init_bigdecimal(void)
rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
- rb_define_singleton_method(rb_cBigDecimal, "induced_from",BigDecimal_induced_from, 1);
rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
rb_define_singleton_method(rb_cBigDecimal, "ver", BigDecimal_version, 0);
@@ -3944,7 +3936,12 @@ VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, con
es = e*((S_INT)BASE_FIG);
e = e * 10 + exp_chr[i] - '0';
if(es>e*((S_INT)BASE_FIG)) {
- return VpException(VP_EXCEPTION_INFINITY,"exponent overflow",0);
+ VpException(VP_EXCEPTION_INFINITY,"exponent overflow",0);
+ sign = 1;
+ if(int_chr[0] == '-') sign = -1;
+ if(signe > 0) VpSetInf(a, sign);
+ else VpSetZero(a, sign);
+ return 1;
}
++i;
}
@@ -4633,8 +4630,20 @@ VpPower(Real *y, Real *x, S_INT n)
}
goto Exit;
}
- if(!VpIsDef(x)) {
- VpSetNaN(y); /* Not sure !!! */
+ if(VpIsNaN(x)) {
+ VpSetNaN(y);
+ goto Exit;
+ }
+ if(VpIsInf(x)) {
+ if(n==0) {
+ VpSetOne(y);
+ goto Exit;
+ }
+ if(n>0) {
+ VpSetInf(y, (n%2==0 || VpIsPosInf(x)) ? 1 : -1);
+ goto Exit;
+ }
+ VpSetZero(y, (n%2==0 || VpIsPosInf(x)) ? 1 : -1);
goto Exit;
}
diff --git a/ext/json/ext/generator/extconf.rb b/ext/json/ext/generator/extconf.rb
index 86ed7e6367..88aaf40d70 100644
--- a/ext/json/ext/generator/extconf.rb
+++ b/ext/json/ext/generator/extconf.rb
@@ -2,9 +2,8 @@ require 'mkmf'
require 'rbconfig'
if CONFIG['CC'] =~ /gcc/
- #$CFLAGS += ' -Wall -ggdb'
$CFLAGS += ' -Wall'
+ #$CFLAGS += ' -O0 -ggdb'
end
-have_header 'st.h'
-create_makefile 'json/ext/generator'
+create_makefile 'generator'
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index b8a1ea16d1..1f48d3c780 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -1,15 +1,8 @@
-/* vim: set cin et sw=4 ts=4: */
-
+#include <string.h>
#include "ruby.h"
-#include "ruby/st.h"
#include "unicode.h"
-#include <string.h>
#include <math.h>
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
#define check_max_nesting(state, depth) do { \
long current_nesting = 1 + depth; \
if (state->max_nesting != 0 && current_nesting > state->max_nesting) \
@@ -297,14 +290,14 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
return rb_funcall(self, i_to_s, 0);
} else {
tmp = rb_funcall(self, i_to_s, 0);
- rb_raise(eGeneratorError, "%s not allowed in JSON", StringValueCStr(tmp));
+ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
}
} else if (isnan(value)) {
if (!state || state->allow_nan) {
return rb_funcall(self, i_to_s, 0);
} else {
tmp = rb_funcall(self, i_to_s, 0);
- rb_raise(eGeneratorError, "%s not allowed in JSON", StringValueCStr(tmp));
+ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
}
} else {
return rb_funcall(self, i_to_s, 0);
diff --git a/ext/json/ext/generator/unicode.c b/ext/json/ext/generator/unicode.c
index 44e1f41f98..76834eadc5 100644
--- a/ext/json/ext/generator/unicode.c
+++ b/ext/json/ext/generator/unicode.c
@@ -1,5 +1,3 @@
-/* vim: set cin et sw=4 ts=4: */
-
#include "unicode.h"
#define unicode_escape(buffer, character) \
diff --git a/ext/json/ext/parser/extconf.rb b/ext/json/ext/parser/extconf.rb
index b2e7b051a4..f511bf07da 100644
--- a/ext/json/ext/parser/extconf.rb
+++ b/ext/json/ext/parser/extconf.rb
@@ -2,9 +2,8 @@ require 'mkmf'
require 'rbconfig'
if CONFIG['CC'] =~ /gcc/
- #$CFLAGS += ' -Wall -ggdb'
$CFLAGS += ' -Wall'
+ #$CFLAGS += ' -O0 -ggdb'
end
-have_header 'st.h'
-create_makefile 'json/ext/parser'
+create_makefile 'parser'
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
index 8734de2f5b..fe85b26cee 100644
--- a/ext/json/ext/parser/parser.c
+++ b/ext/json/ext/parser/parser.c
@@ -1,10 +1,5 @@
#line 1 "parser.rl"
-/* vim: set cin et sw=4 ts=4: */
-
#include "ruby.h"
-#include "ruby/re.h"
-#include "ruby/st.h"
-#include "ruby/encoding.h"
#include "unicode.h"
#define EVIL 0x666
@@ -39,18 +34,18 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
JSON_Parser *json; \
Data_Get_Struct(self, JSON_Parser, json);
-#line 67 "parser.rl"
+#line 64 "parser.rl"
-#line 47 "parser.c"
+#line 44 "parser.c"
static const int JSON_object_start = 1;
static const int JSON_object_first_final = 27;
static const int JSON_object_error = 0;
static const int JSON_object_en_main = 1;
-#line 100 "parser.rl"
+#line 97 "parser.rl"
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -65,16 +60,16 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = rb_hash_new();
-#line 69 "parser.c"
+#line 66 "parser.c"
{
cs = JSON_object_start;
}
-#line 114 "parser.rl"
+#line 111 "parser.rl"
-#line 75 "parser.c"
+#line 72 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -82,10 +77,11 @@ case 1:
goto st2;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
switch( (*p) ) {
case 13: goto st2;
@@ -98,17 +94,17 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 86 "parser.rl"
+#line 83 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, &last_name);
- if (np == NULL) goto _out3; else {p = (( np))-1;}
+ if (np == NULL) { p--; {p++; cs = 3; goto _out;} } else {p = (( np))-1;}
}
goto st3;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
-#line 112 "parser.c"
+#line 110 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -120,7 +116,7 @@ case 3:
goto st0;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
switch( (*p) ) {
case 42: goto st5;
@@ -129,14 +125,14 @@ case 4:
goto st0;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
if ( (*p) == 42 )
goto st6;
goto st5;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
switch( (*p) ) {
case 42: goto st6;
@@ -145,14 +141,14 @@ case 6:
goto st5;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
if ( (*p) == 10 )
goto st3;
goto st7;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
switch( (*p) ) {
case 13: goto st8;
@@ -175,12 +171,12 @@ case 8:
goto st8;
goto st0;
tr11:
-#line 75 "parser.rl"
+#line 72 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
if (np == NULL) {
- goto _out9;
+ p--; {p++; cs = 9; goto _out;}
} else {
rb_hash_aset(*result, last_name, v);
{p = (( np))-1;}
@@ -189,9 +185,9 @@ tr11:
goto st9;
st9:
if ( ++p == pe )
- goto _out9;
+ goto _test_eof9;
case 9:
-#line 195 "parser.c"
+#line 193 "parser.c"
switch( (*p) ) {
case 13: goto st9;
case 32: goto st9;
@@ -204,7 +200,7 @@ case 9:
goto st0;
st10:
if ( ++p == pe )
- goto _out10;
+ goto _test_eof10;
case 10:
switch( (*p) ) {
case 13: goto st10;
@@ -217,7 +213,7 @@ case 10:
goto st0;
st11:
if ( ++p == pe )
- goto _out11;
+ goto _test_eof11;
case 11:
switch( (*p) ) {
case 42: goto st12;
@@ -226,14 +222,14 @@ case 11:
goto st0;
st12:
if ( ++p == pe )
- goto _out12;
+ goto _test_eof12;
case 12:
if ( (*p) == 42 )
goto st13;
goto st12;
st13:
if ( ++p == pe )
- goto _out13;
+ goto _test_eof13;
case 13:
switch( (*p) ) {
case 42: goto st13;
@@ -242,14 +238,14 @@ case 13:
goto st12;
st14:
if ( ++p == pe )
- goto _out14;
+ goto _test_eof14;
case 14:
if ( (*p) == 10 )
goto st10;
goto st14;
st15:
if ( ++p == pe )
- goto _out15;
+ goto _test_eof15;
case 15:
switch( (*p) ) {
case 42: goto st16;
@@ -258,14 +254,14 @@ case 15:
goto st0;
st16:
if ( ++p == pe )
- goto _out16;
+ goto _test_eof16;
case 16:
if ( (*p) == 42 )
goto st17;
goto st16;
st17:
if ( ++p == pe )
- goto _out17;
+ goto _test_eof17;
case 17:
switch( (*p) ) {
case 42: goto st17;
@@ -274,24 +270,24 @@ case 17:
goto st16;
st18:
if ( ++p == pe )
- goto _out18;
+ goto _test_eof18;
case 18:
if ( (*p) == 10 )
goto st9;
goto st18;
tr4:
-#line 91 "parser.rl"
- { goto _out27; }
+#line 88 "parser.rl"
+ { p--; {p++; cs = 27; goto _out;} }
goto st27;
st27:
if ( ++p == pe )
- goto _out27;
+ goto _test_eof27;
case 27:
-#line 291 "parser.c"
+#line 289 "parser.c"
goto st0;
st19:
if ( ++p == pe )
- goto _out19;
+ goto _test_eof19;
case 19:
switch( (*p) ) {
case 42: goto st20;
@@ -300,14 +296,14 @@ case 19:
goto st0;
st20:
if ( ++p == pe )
- goto _out20;
+ goto _test_eof20;
case 20:
if ( (*p) == 42 )
goto st21;
goto st20;
st21:
if ( ++p == pe )
- goto _out21;
+ goto _test_eof21;
case 21:
switch( (*p) ) {
case 42: goto st21;
@@ -316,14 +312,14 @@ case 21:
goto st20;
st22:
if ( ++p == pe )
- goto _out22;
+ goto _test_eof22;
case 22:
if ( (*p) == 10 )
goto st8;
goto st22;
st23:
if ( ++p == pe )
- goto _out23;
+ goto _test_eof23;
case 23:
switch( (*p) ) {
case 42: goto st24;
@@ -332,14 +328,14 @@ case 23:
goto st0;
st24:
if ( ++p == pe )
- goto _out24;
+ goto _test_eof24;
case 24:
if ( (*p) == 42 )
goto st25;
goto st24;
st25:
if ( ++p == pe )
- goto _out25;
+ goto _test_eof25;
case 25:
switch( (*p) ) {
case 42: goto st25;
@@ -348,43 +344,43 @@ case 25:
goto st24;
st26:
if ( ++p == pe )
- goto _out26;
+ goto _test_eof26;
case 26:
if ( (*p) == 10 )
goto st2;
goto st26;
}
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
- _out8: cs = 8; goto _out;
- _out9: cs = 9; goto _out;
- _out10: cs = 10; goto _out;
- _out11: cs = 11; goto _out;
- _out12: cs = 12; goto _out;
- _out13: cs = 13; goto _out;
- _out14: cs = 14; goto _out;
- _out15: cs = 15; goto _out;
- _out16: cs = 16; goto _out;
- _out17: cs = 17; goto _out;
- _out18: cs = 18; goto _out;
- _out27: cs = 27; goto _out;
- _out19: cs = 19; goto _out;
- _out20: cs = 20; goto _out;
- _out21: cs = 21; goto _out;
- _out22: cs = 22; goto _out;
- _out23: cs = 23; goto _out;
- _out24: cs = 24; goto _out;
- _out25: cs = 25; goto _out;
- _out26: cs = 26; goto _out;
-
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof11: cs = 11; goto _test_eof;
+ _test_eof12: cs = 12; goto _test_eof;
+ _test_eof13: cs = 13; goto _test_eof;
+ _test_eof14: cs = 14; goto _test_eof;
+ _test_eof15: cs = 15; goto _test_eof;
+ _test_eof16: cs = 16; goto _test_eof;
+ _test_eof17: cs = 17; goto _test_eof;
+ _test_eof18: cs = 18; goto _test_eof;
+ _test_eof27: cs = 27; goto _test_eof;
+ _test_eof19: cs = 19; goto _test_eof;
+ _test_eof20: cs = 20; goto _test_eof;
+ _test_eof21: cs = 21; goto _test_eof;
+ _test_eof22: cs = 22; goto _test_eof;
+ _test_eof23: cs = 23; goto _test_eof;
+ _test_eof24: cs = 24; goto _test_eof;
+ _test_eof25: cs = 25; goto _test_eof;
+ _test_eof26: cs = 26; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 115 "parser.rl"
+#line 112 "parser.rl"
if (cs >= JSON_object_first_final) {
if (RTEST(json->create_id)) {
@@ -403,14 +399,14 @@ case 26:
}
-#line 407 "parser.c"
+#line 405 "parser.c"
static const int JSON_value_start = 1;
static const int JSON_value_first_final = 21;
static const int JSON_value_error = 0;
static const int JSON_value_en_main = 1;
-#line 213 "parser.rl"
+#line 210 "parser.rl"
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -418,16 +414,16 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 422 "parser.c"
+#line 420 "parser.c"
{
cs = JSON_value_start;
}
-#line 220 "parser.rl"
+#line 217 "parser.rl"
-#line 428 "parser.c"
+#line 426 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -446,259 +442,260 @@ case 1:
goto tr2;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
tr0:
-#line 161 "parser.rl"
+#line 158 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, result);
- if (np == NULL) goto _out21; else {p = (( np))-1;}
+ if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
}
goto st21;
tr2:
-#line 166 "parser.rl"
+#line 163 "parser.rl"
{
char *np;
if(pe > p + 9 && !strncmp(MinusInfinity, p, 9)) {
if (json->allow_nan) {
*result = CMinusInfinity;
{p = (( p + 10))-1;}
- goto _out21;
+ p--; {p++; cs = 21; goto _out;}
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
np = JSON_parse_float(json, p, pe, result);
if (np != NULL) {p = (( np))-1;}
np = JSON_parse_integer(json, p, pe, result);
if (np != NULL) {p = (( np))-1;}
- goto _out21;
+ p--; {p++; cs = 21; goto _out;}
}
goto st21;
tr5:
-#line 184 "parser.rl"
+#line 181 "parser.rl"
{
char *np;
- json->current_nesting += 1;
+ json->current_nesting++;
np = JSON_parse_array(json, p, pe, result);
- json->current_nesting -= 1;
- if (np == NULL) goto _out21; else {p = (( np))-1;}
+ json->current_nesting--;
+ if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
}
goto st21;
tr9:
-#line 192 "parser.rl"
+#line 189 "parser.rl"
{
char *np;
- json->current_nesting += 1;
+ json->current_nesting++;
np = JSON_parse_object(json, p, pe, result);
- json->current_nesting -= 1;
- if (np == NULL) goto _out21; else {p = (( np))-1;}
+ json->current_nesting--;
+ if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
}
goto st21;
tr16:
-#line 154 "parser.rl"
+#line 151 "parser.rl"
{
if (json->allow_nan) {
*result = CInfinity;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p - 8);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
}
}
goto st21;
tr18:
-#line 147 "parser.rl"
+#line 144 "parser.rl"
{
if (json->allow_nan) {
*result = CNaN;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p - 2);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
}
}
goto st21;
tr22:
-#line 141 "parser.rl"
+#line 138 "parser.rl"
{
*result = Qfalse;
}
goto st21;
tr25:
-#line 138 "parser.rl"
+#line 135 "parser.rl"
{
*result = Qnil;
}
goto st21;
tr28:
-#line 144 "parser.rl"
+#line 141 "parser.rl"
{
*result = Qtrue;
}
goto st21;
st21:
if ( ++p == pe )
- goto _out21;
+ goto _test_eof21;
case 21:
-#line 200 "parser.rl"
- { goto _out21; }
-#line 542 "parser.c"
+#line 197 "parser.rl"
+ { p--; {p++; cs = 21; goto _out;} }
+#line 541 "parser.c"
goto st0;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
if ( (*p) == 110 )
goto st3;
goto st0;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
if ( (*p) == 102 )
goto st4;
goto st0;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
if ( (*p) == 105 )
goto st5;
goto st0;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
if ( (*p) == 110 )
goto st6;
goto st0;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
if ( (*p) == 105 )
goto st7;
goto st0;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
if ( (*p) == 116 )
goto st8;
goto st0;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
if ( (*p) == 121 )
goto tr16;
goto st0;
st9:
if ( ++p == pe )
- goto _out9;
+ goto _test_eof9;
case 9:
if ( (*p) == 97 )
goto st10;
goto st0;
st10:
if ( ++p == pe )
- goto _out10;
+ goto _test_eof10;
case 10:
if ( (*p) == 78 )
goto tr18;
goto st0;
st11:
if ( ++p == pe )
- goto _out11;
+ goto _test_eof11;
case 11:
if ( (*p) == 97 )
goto st12;
goto st0;
st12:
if ( ++p == pe )
- goto _out12;
+ goto _test_eof12;
case 12:
if ( (*p) == 108 )
goto st13;
goto st0;
st13:
if ( ++p == pe )
- goto _out13;
+ goto _test_eof13;
case 13:
if ( (*p) == 115 )
goto st14;
goto st0;
st14:
if ( ++p == pe )
- goto _out14;
+ goto _test_eof14;
case 14:
if ( (*p) == 101 )
goto tr22;
goto st0;
st15:
if ( ++p == pe )
- goto _out15;
+ goto _test_eof15;
case 15:
if ( (*p) == 117 )
goto st16;
goto st0;
st16:
if ( ++p == pe )
- goto _out16;
+ goto _test_eof16;
case 16:
if ( (*p) == 108 )
goto st17;
goto st0;
st17:
if ( ++p == pe )
- goto _out17;
+ goto _test_eof17;
case 17:
if ( (*p) == 108 )
goto tr25;
goto st0;
st18:
if ( ++p == pe )
- goto _out18;
+ goto _test_eof18;
case 18:
if ( (*p) == 114 )
goto st19;
goto st0;
st19:
if ( ++p == pe )
- goto _out19;
+ goto _test_eof19;
case 19:
if ( (*p) == 117 )
goto st20;
goto st0;
st20:
if ( ++p == pe )
- goto _out20;
+ goto _test_eof20;
case 20:
if ( (*p) == 101 )
goto tr28;
goto st0;
}
- _out0: cs = 0; goto _out;
- _out21: cs = 21; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
- _out8: cs = 8; goto _out;
- _out9: cs = 9; goto _out;
- _out10: cs = 10; goto _out;
- _out11: cs = 11; goto _out;
- _out12: cs = 12; goto _out;
- _out13: cs = 13; goto _out;
- _out14: cs = 14; goto _out;
- _out15: cs = 15; goto _out;
- _out16: cs = 16; goto _out;
- _out17: cs = 17; goto _out;
- _out18: cs = 18; goto _out;
- _out19: cs = 19; goto _out;
- _out20: cs = 20; goto _out;
-
+ _test_eof21: cs = 21; goto _test_eof;
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof11: cs = 11; goto _test_eof;
+ _test_eof12: cs = 12; goto _test_eof;
+ _test_eof13: cs = 13; goto _test_eof;
+ _test_eof14: cs = 14; goto _test_eof;
+ _test_eof15: cs = 15; goto _test_eof;
+ _test_eof16: cs = 16; goto _test_eof;
+ _test_eof17: cs = 17; goto _test_eof;
+ _test_eof18: cs = 18; goto _test_eof;
+ _test_eof19: cs = 19; goto _test_eof;
+ _test_eof20: cs = 20; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 221 "parser.rl"
+#line 218 "parser.rl"
if (cs >= JSON_value_first_final) {
return p;
@@ -708,14 +705,14 @@ case 20:
}
-#line 712 "parser.c"
+#line 711 "parser.c"
static const int JSON_integer_start = 1;
static const int JSON_integer_first_final = 5;
static const int JSON_integer_error = 0;
static const int JSON_integer_en_main = 1;
-#line 237 "parser.rl"
+#line 234 "parser.rl"
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -723,17 +720,17 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
int cs = EVIL;
-#line 727 "parser.c"
+#line 726 "parser.c"
{
cs = JSON_integer_start;
}
-#line 244 "parser.rl"
+#line 241 "parser.rl"
json->memo = p;
-#line 734 "parser.c"
+#line 733 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -745,10 +742,11 @@ case 1:
goto st4;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
if ( (*p) == 48 )
goto st3;
@@ -757,38 +755,38 @@ case 2:
goto st0;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
if ( 48 <= (*p) && (*p) <= 57 )
goto st0;
goto tr4;
tr4:
-#line 234 "parser.rl"
- { goto _out5; }
+#line 231 "parser.rl"
+ { p--; {p++; cs = 5; goto _out;} }
goto st5;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
#line 774 "parser.c"
goto st0;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
if ( 48 <= (*p) && (*p) <= 57 )
goto st4;
goto tr4;
}
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out5: cs = 5; goto _out;
- _out4: cs = 4; goto _out;
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof: {}
_out: {}
}
-#line 246 "parser.rl"
+#line 243 "parser.rl"
if (cs >= JSON_integer_first_final) {
long len = p - json->memo;
@@ -807,7 +805,7 @@ static const int JSON_float_error = 0;
static const int JSON_float_en_main = 1;
-#line 268 "parser.rl"
+#line 265 "parser.rl"
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -819,13 +817,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
{
cs = JSON_float_start;
}
-#line 275 "parser.rl"
+#line 272 "parser.rl"
json->memo = p;
#line 826 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -837,10 +835,11 @@ case 1:
goto st9;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
if ( (*p) == 48 )
goto st3;
@@ -849,7 +848,7 @@ case 2:
goto st0;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
switch( (*p) ) {
case 46: goto st4;
@@ -859,14 +858,14 @@ case 3:
goto st0;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
if ( 48 <= (*p) && (*p) <= 57 )
goto st5;
goto st0;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
switch( (*p) ) {
case 69: goto st6;
@@ -879,18 +878,18 @@ case 5:
goto st0;
goto tr7;
tr7:
-#line 262 "parser.rl"
- { goto _out10; }
+#line 259 "parser.rl"
+ { p--; {p++; cs = 10; goto _out;} }
goto st10;
st10:
if ( ++p == pe )
- goto _out10;
+ goto _test_eof10;
case 10:
-#line 890 "parser.c"
+#line 891 "parser.c"
goto st0;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
switch( (*p) ) {
case 43: goto st7;
@@ -901,14 +900,14 @@ case 6:
goto st0;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
if ( 48 <= (*p) && (*p) <= 57 )
goto st8;
goto st0;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
switch( (*p) ) {
case 69: goto st0;
@@ -922,7 +921,7 @@ case 8:
goto tr7;
st9:
if ( ++p == pe )
- goto _out9;
+ goto _test_eof9;
case 9:
switch( (*p) ) {
case 46: goto st4;
@@ -933,20 +932,20 @@ case 9:
goto st9;
goto st0;
}
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out10: cs = 10; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
- _out8: cs = 8; goto _out;
- _out9: cs = 9; goto _out;
-
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 277 "parser.rl"
+#line 274 "parser.rl"
if (cs >= JSON_float_first_final) {
long len = p - json->memo;
@@ -959,14 +958,14 @@ case 9:
-#line 963 "parser.c"
+#line 964 "parser.c"
static const int JSON_array_start = 1;
static const int JSON_array_first_final = 17;
static const int JSON_array_error = 0;
static const int JSON_array_en_main = 1;
-#line 313 "parser.rl"
+#line 310 "parser.rl"
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -979,16 +978,16 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
*result = rb_ary_new();
-#line 983 "parser.c"
+#line 984 "parser.c"
{
cs = JSON_array_start;
}
-#line 325 "parser.rl"
+#line 322 "parser.rl"
-#line 989 "parser.c"
+#line 990 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -996,10 +995,11 @@ case 1:
goto st2;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
switch( (*p) ) {
case 13: goto st2;
@@ -1023,12 +1023,12 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 294 "parser.rl"
+#line 291 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
if (np == NULL) {
- goto _out3;
+ p--; {p++; cs = 3; goto _out;}
} else {
rb_ary_push(*result, v);
{p = (( np))-1;}
@@ -1037,9 +1037,9 @@ tr2:
goto st3;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
-#line 1043 "parser.c"
+#line 1045 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -1052,7 +1052,7 @@ case 3:
goto st0;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
switch( (*p) ) {
case 13: goto st4;
@@ -1076,7 +1076,7 @@ case 4:
goto st0;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
switch( (*p) ) {
case 42: goto st6;
@@ -1085,14 +1085,14 @@ case 5:
goto st0;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
if ( (*p) == 42 )
goto st7;
goto st6;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
switch( (*p) ) {
case 42: goto st7;
@@ -1101,14 +1101,14 @@ case 7:
goto st6;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
if ( (*p) == 10 )
goto st4;
goto st8;
st9:
if ( ++p == pe )
- goto _out9;
+ goto _test_eof9;
case 9:
switch( (*p) ) {
case 42: goto st10;
@@ -1117,14 +1117,14 @@ case 9:
goto st0;
st10:
if ( ++p == pe )
- goto _out10;
+ goto _test_eof10;
case 10:
if ( (*p) == 42 )
goto st11;
goto st10;
st11:
if ( ++p == pe )
- goto _out11;
+ goto _test_eof11;
case 11:
switch( (*p) ) {
case 42: goto st11;
@@ -1133,24 +1133,24 @@ case 11:
goto st10;
st12:
if ( ++p == pe )
- goto _out12;
+ goto _test_eof12;
case 12:
if ( (*p) == 10 )
goto st3;
goto st12;
tr4:
-#line 305 "parser.rl"
- { goto _out17; }
+#line 302 "parser.rl"
+ { p--; {p++; cs = 17; goto _out;} }
goto st17;
st17:
if ( ++p == pe )
- goto _out17;
+ goto _test_eof17;
case 17:
-#line 1150 "parser.c"
+#line 1152 "parser.c"
goto st0;
st13:
if ( ++p == pe )
- goto _out13;
+ goto _test_eof13;
case 13:
switch( (*p) ) {
case 42: goto st14;
@@ -1159,14 +1159,14 @@ case 13:
goto st0;
st14:
if ( ++p == pe )
- goto _out14;
+ goto _test_eof14;
case 14:
if ( (*p) == 42 )
goto st15;
goto st14;
st15:
if ( ++p == pe )
- goto _out15;
+ goto _test_eof15;
case 15:
switch( (*p) ) {
case 42: goto st15;
@@ -1175,44 +1175,44 @@ case 15:
goto st14;
st16:
if ( ++p == pe )
- goto _out16;
+ goto _test_eof16;
case 16:
if ( (*p) == 10 )
goto st2;
goto st16;
}
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
- _out8: cs = 8; goto _out;
- _out9: cs = 9; goto _out;
- _out10: cs = 10; goto _out;
- _out11: cs = 11; goto _out;
- _out12: cs = 12; goto _out;
- _out17: cs = 17; goto _out;
- _out13: cs = 13; goto _out;
- _out14: cs = 14; goto _out;
- _out15: cs = 15; goto _out;
- _out16: cs = 16; goto _out;
-
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof11: cs = 11; goto _test_eof;
+ _test_eof12: cs = 12; goto _test_eof;
+ _test_eof17: cs = 17; goto _test_eof;
+ _test_eof13: cs = 13; goto _test_eof;
+ _test_eof14: cs = 14; goto _test_eof;
+ _test_eof15: cs = 15; goto _test_eof;
+ _test_eof16: cs = 16; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 326 "parser.rl"
+#line 323 "parser.rl"
if(cs >= JSON_array_first_final) {
return p + 1;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
static VALUE json_string_unescape(char *p, char *pe)
{
- VALUE result = rb_enc_str_new("", 0, rb_utf8_encoding());
+ VALUE result = rb_str_buf_new(pe - p + 1);
while (p < pe) {
if (*p == '\\') {
@@ -1267,33 +1267,33 @@ static VALUE json_string_unescape(char *p, char *pe)
}
-#line 1271 "parser.c"
+#line 1273 "parser.c"
static const int JSON_string_start = 1;
static const int JSON_string_first_final = 8;
static const int JSON_string_error = 0;
static const int JSON_string_en_main = 1;
-#line 404 "parser.rl"
+#line 401 "parser.rl"
static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
{
int cs = EVIL;
- *result = rb_enc_str_new("", 0, rb_utf8_encoding());
+ *result = rb_str_new("", 0);
-#line 1287 "parser.c"
+#line 1289 "parser.c"
{
cs = JSON_string_start;
}
-#line 412 "parser.rl"
+#line 409 "parser.rl"
json->memo = p;
-#line 1294 "parser.c"
+#line 1296 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -1301,10 +1301,11 @@ case 1:
goto st2;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
switch( (*p) ) {
case 34: goto tr2;
@@ -1314,23 +1315,23 @@ case 2:
goto st0;
goto st2;
tr2:
-#line 396 "parser.rl"
+#line 393 "parser.rl"
{
*result = json_string_unescape(json->memo + 1, p);
- if (NIL_P(*result)) goto _out8; else {p = (( p + 1))-1;}
+ if (NIL_P(*result)) { p--; {p++; cs = 8; goto _out;} } else {p = (( p + 1))-1;}
}
-#line 401 "parser.rl"
- { goto _out8; }
+#line 398 "parser.rl"
+ { p--; {p++; cs = 8; goto _out;} }
goto st8;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
-#line 1330 "parser.c"
+#line 1333 "parser.c"
goto st0;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
if ( (*p) == 117 )
goto st4;
@@ -1339,7 +1340,7 @@ case 3:
goto st2;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 )
@@ -1352,7 +1353,7 @@ case 4:
goto st0;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 )
@@ -1365,7 +1366,7 @@ case 5:
goto st0;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 )
@@ -1378,7 +1379,7 @@ case 6:
goto st0;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 )
@@ -1390,18 +1391,18 @@ case 7:
goto st2;
goto st0;
}
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out8: cs = 8; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
-
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 414 "parser.rl"
+#line 411 "parser.rl"
if (cs >= JSON_string_first_final) {
return p + 1;
@@ -1412,14 +1413,14 @@ case 7:
-#line 1416 "parser.c"
+#line 1419 "parser.c"
static const int JSON_start = 1;
static const int JSON_first_final = 10;
static const int JSON_error = 0;
static const int JSON_en_main = 1;
-#line 448 "parser.rl"
+#line 445 "parser.rl"
/*
@@ -1542,23 +1543,23 @@ static VALUE cParser_parse(VALUE self)
GET_STRUCT;
-#line 1546 "parser.c"
+#line 1549 "parser.c"
{
cs = JSON_start;
}
-#line 570 "parser.rl"
+#line 567 "parser.rl"
p = json->source;
pe = p + json->len;
-#line 1554 "parser.c"
+#line 1557 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
st1:
if ( ++p == pe )
- goto _out1;
+ goto _test_eof1;
case 1:
switch( (*p) ) {
case 13: goto st1;
@@ -1571,10 +1572,11 @@ case 1:
goto st1;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
switch( (*p) ) {
case 42: goto st3;
@@ -1583,14 +1585,14 @@ case 2:
goto st0;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
if ( (*p) == 42 )
goto st4;
goto st3;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
switch( (*p) ) {
case 42: goto st4;
@@ -1599,34 +1601,34 @@ case 4:
goto st3;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
if ( (*p) == 10 )
goto st1;
goto st5;
tr3:
-#line 437 "parser.rl"
+#line 434 "parser.rl"
{
char *np;
json->current_nesting = 1;
np = JSON_parse_array(json, p, pe, &result);
- if (np == NULL) goto _out10; else {p = (( np))-1;}
+ if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
}
goto st10;
tr4:
-#line 430 "parser.rl"
+#line 427 "parser.rl"
{
char *np;
json->current_nesting = 1;
np = JSON_parse_object(json, p, pe, &result);
- if (np == NULL) goto _out10; else {p = (( np))-1;}
+ if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
}
goto st10;
st10:
if ( ++p == pe )
- goto _out10;
+ goto _test_eof10;
case 10:
-#line 1630 "parser.c"
+#line 1634 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
@@ -1637,7 +1639,7 @@ case 10:
goto st0;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
switch( (*p) ) {
case 42: goto st7;
@@ -1646,14 +1648,14 @@ case 6:
goto st0;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
if ( (*p) == 42 )
goto st8;
goto st7;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
switch( (*p) ) {
case 42: goto st8;
@@ -1662,32 +1664,32 @@ case 8:
goto st7;
st9:
if ( ++p == pe )
- goto _out9;
+ goto _test_eof9;
case 9:
if ( (*p) == 10 )
goto st10;
goto st9;
}
- _out1: cs = 1; goto _out;
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out10: cs = 10; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
- _out8: cs = 8; goto _out;
- _out9: cs = 9; goto _out;
-
+ _test_eof1: cs = 1; goto _test_eof;
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 573 "parser.rl"
+#line 570 "parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
@@ -1729,6 +1731,7 @@ static VALUE cParser_source(VALUE self)
void Init_parser()
{
+ rb_require("json/common");
mJSON = rb_define_module("JSON");
mExt = rb_define_module_under(mJSON, "Ext");
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
index c25b1278f7..8325a93795 100644
--- a/ext/json/ext/parser/parser.rl
+++ b/ext/json/ext/parser/parser.rl
@@ -1,9 +1,4 @@
-/* vim: set cin et sw=4 ts=4: */
-
#include "ruby.h"
-#include "ruby/re.h"
-#include "ruby/st.h"
-#include "ruby/encoding.h"
#include "unicode.h"
#define EVIL 0x666
@@ -76,7 +71,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
VALUE v = Qnil;
char *np = JSON_parse_value(json, fpc, pe, &v);
if (np == NULL) {
- fbreak;
+ fhold; fbreak;
} else {
rb_hash_aset(*result, last_name, v);
fexec np;
@@ -85,10 +80,10 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
action parse_name {
char *np = JSON_parse_string(json, fpc, pe, &last_name);
- if (np == NULL) fbreak; else fexec np;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
a_pair = ignore* begin_name >parse_name
ignore* name_separator ignore*
@@ -148,19 +143,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
if (json->allow_nan) {
*result = CNaN;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p - 2);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
}
}
action parse_infinity {
if (json->allow_nan) {
*result = CInfinity;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p - 8);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
}
}
action parse_string {
char *np = JSON_parse_string(json, fpc, pe, result);
- if (np == NULL) fbreak; else fexec np;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
action parse_number {
@@ -169,35 +164,35 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
if (json->allow_nan) {
*result = CMinusInfinity;
fexec p + 10;
- fbreak;
+ fhold; fbreak;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
np = JSON_parse_float(json, fpc, pe, result);
if (np != NULL) fexec np;
np = JSON_parse_integer(json, fpc, pe, result);
if (np != NULL) fexec np;
- fbreak;
+ fhold; fbreak;
}
action parse_array {
char *np;
- json->current_nesting += 1;
+ json->current_nesting++;
np = JSON_parse_array(json, fpc, pe, result);
- json->current_nesting -= 1;
- if (np == NULL) fbreak; else fexec np;
+ json->current_nesting--;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
action parse_object {
char *np;
- json->current_nesting += 1;
+ json->current_nesting++;
np = JSON_parse_object(json, fpc, pe, result);
- json->current_nesting -= 1;
- if (np == NULL) fbreak; else fexec np;
+ json->current_nesting--;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
main := (
Vnull @parse_null |
@@ -231,7 +226,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
write data;
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
main := '-'? ('0' | [1-9][0-9]*) (^[0-9] @exit);
}%%
@@ -259,7 +254,7 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
write data;
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
main := '-'? (
(('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?)
@@ -295,14 +290,14 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
VALUE v = Qnil;
char *np = JSON_parse_value(json, fpc, pe, &v);
if (np == NULL) {
- fbreak;
+ fhold; fbreak;
} else {
rb_ary_push(*result, v);
fexec np;
}
}
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
next_element = value_separator ignore* begin_value >parse_value;
@@ -327,13 +322,13 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
if(cs >= JSON_array_first_final) {
return p + 1;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
static VALUE json_string_unescape(char *p, char *pe)
{
- VALUE result = rb_enc_str_new(0, pe - p + 1, rb_utf8_encoding());
+ VALUE result = rb_str_buf_new(pe - p + 1);
while (p < pe) {
if (*p == '\\') {
@@ -395,10 +390,10 @@ static VALUE json_string_unescape(char *p, char *pe)
action parse_string {
*result = json_string_unescape(json->memo + 1, p);
- if (NIL_P(*result)) fbreak; else fexec p + 1;
+ if (NIL_P(*result)) { fhold; fbreak; } else fexec p + 1;
}
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
main := '"' ((^(["\\] | 0..0x1f) | '\\'["\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^(["\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit;
}%%
@@ -407,7 +402,7 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
{
int cs = EVIL;
- *result = rb_enc_str_new("", 0, rb_utf8_encoding());
+ *result = rb_str_new("", 0);
%% write init;
json->memo = p;
%% write exec;
@@ -431,14 +426,14 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
char *np;
json->current_nesting = 1;
np = JSON_parse_object(json, fpc, pe, &result);
- if (np == NULL) fbreak; else fexec np;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
action parse_array {
char *np;
json->current_nesting = 1;
np = JSON_parse_array(json, fpc, pe, &result);
- if (np == NULL) fbreak; else fexec np;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
main := ignore* (
@@ -574,7 +569,7 @@ static VALUE cParser_parse(VALUE self)
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
@@ -616,6 +611,7 @@ static VALUE cParser_source(VALUE self)
void Init_parser()
{
+ rb_require("json/common");
mJSON = rb_define_module("JSON");
mExt = rb_define_module_under(mJSON, "Ext");
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
diff --git a/ext/json/ext/parser/unicode.c b/ext/json/ext/parser/unicode.c
index f196727354..b2f1e58676 100644
--- a/ext/json/ext/parser/unicode.c
+++ b/ext/json/ext/parser/unicode.c
@@ -1,5 +1,3 @@
-/* vim: set cin et sw=4 ts=4: */
-
#include "unicode.h"
/*
@@ -105,7 +103,7 @@ char *JSON_convert_UTF16_to_UTF8 (
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++tmpPtr;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- ruby_xfree(tmp);
+ ruby_xfree(tmp);
rb_raise(rb_path2class("JSON::ParserError"),
"source sequence is illegal/malformed near %s", source);
}
diff --git a/ext/json/lib/json/add/core.rb b/ext/json/lib/json/add/core.rb
index 630ed6e4b7..7121a77ff1 100644
--- a/ext/json/lib/json/add/core.rb
+++ b/ext/json/lib/json/add/core.rb
@@ -9,14 +9,21 @@ require 'date'
class Time
def self.json_create(object)
- at(*object.values_at('s', 'u'))
+ if usec = object.delete('u') # used to be tv_usec -> tv_nsec
+ object['n'] = usec * 1000
+ end
+ if respond_to?(:tv_nsec)
+ at(*object.values_at('s', 'n'))
+ else
+ at(object['s'], object['n'] / 1000)
+ end
end
def to_json(*args)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
's' => tv_sec,
- 'u' => tv_usec,
+ 'n' => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
}.to_json(*args)
end
end
@@ -26,13 +33,15 @@ class Date
civil(*object.values_at('y', 'm', 'd', 'sg'))
end
+ alias start sg unless method_defined?(:start)
+
def to_json(*args)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
'y' => year,
'm' => month,
'd' => day,
- 'sg' => @sg,
+ 'sg' => start,
}.to_json(*args)
end
end
@@ -41,14 +50,20 @@ class DateTime
def self.json_create(object)
args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
of_a, of_b = object['of'].split('/')
- args << Rational(of_a.to_i, of_b.to_i)
+ if of_b and of_b != '0'
+ args << Rational(of_a.to_i, of_b.to_i)
+ else
+ args << of_a
+ end
args << object['sg']
civil(*args)
end
+ alias start sg unless method_defined?(:start)
+
def to_json(*args)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
'y' => year,
'm' => month,
'd' => day,
@@ -56,7 +71,7 @@ class DateTime
'M' => min,
'S' => sec,
'of' => offset.to_s,
- 'sg' => @sg,
+ 'sg' => start,
}.to_json(*args)
end
end
@@ -68,7 +83,7 @@ class Range
def to_json(*args)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
'a' => [ first, last, exclude_end? ]
}.to_json(*args)
end
@@ -80,8 +95,8 @@ class Struct
end
def to_json(*args)
- klass = self.class.name.to_s
- klass.empty? and raise JSON::JSONError, "Only named structs are supported!"
+ klass = self.class.name
+ klass.nil? and raise JSON::JSONError, "Only named structs are supported!"
{
'json_class' => klass,
'v' => values,
@@ -98,7 +113,7 @@ class Exception
def to_json(*args)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
'm' => message,
'b' => backtrace,
}.to_json(*args)
@@ -112,7 +127,7 @@ class Regexp
def to_json(*)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
'o' => options,
's' => source,
}.to_json
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
index 7bc5ae0656..499fcc0dae 100644
--- a/ext/json/lib/json/common.rb
+++ b/ext/json/lib/json/common.rb
@@ -2,7 +2,7 @@ require 'json/version'
module JSON
class << self
- # If _object_ is string like parse the string and return the parsed result
+ # If _object_ is string-like parse the string and return the parsed result
# as a Ruby data structure. Otherwise generate a JSON text from the Ruby
# data structure object and return it.
#
@@ -184,7 +184,8 @@ module JSON
end
# :stopdoc:
- # I want to deprecate these later, so I'll first be silent about them, and later delete them.
+ # I want to deprecate these later, so I'll first be silent about them, and
+ # later delete them.
alias unparse generate
module_function :unparse
# :startdoc:
@@ -238,7 +239,7 @@ module JSON
# :startdoc:
# Load a ruby data structure from a JSON _source_ and return it. A source can
- # either be a string like object, an IO like object, or an object responding
+ # either be a string-like object, an IO like object, or an object responding
# to the read method. If _proc_ was given, it will be called with any nested
# Ruby object as an argument recursively in depth first order.
#
@@ -327,7 +328,7 @@ module ::Kernel
nil
end
- # If _object_ is string like parse the string and return the parsed result as
+ # If _object_ is string-like parse the string and return the parsed result as
# a Ruby data structure. Otherwise generate a JSON text from the Ruby data
# structure object and return it.
#
@@ -351,4 +352,3 @@ class ::Class
respond_to?(:json_create)
end
end
- # vim: set et sw=2 ts=2:
diff --git a/ext/json/lib/json/editor.rb b/ext/json/lib/json/editor.rb
index 9a65400622..12a7f94591 100644
--- a/ext/json/lib/json/editor.rb
+++ b/ext/json/lib/json/editor.rb
@@ -1360,4 +1360,3 @@ module JSON
end
end
end
- # vim: set et sw=2 ts=2:
diff --git a/ext/json/lib/json/pure/parser.rb b/ext/json/lib/json/pure/parser.rb
index 39bee54269..9b30f15c07 100644
--- a/ext/json/lib/json/pure/parser.rb
+++ b/ext/json/lib/json/pure/parser.rb
@@ -122,9 +122,8 @@ module JSON
def parse_string
if scan(STRING)
return '' if self[1].empty?
- self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do
- c = $&
- if u = UNESCAPE_MAP[c[1]]
+ self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
+ if u = UNESCAPE_MAP[$&[1]]
u
else # \uXXXX
bytes = ''
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
index 3d674ac44f..acf8217048 100644
--- a/ext/json/lib/json/version.rb
+++ b/ext/json/lib/json/version.rb
@@ -1,6 +1,6 @@
module JSON
# JSON version
- VERSION = '1.1.2'
+ VERSION = '1.1.3'
VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
diff --git a/ext/nkf/nkf-utf8/nkf.c b/ext/nkf/nkf-utf8/nkf.c
index a4ad15dcfb..3d690dcb37 100644
--- a/ext/nkf/nkf-utf8/nkf.c
+++ b/ext/nkf/nkf-utf8/nkf.c
@@ -318,7 +318,7 @@ extern POINT _BufferSize;
#endif
struct input_code{
- const char *name;
+ char *name;
nkf_char stat;
nkf_char score;
nkf_char index;
@@ -328,11 +328,10 @@ struct input_code{
int _file_stat;
};
-static const char *input_codename = NULL; /* NULL: unestablished, "": BINARY */
+static char *input_codename = NULL; /* NULL: unestablished, "": BINARY */
static nkf_encoding *input_encoding = NULL;
static nkf_encoding *output_encoding = NULL;
-static int kanji_convert(FILE *f);
#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
/* UCS Mapping
* 0: Shift_JIS, eucJP-ascii
@@ -439,7 +438,7 @@ static nkf_char (*iconv_for_check)(nkf_char c2,nkf_char c1,nkf_char c0) = 0;
#endif
static int guess_f = 0; /* 0: OFF, 1: ON, 2: VERBOSE */
-static void set_input_codename(const char *codename);
+static void set_input_codename(char *codename);
#ifdef EXEC_IO
static int exec_f = 0;
@@ -915,7 +914,8 @@ get_backup_filename(const char *suffix, const char *filename)
}
backup_filename[j] = '\0';
}else{
- backup_filename = malloc(filename_length + strlen(suffix) + 1);
+ j = filename_length + strlen(suffix);
+ backup_filename = malloc(j + 1);
strcpy(backup_filename, filename);
strcat(backup_filename, suffix);
backup_filename[j] = '\0';
@@ -1472,6 +1472,7 @@ s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
nkf_char val;
#endif
static const char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
+ if (0xFC < c1) return 1;
#ifdef SHIFTJIS_CP932
if (!cp932inv_f && is_ibmext_in_sjis(c2)){
val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
@@ -1482,10 +1483,10 @@ s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
}
if (cp932inv_f
&& CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
- nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
- if (c){
- c2 = c >> 8;
- c1 = c & 0xff;
+ val = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
+ if (val){
+ c2 = val >> 8;
+ c1 = val & 0xff;
}
}
#endif /* SHIFTJIS_CP932 */
@@ -2501,6 +2502,7 @@ w_oconv16(nkf_char c2, nkf_char c1)
c1 = val & 0xff;
if (!val) return;
}
+
if (output_endian == ENDIAN_LITTLE){
(*o_putc)(c1);
(*o_putc)(c2);
@@ -3499,7 +3501,7 @@ z_conv(nkf_char c2, nkf_char c1)
if (alpha_f&8 && c2 == 0) {
/* HTML Entity */
- const char *entity = 0;
+ char *entity = 0;
switch (c1){
case '>': entity = "&gt;"; break;
case '<': entity = "&lt;"; break;
@@ -3982,7 +3984,7 @@ debug(const char *str)
#endif
static void
-set_input_codename(const char *codename)
+set_input_codename(char *codename)
{
if (!input_codename) {
input_codename = codename;
@@ -3991,7 +3993,7 @@ set_input_codename(const char *codename)
}
}
-static const char*
+static char*
get_guessed_code(void)
{
if (input_codename && !*input_codename) {
@@ -5251,7 +5253,7 @@ kanji_convert(FILE *f)
{
nkf_char c1=0, c2=0, c3=0, c4=0;
int shift_mode = 0; /* 0, 1, 2, 3 */
- char g2 = 0;
+ int g2 = 0;
int is_8bit = FALSE;
if (input_encoding && !nkf_enc_asciicompat(input_encoding)) {
@@ -6085,9 +6087,9 @@ options(unsigned char *cp)
cp++;
input_endian = ENDIAN_BIG;
}
- enc_idx = enc_idx == UTF_16
+ enc_idx = (enc_idx == UTF_16
? (input_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
- : (input_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
+ : (input_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE));
input_encoding = nkf_enc_from_index(enc_idx);
}
continue;
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index d4285f2069..caa140dc4b 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -463,8 +463,10 @@ static VALUE ossl_ec_key_to_string(VALUE self, int format)
BIO *out;
int i = -1;
int private = 0;
+#if 0 /* unused now */
EVP_CIPHER *cipher = NULL;
char *password = NULL;
+#endif
VALUE str;
Require_EC_KEY(self, ec);
@@ -484,13 +486,18 @@ static VALUE ossl_ec_key_to_string(VALUE self, int format)
switch(format) {
case EXPORT_PEM:
if (private) {
+#if 0 /* unused now */
if (cipher || password)
/* BUG: finish cipher/password key export */
rb_notimplement();
i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password);
+#endif
+ i = PEM_write_bio_ECPrivateKey(out, ec, NULL, NULL, 0, NULL, NULL);
} else {
+#if 0 /* unused now */
if (cipher || password)
rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+#endif
i = PEM_write_bio_EC_PUBKEY(out, ec);
}
@@ -498,13 +505,17 @@ static VALUE ossl_ec_key_to_string(VALUE self, int format)
break;
case EXPORT_DER:
if (private) {
+#if 0 /* unused now */
if (cipher || password)
rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+#endif
i = i2d_ECPrivateKey_bio(out, ec);
} else {
+#if 0 /* unused now */
if (cipher || password)
rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+#endif
i = i2d_EC_PUBKEY_bio(out, ec);
}
diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c
index e99c4e462b..837a506a72 100644
--- a/ext/socket/getaddrinfo.c
+++ b/ext/socket/getaddrinfo.c
@@ -42,7 +42,7 @@
#include <sys/types.h>
#ifndef _WIN32
#include <sys/param.h>
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
# include <net/socket.h>
#else
# include <sys/socket.h>
diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c
index 37f60fc83f..aee81b5356 100644
--- a/ext/socket/getnameinfo.c
+++ b/ext/socket/getnameinfo.c
@@ -38,7 +38,7 @@
#include <stdio.h>
#include <sys/types.h>
#ifndef _WIN32
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
# include <net/socket.h>
#else
# include <sys/socket.h>
diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb
index 46a6655bfc..bb05250805 100644
--- a/ext/socket/mkconstants.rb
+++ b/ext/socket/mkconstants.rb
@@ -143,6 +143,16 @@ IPPROTO_TP
IPPROTO_XTP
IPPROTO_EON
IPPROTO_BIP
+IPPROTO_AH
+IPPROTO_DSTOPTS
+IPPROTO_ESP
+IPPROTO_FRAGMENT
+IPPROTO_HOPOPTS
+IPPROTO_ICMPV6
+IPPROTO_IPV6
+IPPROTO_NONE
+IPPROTO_ROUTING
+
IPPROTO_RAW 255
IPPROTO_MAX
@@ -232,6 +242,7 @@ EAI_FAMILY
EAI_MEMORY
EAI_NODATA
EAI_NONAME
+EAI_OVERFLOW
EAI_SERVICE
EAI_SOCKTYPE
EAI_SYSTEM
@@ -242,6 +253,7 @@ EAI_MAX
AI_PASSIVE
AI_CANONNAME
AI_NUMERICHOST
+AI_NUMERICSERV
AI_MASK
AI_ALL
AI_V4MAPPED_CFG
@@ -288,3 +300,6 @@ IPV6_RTHDR_TYPE_0
IPV6_RECVPATHMTU
IPV6_TCLASS
IPV6_USE_MIN_MTU
+
+INET_ADDRSTRLEN
+INET6_ADDRSTRLEN
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index c753f19de3..698bc60996 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -28,7 +28,7 @@
#endif
#ifndef _WIN32
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
# include <net/socket.h>
#else
# include <sys/socket.h>
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index 8b20e62b0c..7cffda2aed 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -8797,7 +8797,7 @@ void
Init_win32ole()
{
ary_ole_event = rb_ary_new();
- rb_register_mark_object(ary_ole_event);
+ rb_gc_register_mark_object(ary_ole_event);
id_events = rb_intern("events");
com_vtbl.QueryInterface = QueryInterface;
@@ -8816,7 +8816,7 @@ Init_win32ole()
message_filter.MessagePending = mf_MessagePending;
com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
- rb_register_mark_object(com_hash);
+ rb_gc_register_mark_object(com_hash);
cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);
diff --git a/gc.c b/gc.c
index a5e941f1c8..5a1d8723a8 100644
--- a/gc.c
+++ b/gc.c
@@ -722,7 +722,7 @@ rb_gc_disable(void)
VALUE rb_mGC;
void
-rb_register_mark_object(VALUE obj)
+rb_gc_register_mark_object(VALUE obj)
{
VALUE ary = GET_THREAD()->vm->mark_object_ary;
rb_ary_push(ary, obj);
@@ -1539,7 +1539,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
case T_COMPLEX:
gc_mark(objspace, obj->as.complex.real, lev);
- gc_mark(objspace, obj->as.complex.image, lev);
+ gc_mark(objspace, obj->as.complex.imag, lev);
break;
case T_STRUCT:
diff --git a/hash.c b/hash.c
index d71d395d5c..694b619529 100644
--- a/hash.c
+++ b/hash.c
@@ -39,8 +39,6 @@ static ID id_hash, id_yield, id_default;
static int
rb_any_cmp(VALUE a, VALUE b)
{
- VALUE args[2];
-
if (a == b) return 0;
if (FIXNUM_P(a) && FIXNUM_P(b)) {
return a != b;
@@ -54,8 +52,6 @@ rb_any_cmp(VALUE a, VALUE b)
return a != b;
}
- args[0] = a;
- args[1] = b;
return !rb_eql(a, b);
}
diff --git a/include/ruby/defines.h b/include/ruby/defines.h
index 1a0274ec81..d580135233 100644
--- a/include/ruby/defines.h
+++ b/include/ruby/defines.h
@@ -198,7 +198,7 @@ void xfree(void*);
#include "vms/vms.h"
#endif
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
#include <net/socket.h> /* intern.h needs fd_set definition */
#endif
diff --git a/include/ruby/encoding.h b/include/ruby/encoding.h
index a69940e267..f2f7ba19b5 100644
--- a/include/ruby/encoding.h
+++ b/include/ruby/encoding.h
@@ -129,11 +129,11 @@ int rb_enc_codelen(int code, rb_encoding *enc);
/* code,ptr,encoding -> write buf */
#define rb_enc_mbcput(c,buf,enc) ONIGENC_CODE_TO_MBC(enc,c,(UChar*)(buf))
-/* ptr, ptr, encoding -> prev_char */
-#define rb_enc_prev_char(s,p,enc) (char *)onigenc_get_prev_char_head(enc,(UChar*)(s),(UChar*)(p))
-/* ptr, ptr, encoding -> next_char */
-#define rb_enc_left_char_head(s,p,enc) (char *)onigenc_get_left_adjust_char_head(enc,(UChar*)(s),(UChar*)(p))
-#define rb_enc_right_char_head(s,p,enc) (char *)onigenc_get_right_adjust_char_head(enc,(UChar*)(s),(UChar*)(p))
+/* start, ptr, end, encoding -> prev_char */
+#define rb_enc_prev_char(s,p,e,enc) (char *)onigenc_get_prev_char_head(enc,(UChar*)(s),(UChar*)(p),(UChar*)(e))
+/* start, ptr, end, encoding -> next_char */
+#define rb_enc_left_char_head(s,p,e,enc) (char *)onigenc_get_left_adjust_char_head(enc,(UChar*)(s),(UChar*)(p),(UChar*)(e))
+#define rb_enc_right_char_head(s,p,e,enc) (char *)onigenc_get_right_adjust_char_head(enc,(UChar*)(s),(UChar*)(p),(UChar*)(e))
/* ptr, ptr, encoding -> newline_or_not */
#define rb_enc_is_newline(p,end,enc) ONIGENC_IS_MBC_NEWLINE(enc,(UChar*)(p),(UChar*)(end))
diff --git a/include/ruby/oniguruma.h b/include/ruby/oniguruma.h
index 2e3b2bf293..bc6905edaa 100644
--- a/include/ruby/oniguruma.h
+++ b/include/ruby/oniguruma.h
@@ -164,7 +164,7 @@ typedef struct OnigEncodingTypeST {
int (*property_name_to_ctype)(struct OnigEncodingTypeST* enc, OnigUChar* p, OnigUChar* end);
int (*is_code_ctype)(OnigCodePoint code, OnigCtype ctype, struct OnigEncodingTypeST* enc);
int (*get_ctype_code_range)(OnigCtype ctype, OnigCodePoint* sb_out, const OnigCodePoint* ranges[], struct OnigEncodingTypeST* enc);
- OnigUChar* (*left_adjust_char_head)(const OnigUChar* start, const OnigUChar* p, struct OnigEncodingTypeST* enc);
+ OnigUChar* (*left_adjust_char_head)(const OnigUChar* start, const OnigUChar* p, const OnigUChar* end, struct OnigEncodingTypeST* enc);
int (*is_allowed_reverse_match)(const OnigUChar* p, const OnigUChar* end, struct OnigEncodingTypeST* enc);
int ruby_encoding_index;
} OnigEncodingType;
@@ -219,14 +219,14 @@ ONIG_EXTERN OnigEncodingType OnigEncodingASCII;
(enc)->mbc_case_fold(flag,(const OnigUChar** )pp,end,buf,enc)
#define ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc,s,end) \
(enc)->is_allowed_reverse_match(s,end,enc)
-#define ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,start,s) \
- (enc)->left_adjust_char_head(start, s, enc)
+#define ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,start,s,end) \
+ (enc)->left_adjust_char_head(start, s, end, enc)
#define ONIGENC_APPLY_ALL_CASE_FOLD(enc,case_fold_flag,f,arg) \
(enc)->apply_all_case_fold(case_fold_flag,f,arg,enc)
#define ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc,case_fold_flag,p,end,acs) \
(enc)->get_case_fold_codes_by_str(case_fold_flag,p,end,acs,enc)
-#define ONIGENC_STEP_BACK(enc,start,s,n) \
- onigenc_step_back((enc),(start),(s),(n))
+#define ONIGENC_STEP_BACK(enc,start,s,end,n) \
+ onigenc_step_back((enc),(start),(s),(end),(n))
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n) (n)
#define ONIGENC_MBCLEN_CHARFOUND_P(r) (0 < (r))
@@ -290,7 +290,7 @@ int onigenc_mbclen_approximate P_((const OnigUChar* p,const OnigUChar* e, struct
(enc)->get_ctype_code_range(ctype,sbout,ranges,enc)
ONIG_EXTERN
-OnigUChar* onigenc_step_back P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, int n));
+OnigUChar* onigenc_step_back P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end, int n));
/* encoding API */
@@ -303,13 +303,13 @@ OnigEncoding onigenc_get_default_encoding P_((void));
ONIG_EXTERN
void onigenc_set_default_caseconv_table P_((const OnigUChar* table));
ONIG_EXTERN
-OnigUChar* onigenc_get_right_adjust_char_head_with_prev P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar** prev));
+OnigUChar* onigenc_get_right_adjust_char_head_with_prev P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end, const OnigUChar** prev));
ONIG_EXTERN
-OnigUChar* onigenc_get_prev_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s));
+OnigUChar* onigenc_get_prev_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end));
ONIG_EXTERN
-OnigUChar* onigenc_get_left_adjust_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s));
+OnigUChar* onigenc_get_left_adjust_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end));
ONIG_EXTERN
-OnigUChar* onigenc_get_right_adjust_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s));
+OnigUChar* onigenc_get_right_adjust_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end));
ONIG_EXTERN
int onigenc_strlen P_((OnigEncoding enc, const OnigUChar* p, const OnigUChar* end));
ONIG_EXTERN
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index d8ae11b204..eb80bce4c2 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -650,7 +650,7 @@ struct RRational {
struct RComplex {
struct RBasic basic;
VALUE real;
- VALUE image;
+ VALUE imag;
};
struct RData {
@@ -851,7 +851,7 @@ void rb_define_alias(VALUE,const char*,const char*);
void rb_define_attr(VALUE,const char*,int,int);
void rb_global_variable(VALUE*);
-void rb_register_mark_object(VALUE);
+void rb_gc_register_mark_object(VALUE);
void rb_gc_register_address(VALUE*);
void rb_gc_unregister_address(VALUE*);
@@ -982,6 +982,7 @@ RUBY_EXTERN VALUE rb_cCont;
RUBY_EXTERN VALUE rb_cDir;
RUBY_EXTERN VALUE rb_cData;
RUBY_EXTERN VALUE rb_cFalseClass;
+RUBY_EXTERN VALUE rb_cEncoding;
RUBY_EXTERN VALUE rb_cEnumerator;
RUBY_EXTERN VALUE rb_cFile;
RUBY_EXTERN VALUE rb_cFixnum;
diff --git a/inits.c b/inits.c
index 291fcb11bc..457d361a10 100644
--- a/inits.c
+++ b/inits.c
@@ -34,7 +34,6 @@ void Init_marshal(void);
void Init_Numeric(void);
void Init_Object(void);
void Init_pack(void);
-void Init_Precision(void);
void Init_sym(void);
void Init_process(void);
void Init_RandomSeed(void);
@@ -66,7 +65,6 @@ rb_call_inits()
Init_Encoding();
Init_Comparable();
Init_Enumerable();
- Init_Precision();
Init_String();
Init_Exception();
Init_eval();
diff --git a/io.c b/io.c
index 2ed7647de5..2ea192cf4c 100644
--- a/io.c
+++ b/io.c
@@ -2177,13 +2177,14 @@ rb_io_getline_1(VALUE rs, long limit, VALUE io)
else
enc = io_input_encoding(fptr);
while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
- const char *s, *p, *pp;
+ const char *s, *p, *pp, *e;
if (c == newline) {
if (RSTRING_LEN(str) < rslen) continue;
s = RSTRING_PTR(str);
- p = s + RSTRING_LEN(str) - rslen;
- pp = rb_enc_left_char_head(s, p, enc);
+ e = s + RSTRING_LEN(str);
+ p = e - rslen;
+ pp = rb_enc_left_char_head(s, p, e, enc);
if (pp != p) continue;
if (!rspara) rscheck(rsptr, rslen, rs);
if (memcmp(p, rsptr, rslen) == 0) break;
@@ -2191,7 +2192,7 @@ rb_io_getline_1(VALUE rs, long limit, VALUE io)
if (limit == 0) {
s = RSTRING_PTR(str);
p = s + RSTRING_LEN(str);
- pp = rb_enc_left_char_head(s, p-1, enc);
+ pp = rb_enc_left_char_head(s, p-1, p, enc);
if (extra_limit &&
MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
/* relax the limit while incomplete character.
@@ -2256,7 +2257,7 @@ rb_io_gets(VALUE io)
* to <code>$_</code>. Returns <code>nil</code> if called at end of
* file. If the first argument is an integer, or optional second
* argument is given, the returning string would not be longer than the
- * given value.
+ * given value in bytes.
*
* File.new("testfile").gets #=> "This is line one\n"
* $_ #=> "This is line one\n"
@@ -2362,8 +2363,8 @@ rb_io_readline(int argc, VALUE *argv, VALUE io)
* <i>sep</i> is <code>nil</code>, the rest of the stream is returned
* as a single record. If the first argument is an integer, or
* optional second argument is given, the returning string would not be
- * longer than the given value. The stream must be opened for reading
- * or an <code>IOError</code> will be raised.
+ * longer than the given value in bytes. The stream must be opened for
+ * reading or an <code>IOError</code> will be raised.
*
* f = File.new("testfile")
* f.readlines[0] #=> "This is line one\n"
@@ -2747,7 +2748,7 @@ rb_io_getbyte(VALUE io)
* call-seq:
* ios.readbyte => fixnum
*
- * Reads a character as with <code>IO#getc</code>, but raises an
+ * Reads a byte as with <code>IO#getbyte</code>, but raises an
* <code>EOFError</code> on end of file.
*/
@@ -3863,7 +3864,7 @@ validate_enc_binmode(int fmode, rb_encoding *enc, rb_encoding *enc2)
}
static void
-rb_io_extract_modeenc(VALUE *vmode_p, VALUE opthash,
+rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
{
VALUE vmode;
@@ -3871,7 +3872,7 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE opthash,
rb_encoding *enc, *enc2;
int ecflags;
VALUE ecopts;
- int has_enc = 0;
+ int has_enc = 0, has_vmode = 0;
VALUE intmode;
vmode = *vmode_p;
@@ -3890,6 +3891,8 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE opthash,
}
else {
const char *p;
+
+ vmode_handle:
SafeStringValue(vmode);
p = StringValueCStr(vmode);
fmode = rb_io_modestr_fmode(p);
@@ -3908,15 +3911,38 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE opthash,
else {
VALUE v;
v = rb_hash_aref(opthash, sym_textmode);
- if (RTEST(v))
+ if (!NIL_P(v))
fmode |= FMODE_TEXTMODE;
v = rb_hash_aref(opthash, sym_binmode);
- if (RTEST(v)) {
+ if (!NIL_P(v)) {
fmode |= FMODE_BINMODE;
#ifdef O_BINARY
oflags |= O_BINARY;
#endif
}
+ if (!has_vmode) {
+ v = rb_hash_aref(opthash, sym_mode);
+ if (!NIL_P(v)) {
+ if (!NIL_P(vmode)) {
+ rb_raise(rb_eArgError, "mode specified twice");
+ }
+ has_vmode = 1;
+ vmode = v;
+ goto vmode_handle;
+ }
+ }
+ v = rb_hash_aref(opthash, sym_perm);
+ if (!NIL_P(v)) {
+ if (vperm_p) {
+ if (!NIL_P(*vperm_p)) {
+ rb_raise(rb_eArgError, "perm specified twice");
+ }
+ *vperm_p = v;
+ }
+ else {
+ /* perm no use, just ignore */
+ }
+ }
ecflags = rb_econv_prepare_opts(opthash, &ecopts);
if (io_extract_encoding_option(opthash, &enc, &enc2)) {
@@ -4587,7 +4613,7 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
opt = pop_last_hash(&argc, &argv);
rb_scan_args(argc, argv, "11", &pname, &pmode);
- rb_io_extract_modeenc(&pmode, opt, &oflags, &fmode, &convconfig);
+ rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
modestr = rb_io_oflags_modestr(oflags);
tmp = rb_check_array_type(pname);
@@ -4630,6 +4656,7 @@ rb_scan_open_args(int argc, VALUE *argv,
opt = pop_last_hash(&argc, &argv);
rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
+ FilePathValue(fname);
#if defined _WIN32 || defined __APPLE__
{
static rb_encoding *fs_encoding;
@@ -4649,9 +4676,8 @@ rb_scan_open_args(int argc, VALUE *argv,
}
}
#endif
- FilePathValue(fname);
- rb_io_extract_modeenc(&vmode, opt, &oflags, &fmode, convconfig_p);
+ rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
perm = NIL_P(vperm) ? 0666 : NUM2UINT(vperm);
@@ -4908,7 +4934,7 @@ rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
convconfig_t convconfig;
mode_t perm;
- rb_io_extract_modeenc(&vmode, opt, &oflags, &fmode, &convconfig);
+ rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
perm = NIL_P(vperm) ? 0666 : NUM2UINT(vperm);
if (!NIL_P(cmd = check_pipe_command(filename))) {
@@ -5595,7 +5621,7 @@ rb_io_initialize(int argc, VALUE *argv, VALUE io)
opt = pop_last_hash(&argc, &argv);
rb_scan_args(argc, argv, "11", &fnum, &vmode);
- rb_io_extract_modeenc(&vmode, opt, &oflags, &fmode, &convconfig);
+ rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
fd = NUM2INT(fnum);
UPDATE_MAXFD(fd);
@@ -5993,9 +6019,9 @@ static VALUE argf_gets(int, VALUE *, VALUE);
* reads the input one paragraph at a time, where paragraphs are
* divided by two consecutive newlines. If the first argument is an
* integer, or optional second argument is given, the returning string
- * would not be longer than the given value. If multiple filenames are
- * present in +ARGV+, +gets(nil)+ will read the contents one file at a
- * time.
+ * would not be longer than the given value in bytes. If multiple
+ * filenames are present in +ARGV+, +gets(nil)+ will read the contents
+ * one file at a time.
*
* ARGV << "testfile"
* print while gets
@@ -6773,7 +6799,6 @@ static void
open_key_args(int argc, VALUE *argv, struct foreach_arg *arg)
{
VALUE opt, v;
- VALUE vmode, vperm;
FilePathValue(argv[0]);
arg->io = 0;
@@ -6800,15 +6825,7 @@ open_key_args(int argc, VALUE *argv, struct foreach_arg *arg)
arg->io = rb_io_open_with_args(RARRAY_LEN(args), RARRAY_PTR(args));
return;
}
- vmode = Qnil;
- vperm = INT2NUM(O_RDONLY);
- v = rb_hash_aref(opt, sym_mode);
- if (!NIL_P(v))
- vmode = v;
- v = rb_hash_aref(opt, sym_perm);
- if (!NIL_P(v))
- vperm = v;
- arg->io = rb_io_open(argv[0], vmode, vperm, opt);
+ arg->io = rb_io_open(argv[0], Qnil, INT2NUM(O_RDONLY), opt);
}
static VALUE
@@ -8179,8 +8196,8 @@ Init_IO(void)
rb_output_fs = Qnil;
rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
- rb_global_variable(&rb_default_rs);
rb_rs = rb_default_rs = rb_str_new2("\n");
+ rb_gc_register_mark_object(rb_default_rs);
rb_output_rs = Qnil;
OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
diff --git a/lib/cmath.rb b/lib/cmath.rb
index 55995879e6..d293401804 100644
--- a/lib/cmath.rb
+++ b/lib/cmath.rb
@@ -25,17 +25,17 @@ module CMath
alias atanh! atanh
def exp(z)
- if z.scalar?
+ if z.real?
exp!(z)
else
- Complex(exp!(z.real) * cos!(z.image),
- exp!(z.real) * sin!(z.image))
+ Complex(exp!(z.real) * cos!(z.imag),
+ exp!(z.real) * sin!(z.imag))
end
end
def log(*args)
z, b = args
- if z.scalar? and z >= 0 and (b.nil? or b >= 0)
+ if z.real? and z >= 0 and (b.nil? or b >= 0)
log!(*args)
else
r, theta = z.polar
@@ -48,7 +48,7 @@ module CMath
end
def log10(z)
- if z.scalar?
+ if z.real?
log10!(z)
else
log(z) / log!(10)
@@ -56,14 +56,14 @@ module CMath
end
def sqrt(z)
- if z.scalar?
+ if z.real?
if z >= 0
sqrt!(z)
else
- Complex(0,sqrt!(-z))
+ Complex(0, sqrt!(-z))
end
else
- if z.image < 0
+ if z.imag < 0
sqrt(z.conjugate).conjugate
else
r = z.abs
@@ -74,25 +74,25 @@ module CMath
end
def sin(z)
- if z.scalar?
+ if z.real?
sin!(z)
else
- Complex(sin!(z.real) * cosh!(z.image),
- cos!(z.real) * sinh!(z.image))
+ Complex(sin!(z.real) * cosh!(z.imag),
+ cos!(z.real) * sinh!(z.imag))
end
end
def cos(z)
- if z.scalar?
+ if z.real?
cos!(z)
else
- Complex(cos!(z.real) * cosh!(z.image),
- -sin!(z.real) * sinh!(z.image))
+ Complex(cos!(z.real) * cosh!(z.imag),
+ -sin!(z.real) * sinh!(z.imag))
end
end
def tan(z)
- if z.scalar?
+ if z.real?
tan!(z)
else
sin(z)/cos(z)
@@ -100,25 +100,25 @@ module CMath
end
def sinh(z)
- if z.scalar?
+ if z.real?
sinh!(z)
else
- Complex(sinh!(z.real) * cos!(z.image),
- cosh!(z.real) * sin!(z.image))
+ Complex(sinh!(z.real) * cos!(z.imag),
+ cosh!(z.real) * sin!(z.imag))
end
end
def cosh(z)
- if z.scalar?
+ if z.real?
cosh!(z)
else
- Complex(cosh!(z.real) * cos!(z.image),
- sinh!(z.real) * sin!(z.image))
+ Complex(cosh!(z.real) * cos!(z.imag),
+ sinh!(z.real) * sin!(z.imag))
end
end
def tanh(z)
- if z.scalar?
+ if z.real?
tanh!(z)
else
sinh(z) / cosh(z)
@@ -126,39 +126,39 @@ module CMath
end
def asin(z)
- if z.scalar? and z >= -1 and z <= 1
+ if z.real? and z >= -1 and z <= 1
asin!(z)
else
- -1.0.im * log(1.0.im * z + sqrt(1.0 - z * z))
+ Complex(0, -1.0) * log(Complex(0, 1.0) * z + sqrt(1.0 - z * z))
end
end
def acos(z)
- if z.scalar? and z >= -1 and z <= 1
+ if z.real? and z >= -1 and z <= 1
acos!(z)
else
- -1.0.im * log(z + 1.0.im * sqrt(1.0 - z * z))
+ Complex(0, -1.0) * log(z + Complex(0, 1.0) * sqrt(1.0 - z * z))
end
end
def atan(z)
- if z.scalar?
+ if z.real?
atan!(z)
else
- 1.0.im * log((1.0.im + z) / (1.0.im - z)) / 2.0
+ Complex(0, 1.0) * log((Complex(0, 1.0) + z) / (Complex(0, 1.0) - z)) / 2.0
end
end
def atan2(y,x)
- if y.scalar? and x.scalar?
+ if y.real? and x.real?
atan2!(y,x)
else
- -1.0.im * log((x + 1.0.im * y) / sqrt(x * x + y * y))
+ Complex(0, -1.0) * log((x + Complex(0, 1.0) * y) / sqrt(x * x + y * y))
end
end
def acosh(z)
- if z.scalar? and z >= 1
+ if z.real? and z >= 1
acosh!(z)
else
log(z + sqrt(z * z - 1.0))
@@ -166,7 +166,7 @@ module CMath
end
def asinh(z)
- if z.scalar?
+ if z.real?
asinh!(z)
else
log(z + sqrt(1.0 + z * z))
@@ -174,7 +174,7 @@ module CMath
end
def atanh(z)
- if z.scalar? and z >= -1 and z <= 1
+ if z.real? and z >= -1 and z <= 1
atanh!(z)
else
log((1.0 + z) / (1.0 - z)) / 2.0
diff --git a/lib/complex.rb b/lib/complex.rb
index 1845f30b1f..301879143f 100644
--- a/lib/complex.rb
+++ b/lib/complex.rb
@@ -1,10 +1,24 @@
require 'cmath'
-Object.instance_eval{remove_const :Math}
-Math = CMath
+unless defined?(Math.exp!)
+ Object.instance_eval{remove_const :Math}
+ Math = CMath
+end
def Complex.generic? (other)
other.kind_of?(Integer) ||
other.kind_of?(Float) ||
other.kind_of?(Rational)
end
+
+class Complex
+
+ alias image imag
+
+end
+
+class Numeric
+
+ def im() Complex(0, self) end
+
+end
diff --git a/lib/csv.rb b/lib/csv.rb
index f60d5b1cb0..dccee6cbe8 100644
--- a/lib/csv.rb
+++ b/lib/csv.rb
@@ -1,5 +1,5 @@
-#!/usr/local/bin/ruby -w
-
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# = csv.rb -- CSV Reading and Writing
#
# Created by James Edward Gray II on 2005-10-31.
@@ -37,6 +37,7 @@
#
# === CSV Parsing
#
+# * This parser is m17n aware. See CSV for full details.
# * This library has a stricter parser and will throw MalformedCSVErrors on
# problematic data.
# * This library has a less liberal idea of a line ending than CSV. What you
@@ -91,7 +92,6 @@
require "forwardable"
require "English"
-require "enumerator"
require "date"
require "stringio"
@@ -130,7 +130,7 @@ require "stringio"
#
# === To a File
#
-# CSV.open("path/to/file.csv", "w") do |csv|
+# CSV.open("path/to/file.csv", "wb") do |csv|
# csv << ["row", "of", "CSV", "data"]
# csv << ["another", "row"]
# # ...
@@ -155,9 +155,51 @@ require "stringio"
# CSV(csv = "") { |csv_str| csv_str << %w{my data here} } # to a String
# CSV($stderr) { |csv_err| csv_err << %w{my data here} } # to $stderr
#
+# == CSV and Character Encodings (M17n or Multilingualization)
+#
+# This new CSV parser is m17n savvy. The parser works in the Encoding of the IO
+# or String object being read from or written to. Your data is never transcoded
+# (unless you ask Ruby to transcode it for you) and will literally be parsed in
+# the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the
+# Encoding of your data. This is accomplished by transcoding the parser itself
+# into your Encoding.
+#
+# Some transcoding must take place, of course, to accomplish this multiencoding
+# support. For example, <tt>:col_sep</tt>, <tt>:row_sep</tt>, and
+# <tt>:quote_char</tt> must be transcoded to match your data. Hopefully this
+# makes the entire process feel transparent, since CSV's defaults should just
+# magically work for you data. However, you can set these values manually in
+# the target Encoding to avoid the translation.
+#
+# It's also important to note that while all of CSV's core parser is now
+# Encoding agnostic, some features are not. For example, the built-in
+# converters will try to transcode data to UTF-8 before making conversions.
+# Again, you can provide custom converters that are aware of your Encodings to
+# avoid this translation. It's just too hard for me to support native
+# conversions in all of Ruby's Encodings.
+#
+# Anyway, the practical side of this is simple: make sure IO and String objects
+# passed into CSV have the proper Encoding set and everything should just work.
+# CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(),
+# CSV::read(), and CSV::readlines()) do allow you to specify the Encoding.
+#
+# One minor exception comes when generating CSV into a String with an Encoding
+# that is not ASCII compatible. There's no existing data for CSV to use to
+# prepare itself and thus you will probably need to manually specify the desired
+# Encoding for most of those cases. It will try to guess using the fields in a
+# row of output though, when using CSV::generate_line() or Array#to_csv().
+#
+# I try to point out any other Encoding issues in the documentation of methods
+# as they come up.
+#
+# This has been tested to the best of my ability with all non-"dummy" Encodings
+# Ruby ships with. However, it is brave new code and may have some bugs.
+# Please feel free to {report}[mailto:james@grayproductions.net] any issues you
+# find with it.
+#
class CSV
# The version of the installed library.
- VERSION = "2.0.0".freeze
+ VERSION = "2.4.0".freeze
#
# A CSV::Row is part Array and part Hash. It retains an order for the fields
@@ -188,9 +230,9 @@ class CSV
# handle extra headers or fields
@row = if headers.size > fields.size
- headers.each_with_index.map { |header, i| [header, fields[i]] }
+ headers.zip(fields)
else
- fields.each_with_index.map { |field, i| [headers[i], field] }
+ fields.zip(headers).map { |pair| pair.reverse }
end
end
@@ -444,6 +486,17 @@ class CSV
fields.to_csv(options)
end
alias_method :to_s, :to_csv
+
+ # A summary of fields, by header, in an ASCII-8BIT String.
+ def inspect
+ str = ["#<", self.class.to_s]
+ each do |header, field|
+ str << " " << (header.is_a?(Symbol) ? header.to_s : header.inspect) <<
+ ":" << field.inspect
+ end
+ str << ">"
+ str.map { |s| s.encode("ASCII-8BIT") }.join
+ end
end
#
@@ -775,6 +828,11 @@ class CSV
end.join
end
alias_method :to_s, :to_csv
+
+ # Shows the mode and size of this table in a US-ASCII String.
+ def inspect
+ "#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>"
+ end
end
# The error thrown when the parser encounters illegal CSV formatting.
@@ -799,6 +857,10 @@ class CSV
DateTimeMatcher =
/ \A(?: (\w+,?\s+)?\w+\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},?\s+\d{2,4} |
\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2} )\z /x
+
+ # The encoding used by all converters.
+ ConverterEncoding = Encoding.find("UTF-8")
+
#
# This Hash holds the built-in converters of CSV that can be accessed by name.
# You can select Converters with CSV.convert() or through the +options+ Hash
@@ -813,20 +875,38 @@ class CSV
# <b><tt>:all</tt></b>:: All built-in converters. A combination of
# <tt>:date_time</tt> and <tt>:numeric</tt>.
#
+ # All built-in converters transcode field data to UTF-8 before attempting a
+ # conversion. If your data cannot be transcoded to UTF-8 the conversion will
+ # fail and the field will remain unchanged.
+ #
# This Hash is intentionally left unfrozen and users should feel free to add
# values to it that can be accessed by all CSV objects.
#
# To add a combo field, the value should be an Array of names. Combo fields
# can be nested with other combo fields.
#
- Converters = { :integer => lambda { |f| Integer(f) rescue f },
- :float => lambda { |f| Float(f) rescue f },
+ Converters = { :integer => lambda { |f|
+ Integer(f.encode(ConverterEncoding)) rescue f
+ },
+ :float => lambda { |f|
+ Float(f.encode(ConverterEncoding)) rescue f
+ },
:numeric => [:integer, :float],
:date => lambda { |f|
- f =~ DateMatcher ? (Date.parse(f) rescue f) : f
+ begin
+ e = f.encode(ConverterEncoding)
+ e =~ DateMatcher ? Date.parse(e) : f
+ rescue # encoding conversion or date parse errors
+ f
+ end
},
:date_time => lambda { |f|
- f =~ DateTimeMatcher ? (DateTime.parse(f) rescue f) : f
+ begin
+ e = f.encode(ConverterEncoding)
+ e =~ DateTimeMatcher ? DateTime.parse(e) : f
+ rescue # encoding conversion or date parse errors
+ f
+ end
},
:all => [:date_time, :numeric] }
@@ -840,6 +920,10 @@ class CSV
# replaced with underscores, non-word characters
# are dropped, and finally to_sym() is called.
#
+ # All built-in header converters transcode header data to UTF-8 before
+ # attempting a conversion. If your data cannot be transcoded to UTF-8 the
+ # conversion will fail and the header will remain unchanged.
+ #
# This Hash is intetionally left unfrozen and users should feel free to add
# values to it that can be accessed by all CSV objects.
#
@@ -847,9 +931,10 @@ class CSV
# can be nested with other combo fields.
#
HeaderConverters = {
- :downcase => lambda { |h| h.downcase },
+ :downcase => lambda { |h| h.encode(ConverterEncoding).downcase },
:symbol => lambda { |h|
- h.downcase.tr(" ", "_").delete("^a-z0-9_").to_sym
+ h.encode(ConverterEncoding).
+ downcase.tr(" ", "_").delete("^a-z0-9_").to_sym
}
}
@@ -859,6 +944,7 @@ class CSV
# <b><tt>:col_sep</tt></b>:: <tt>","</tt>
# <b><tt>:row_sep</tt></b>:: <tt>:auto</tt>
# <b><tt>:quote_char</tt></b>:: <tt>'"'</tt>
+ # <b><tt>:field_size_limit</tt></b>:: +nil+
# <b><tt>:converters</tt></b>:: +nil+
# <b><tt>:unconverted_fields</tt></b>:: +nil+
# <b><tt>:headers</tt></b>:: +false+
@@ -870,6 +956,7 @@ class CSV
DEFAULT_OPTIONS = { :col_sep => ",",
:row_sep => :auto,
:quote_char => '"',
+ :field_size_limit => nil,
:converters => nil,
:unconverted_fields => nil,
:headers => false,
@@ -879,6 +966,31 @@ class CSV
:force_quotes => false }.freeze
#
+ # This method will return a CSV instance, just like CSV::new(), but the
+ # instance will be cached and returned for all future calls to this method for
+ # the same +data+ object (tested by Object#object_id()) with the same
+ # +options+.
+ #
+ # If a block is given, the instance is passed to the block and the return
+ # value becomes the return value of the block.
+ #
+ def self.instance(data = $stdout, options = Hash.new)
+ # create a _signature_ for this method call, data object and options
+ sig = [data.object_id] +
+ options.values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s })
+
+ # fetch or create the instance for this signature
+ @@instances ||= Hash.new
+ instance = (@@instances[sig] ||= new(data, options))
+
+ if block_given?
+ yield instance # run block, if given, returning result
+ else
+ instance # or return the instance
+ end
+ end
+
+ #
# This method allows you to serialize an Array of Ruby objects to a String or
# File of CSV data. This is not as powerful as Marshal or YAML, but perhaps
# useful for spreadsheet and database interaction.
@@ -959,6 +1071,53 @@ class CSV
end
#
+ # This method is the reading counterpart to CSV::dump(). See that method for
+ # a detailed description of the process.
+ #
+ # You can customize loading by adding a class method called csv_load() which
+ # will be passed a Hash of meta information, an Array of headers, and an Array
+ # of fields for the object the method is expected to return.
+ #
+ # Remember that all fields will be Strings after this load. If you need
+ # something else, use +options+ to setup converters or provide a custom
+ # csv_load() implementation.
+ #
+ def self.load(io_or_str, options = Hash.new)
+ csv = new(io_or_str, options)
+
+ # load meta information
+ meta = Hash[*csv.shift]
+ cls = meta["class".encode(csv.encoding)].split("::".encode(csv.encoding)).
+ inject(Object) do |c, const|
+ c.const_get(const)
+ end
+
+ # load headers
+ headers = csv.shift
+
+ # unserialize each object stored in the file
+ results = csv.inject(Array.new) do |all, row|
+ begin
+ obj = cls.csv_load(meta, headers, row)
+ rescue NoMethodError
+ obj = cls.allocate
+ headers.zip(row) do |name, value|
+ if name[0] == ?@
+ obj.instance_variable_set(name, value)
+ else
+ obj.send(name, value)
+ end
+ end
+ end
+ all << obj
+ end
+
+ csv.close unless io_or_str.is_a? String
+
+ results
+ end
+
+ #
# :call-seq:
# filter( options = Hash.new ) { |row| ... }
# filter( input, options = Hash.new ) { |row| ... }
@@ -1014,10 +1173,20 @@ class CSV
# pass a +path+ and any +options+ you wish to set for the read. Each row of
# file will be passed to the provided +block+ in turn.
#
- # The +options+ parameter can be anything CSV::new() understands.
+ # The +options+ parameter can be anything CSV::new() understands. This method
+ # also understands an additional <tt>:encoding</tt> parameter that you can use
+ # to specify the Encoding of the data in the file to be read. You must provide
+ # this unless your data is in Encoding::default_external(). CSV will use this
+ # to deterime how to parse the data. You may provide a second Encoding to
+ # have the data transcoded as it is read. For example,
+ # <tt>:encoding => "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the
+ # file but transcode it to UTF-8 before CSV parses it.
#
def self.foreach(path, options = Hash.new, &block)
- open(path, options) do |csv|
+ encoding = options.delete(:encoding)
+ mode = "rb"
+ mode << ":#{encoding}" if encoding
+ open(path, mode, options) do |csv|
csv.each(&block)
end
end
@@ -1035,7 +1204,10 @@ class CSV
# Note that a passed String *is* modfied by this method. Call dup() before
# passing if you need a new String.
#
- # The +options+ parameter can be anthing CSV::new() understands.
+ # The +options+ parameter can be anthing CSV::new() understands. This method
+ # understands an additional <tt>:encoding</tt> parameter when not passed a
+ # String to set the base Encoding for the output. CSV needs this hint if you
+ # plan to output non-ASCII compatible data.
#
def self.generate(*args)
# add a default empty String, if none was given
@@ -1044,7 +1216,10 @@ class CSV
io.seek(0, IO::SEEK_END)
args.unshift(io)
else
- args.unshift("")
+ encoding = args.last.is_a?(Hash) ? args.last.delete(:encoding) : nil
+ str = ""
+ str.encode!(encoding) if encoding
+ args.unshift(str)
end
csv = new(*args) # wrap
yield csv # yield for appending
@@ -1055,97 +1230,40 @@ class CSV
# This method is a shortcut for converting a single row (Array) into a CSV
# String.
#
- # The +options+ parameter can be anthing CSV::new() understands.
+ # The +options+ parameter can be anthing CSV::new() understands. This method
+ # understands an additional <tt>:encoding</tt> parameter to set the base
+ # Encoding for the output. This method will try to guess your Encoding from
+ # the first non-+nil+ field in +row+, if possible, but you may need to use
+ # this parameter as a backup plan.
#
# The <tt>:row_sep</tt> +option+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
# (<tt>$/</tt>) when calling this method.
#
def self.generate_line(row, options = Hash.new)
- options = {:row_sep => $INPUT_RECORD_SEPARATOR}.merge(options)
- (new("", options) << row).string
- end
-
- #
- # This method will return a CSV instance, just like CSV::new(), but the
- # instance will be cached and returned for all future calls to this method for
- # the same +data+ object (tested by Object#object_id()) with the same
- # +options+.
- #
- # If a block is given, the instance is passed to the block and the return
- # value becomes the return value of the block.
- #
- def self.instance(data = $stdout, options = Hash.new)
- # create a _signature_ for this method call, data object and options
- sig = [data.object_id] +
- options.values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s })
-
- # fetch or create the instance for this signature
- @@instances ||= Hash.new
- instance = (@@instances[sig] ||= new(data, options))
-
- if block_given?
- yield instance # run block, if given, returning result
- else
- instance # or return the instance
- end
- end
-
- #
- # This method is the reading counterpart to CSV::dump(). See that method for
- # a detailed description of the process.
- #
- # You can customize loading by adding a class method called csv_load() which
- # will be passed a Hash of meta information, an Array of headers, and an Array
- # of fields for the object the method is expected to return.
- #
- # Remember that all fields will be Strings after this load. If you need
- # something else, use +options+ to setup converters or provide a custom
- # csv_load() implementation.
- #
- def self.load(io_or_str, options = Hash.new)
- csv = new(io_or_str, options)
-
- # load meta information
- meta = Hash[*csv.shift]
- cls = meta["class"].split("::").inject(Object) do |c, const|
- c.const_get(const)
- end
-
- # load headers
- headers = csv.shift
-
- # unserialize each object stored in the file
- results = csv.inject(Array.new) do |all, row|
- begin
- obj = cls.csv_load(meta, headers, row)
- rescue NoMethodError
- obj = cls.allocate
- headers.zip(row) do |name, value|
- if name[0] == ?@
- obj.instance_variable_set(name, value)
- else
- obj.send(name, value)
- end
- end
- end
- all << obj
- end
-
- csv.close unless io_or_str.is_a? String
-
- results
+ options = {:row_sep => $INPUT_RECORD_SEPARATOR}.merge(options)
+ encoding = options.delete(:encoding)
+ str = ""
+ if encoding
+ str.encode!(encoding)
+ elsif field = row.find { |f| not f.nil? }
+ str.encode!(String(field).encoding)
+ end
+ (new(str, options) << row).string
end
#
# :call-seq:
- # open( filename, mode="r", options = Hash.new ) { |csv| ... }
- # open( filename, mode="r", options = Hash.new )
+ # open( filename, mode = "rb", options = Hash.new ) { |faster_csv| ... }
+ # open( filename, options = Hash.new ) { |faster_csv| ... }
+ # open( filename, mode = "rb", options = Hash.new )
+ # open( filename, options = Hash.new )
#
# This method opens an IO object, and wraps that with CSV. This is intended
# as the primary interface for writing a CSV file.
#
- # You may pass any +args+ Ruby's open() understands followed by an optional
- # Hash containing any +options+ CSV::new() understands.
+ # You must pass a +filename+ and may optionally add a +mode+ for Ruby's
+ # open(). You may also pass an optional Hash containing any +options+
+ # CSV::new() understands as the final argument.
#
# This method works like Ruby's open() call, in that it will pass a CSV object
# to a provided block and close it when the block terminates, or it will
@@ -1153,24 +1271,38 @@ class CSV
# from the Ruby 1.8 CSV library which passed rows to the block. Use
# CSV::foreach() for that behavior.)
#
- # An opened CSV object will delegate to many IO methods, for convenience. You
+ # You must provide a +mode+ with an embedded Encoding designator unless your
+ # data is in Encoding::default_external(). CSV will check the Encoding of the
+ # underlying IO object (set by the +mode+ you pass) to deterime how to parse
+ # the data. You may provide a second Encoding to have the data transcoded as
+ # it is read just as you can with a normal call to IO::open(). For example,
+ # <tt>"rb:UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file but
+ # transcode it to UTF-8 before CSV parses it.
+ #
+ # An opened CSV object will delegate to many IO methods for convenience. You
# may call:
#
# * binmode()
+ # * binmode?()
# * close()
# * close_read()
# * close_write()
# * closed?()
# * eof()
# * eof?()
+ # * external_encoding()
# * fcntl()
# * fileno()
+ # * flock()
# * flush()
# * fsync()
+ # * internal_encoding()
# * ioctl()
# * isatty()
+ # * path()
# * pid()
# * pos()
+ # * pos=()
# * reopen()
# * seek()
# * stat()
@@ -1179,11 +1311,14 @@ class CSV
# * tell()
# * to_i()
# * to_io()
+ # * truncate()
# * tty?()
#
def self.open(*args)
# find the +options+ Hash
options = if args.last.is_a? Hash then args.pop else Hash.new end
+ # default to a binary open mode
+ args << "rb" if args.size == 1
# wrap a File opened with the remaining +args+
csv = new(File.open(*args), options)
@@ -1237,10 +1372,20 @@ class CSV
#
# Use to slurp a CSV file into an Array of Arrays. Pass the +path+ to the
- # file and any +options+ CSV::new() understands.
+ # file and any +options+ CSV::new() understands. This method also understands
+ # an additional <tt>:encoding</tt> parameter that you can use to specify the
+ # Encoding of the data in the file to be read. You must provide this unless
+ # your data is in Encoding::default_external(). CSV will use this to deterime
+ # how to parse the data. You may provide a second Encoding to have the data
+ # transcoded as it is read. For example,
+ # <tt>:encoding => "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the
+ # file but transcode it to UTF-8 before CSV parses it.
#
def self.read(path, options = Hash.new)
- open(path, options) { |csv| csv.read }
+ encoding = options.delete(:encoding)
+ mode = "rb"
+ mode << ":#{encoding}" if encoding
+ open(path, mode, options) { |csv| csv.read }
end
# Alias for CSV::read().
@@ -1276,6 +1421,8 @@ class CSV
# Available options are:
#
# <b><tt>:col_sep</tt></b>:: The String placed between each field.
+ # This String will be transcoded into
+ # the data's Encoding before parsing.
# <b><tt>:row_sep</tt></b>:: The String appended to the end of each
# row. This can be set to the special
# <tt>:auto</tt> setting, which requests
@@ -1295,7 +1442,16 @@ class CSV
# <tt>$INPUT_RECORD_SEPARATOR</tt>
# (<tt>$/</tt>) is used. Obviously,
# discovery takes a little time. Set
- # manually if speed is important.
+ # manually if speed is important. Also
+ # note that IO objects should be opened
+ # in binary mode on Windows if this
+ # feature will be used as the
+ # line-ending translation can cause
+ # problems with resetting the document
+ # position to where it was before the
+ # read ahead. This String will be
+ # transcoded into the data's Encoding
+ # before parsing.
# <b><tt>:quote_char</tt></b>:: The character used to quote fields.
# This has to be a single character
# String. This is useful for
@@ -1304,11 +1460,31 @@ class CSV
# instead of the correct <tt>"</tt>.
# CSV will always consider a double
# sequence this character to be an
- # escaped quote.
+ # escaped quote. This String will be
+ # transcoded into the data's Encoding
+ # before parsing.
+ # <b><tt>:field_size_limit</tt></b>:: This is a maximum size CSV will read
+ # ahead looking for the closing quote
+ # for a field. (In truth, it reads to
+ # the first line ending beyond this
+ # size.) If a quote cannot be found
+ # within the limit CSV will raise a
+ # MalformedCSVError, assuming the data
+ # is faulty. You can use this limit to
+ # prevent what are effectively DoS
+ # attacks on the parser. However, this
+ # limit can cause a legitimate parse to
+ # fail and thus is set to +nil+, or off,
+ # by default.
# <b><tt>:converters</tt></b>:: An Array of names from the Converters
# Hash and/or lambdas that handle custom
# conversion. A single converter
- # doesn't have to be in an Array.
+ # doesn't have to be in an Array. All
+ # built-in converters try to transcode
+ # fields to UTF-8 before converting.
+ # The conversion will fail if the data
+ # cannot be transcoded, leaving the
+ # field unchanged.
# <b><tt>:unconverted_fields</tt></b>:: If set to +true+, an
# unconverted_fields() method will be
# added to all returned rows (Array or
@@ -1324,11 +1500,14 @@ class CSV
# headers. If set to an Array, the
# contents will be used as the headers.
# If set to a String, the String is run
- # through a call of CSV::parse_line() to
- # produce an Array of headers. This
- # setting causes CSV.shift() to return
+ # through a call of CSV::parse_line()
+ # with the same <tt>:col_sep</tt>,
+ # <tt>:row_sep</tt>, and
+ # <tt>:quote_char</tt> as this instance
+ # to produce an Array of headers. This
+ # setting causes CSV#shift() to return
# rows as CSV::Row objects instead of
- # Arrays and CSV.read() to return
+ # Arrays and CSV#read() to return
# CSV::Table objects instead of an Array
# of Arrays.
# <b><tt>:return_headers</tt></b>:: When +false+, header rows are silently
@@ -1337,10 +1516,17 @@ class CSV
# with identical headers and
# fields (save that the fields do not go
# through the converters).
+ # <b><tt>:write_headers</tt></b>:: When +true+ and <tt>:headers</tt> is
+ # set, a header row will be added to the
+ # output.
# <b><tt>:header_converters</tt></b>:: Identical in functionality to
# <tt>:converters</tt> save that the
# conversions are only made to header
- # rows.
+ # rows. All built-in converters try to
+ # transcode headers to UTF-8 before
+ # converting. The conversion will fail
+ # if the data cannot be transcoded,
+ # leaving the header unchanged.
# <b><tt>:skip_blanks</tt></b>:: When set to a +true+ value, CSV will
# skip over any rows with no content.
# <b><tt>:force_quotes</tt></b>:: When set to a +true+ value, CSV will
@@ -1356,8 +1542,24 @@ class CSV
options = DEFAULT_OPTIONS.merge(options)
# create the IO object we will read from
- @io = if data.is_a? String then StringIO.new(data) else data end
-
+ @io = if data.is_a? String then StringIO.new(data) else data end
+ # honor the IO encoding if we can, otherwise default to ASCII-8BIT
+ @encoding = if @io.respond_to? :internal_encoding
+ @io.internal_encoding || @io.external_encoding
+ elsif @io.is_a? StringIO
+ @io.string.encoding
+ end
+ @encoding ||= Encoding.default_external
+ #
+ # prepare for build safe regular expressions in the target encoding,
+ # if we can transcode the needed characters
+ #
+ @re_esc = "\\".encode(@encoding) rescue ""
+ @re_chars = %w[ \\ . [ ] - ^ $ ?
+ * + { } ( ) | #
+ \ \r \n \t \f \v ].
+ map { |s| s.encode(@encoding) rescue nil }.compact
+
init_separators(options)
init_parsers(options)
init_converters(options)
@@ -1372,6 +1574,79 @@ class CSV
end
#
+ # The encoded <tt>:col_sep</tt> used in parsing and writing. See CSV::new
+ # for details.
+ #
+ attr_reader :col_sep
+ #
+ # The encoded <tt>:row_sep</tt> used in parsing and writing. See CSV::new
+ # for details.
+ #
+ attr_reader :row_sep
+ #
+ # The encoded <tt>:quote_char</tt> used in parsing and writing. See CSV::new
+ # for details.
+ #
+ attr_reader :quote_char
+ # The limit for field size, if any. See CSV::new for details.
+ attr_reader :field_size_limit
+ #
+ # Returns the current list of converters in effect. See CSV::new for details.
+ # Built-in converters will be returned by name, while others will be returned
+ # as is.
+ #
+ def converters
+ @converters.map do |converter|
+ name = Converters.rassoc(converter)
+ name ? name.first : converter
+ end
+ end
+ #
+ # Returns +true+ if unconverted_fields() to parsed results. See CSV::new
+ # for details.
+ #
+ def unconverted_fields?() @unconverted_fields end
+ #
+ # Returns +nil+ if headers will not be used, +true+ if they will but have not
+ # yet been read, or the actual headers after they have been read. See
+ # CSV::new for details.
+ #
+ def headers
+ @headers || true if @use_headers
+ end
+ #
+ # Returns +true+ if headers will be returned as a row of results.
+ # See CSV::new for details.
+ #
+ def return_headers?() @return_headers end
+ # Returns +true+ if headers are written in output. See CSV::new for details.
+ def write_headers?() @write_headers end
+ #
+ # Returns the current list of converters in effect for headers. See CSV::new
+ # for details. Built-in converters will be returned by name, while others
+ # will be returned as is.
+ #
+ def header_converters
+ @header_converters.map do |converter|
+ name = HeaderConverters.rassoc(converter)
+ name ? name.first : converter
+ end
+ end
+ #
+ # Returns +true+ blank lines are skipped by the parser. See CSV::new
+ # for details.
+ #
+ def skip_blanks?() @skip_blanks end
+ # Returns +true+ if all output fields are quoted. See CSV::new for details.
+ def force_quotes?() @force_quotes end
+
+ #
+ # The Encoding CSV is parsing or writing in. This will be the Encoding you
+ # receive parsed data in and/or the Encoding data will be written in.
+ #
+ attr_reader :encoding
+
+ #
# The line number of the last row read from this file. Fields with nested
# line-end characters will not affect this count.
#
@@ -1380,10 +1655,12 @@ class CSV
### IO and StringIO Delegation ###
extend Forwardable
- def_delegators :@io, :binmode, :close, :close_read, :close_write, :closed?,
- :eof, :eof?, :fcntl, :fileno, :flush, :fsync, :ioctl,
- :isatty, :pid, :pos, :reopen, :seek, :stat, :string,
- :sync, :sync=, :tell, :to_i, :to_io, :tty?
+ def_delegators :@io, :binmode, :binmode?, :close, :close_read, :close_write,
+ :closed?, :eof, :eof?, :external_encoding, :fcntl,
+ :fileno, :flock, :flush, :fsync, :internal_encoding,
+ :ioctl, :isatty, :path, :pid, :pos, :pos=, :reopen,
+ :seek, :stat, :string, :sync, :sync=, :tell, :to_i,
+ :to_io, :truncate, :tty?
# Rewinds the underlying IO object and resets CSV's lineno() counter.
def rewind
@@ -1403,12 +1680,18 @@ class CSV
# The data source must be open for writing.
#
def <<(row)
+ # make sure headers have been assigned
+ if header_row? and [Array, String].include? @use_headers.class
+ parse_headers # won't read data for Array or String
+ self << @headers if @write_headers
+ end
+
# handle CSV::Row objects and Hashes
row = case row
- when self.class::Row then row.fields
- when Hash then @headers.map { |header| row[header] }
- else row
- end
+ when self.class::Row then row.fields
+ when Hash then @headers.map { |header| row[header] }
+ else row
+ end
@headers = row if header_row?
@lineno += 1
@@ -1431,7 +1714,7 @@ class CSV
#
# If you provide a block that takes one argument, it will be passed the field
# and is expected to return the converted value or the field itself. If your
- # block takes two arguments, it will also be passed a FieldInfo Struct,
+ # block takes two arguments, it will also be passed a CSV::FieldInfo Struct,
# containing details about the field. Again, the block should return a
# converted field or the field itself.
#
@@ -1445,7 +1728,7 @@ class CSV
# header_convert { |field| ... }
# header_convert { |field, field_info| ... }
#
- # Identical to CSV.convert(), but for header rows.
+ # Identical to CSV#convert(), but for header rows.
#
# Note that this method must be called before header rows are read to have any
# effect.
@@ -1526,7 +1809,7 @@ class CSV
# add another read to the line
(line += @io.gets(@row_sep)) rescue return nil
# copy the line so we can chop it up in parsing
- parse = line.dup
+ parse = line.dup
parse.sub!(@parsers[:line_end], "")
#
@@ -1566,7 +1849,7 @@ class CSV
nil # for Ruby 1.8 CSV compatibility
else
# I decided to take a strict approach to CSV parsing...
- if $2.count("\r\n").zero? # verify correctness of field...
+ if $2.count(@parsers[:return_newline]).zero? # verify correctness
$2
else
# or throw an Exception
@@ -1603,6 +1886,10 @@ class CSV
# if we're not empty?() but at eof?(), a quoted field wasn't closed...
if @io.eof?
raise MalformedCSVError, "Unclosed quoted field on line #{lineno + 1}."
+ elsif parse =~ @parsers[:bad_field]
+ raise MalformedCSVError, "Illegal quoting on line #{lineno + 1}."
+ elsif @field_size_limit and parse.length >= @field_size_limit
+ raise MalformedCSVError, "Field size exceeded on line #{lineno + 1}."
end
# otherwise, we need to loop and pull some more data to complete the row
end
@@ -1610,6 +1897,38 @@ class CSV
alias_method :gets, :shift
alias_method :readline, :shift
+ #
+ # Returns a simplified description of the key FasterCSV attributes in an
+ # ASCII-8BIT String.
+ #
+ def inspect
+ str = ["<#", self.class.to_s, " io_type:"]
+ # show type of wrapped IO
+ if @io == $stdout then str << "$stdout"
+ elsif @io == $stdin then str << "$stdin"
+ elsif @io == $stderr then str << "$stderr"
+ else str << @io.class.to_s
+ end
+ # show IO.path(), if available
+ if @io.respond_to?(:path) and (p = @io.path)
+ str << " io_path:" << p.inspect
+ end
+ # show encoding
+ str << " encoding:" << @encoding.name
+ # show other attributes
+ %w[ lineno col_sep row_sep
+ quote_char skip_blanks ].each do |attr_name|
+ if a = instance_variable_get("@#{attr_name}")
+ str << " " << attr_name << ":" << a.inspect
+ end
+ end
+ if @use_headers
+ str << " headers:" << headers.inspect
+ end
+ str << ">"
+ str.map { |s| s.encode("ASCII-8BIT") }.join
+ end
+
private
#
@@ -1624,15 +1943,18 @@ class CSV
#
def init_separators(options)
# store the selected separators
- @col_sep = options.delete(:col_sep)
- @row_sep = options.delete(:row_sep)
- @quote_char = options.delete(:quote_char)
+ @col_sep = options.delete(:col_sep).to_s.encode(@encoding)
+ @row_sep = options.delete(:row_sep) # encode after resolving :auto
+ @quote_char = options.delete(:quote_char).to_s.encode(@encoding)
if @quote_char.length != 1
raise ArgumentError, ":quote_char has to be a single character String"
end
+ #
# automatically discover row separator when requested
+ # (not fully encoding safe)
+ #
if @row_sep == :auto
if [ARGF, STDIN, STDOUT, STDERR].include?(@io) or
(defined?(Zlib) and @io.class == Zlib::GzipWriter)
@@ -1651,11 +1973,12 @@ class CSV
end
# read ahead a bit
- sample = @io.read(1024)
- sample += @io.read(1) if sample[-1..-1] == "\r" and not @io.eof?
+ sample = read_to_char(1024)
+ sample += read_to_char(1) if sample[-1..-1] == encode_str("\r") and
+ not @io.eof?
# try to find a standard separator
- if sample =~ /\r\n?|\n/
+ if sample =~ encode_re("\r\n?|\n")
@row_sep = $&
break
end
@@ -1673,14 +1996,17 @@ class CSV
end
end
end
+ @row_sep = @row_sep.to_s.encode(@encoding)
# establish quoting rules
- do_quote = lambda do |field|
+ @force_quotes = options.delete(:force_quotes)
+ do_quote = lambda do |field|
@quote_char +
String(field).gsub(@quote_char, @quote_char * 2) +
@quote_char
end
- @quote = if options.delete(:force_quotes)
+ quotable_chars = encode_str("\r\n", @col_sep, @quote_char)
+ @quote = if @force_quotes
do_quote
else
lambda do |field|
@@ -1690,7 +2016,7 @@ class CSV
field = String(field) # Stringify fields
# represent empty fields as empty quoted fields
if field.empty? or
- field.count("\r\n#{@col_sep}#{@quote_char}").nonzero?
+ field.count(quotable_chars).nonzero?
do_quote.call(field)
else
field # unquoted field
@@ -1703,27 +2029,45 @@ class CSV
# Pre-compiles parsers and stores them by name for access during reads.
def init_parsers(options)
# store the parser behaviors
- @skip_blanks = options.delete(:skip_blanks)
+ @skip_blanks = options.delete(:skip_blanks)
+ @field_size_limit = options.delete(:field_size_limit)
# prebuild Regexps for faster parsing
- esc_col_sep = Regexp.escape(@col_sep)
- esc_row_sep = Regexp.escape(@row_sep)
- esc_quote = Regexp.escape(@quote_char)
+ esc_col_sep = escape_re(@col_sep)
+ esc_row_sep = escape_re(@row_sep)
+ esc_quote = escape_re(@quote_char)
@parsers = {
- :leading_fields =>
- /\A(?:#{esc_col_sep})+/, # for empty leading fields
- :csv_row =>
- ### The Primary Parser ###
- / \G(?:^|#{esc_col_sep}) # anchor the match
- (?: #{esc_quote}( (?>[^#{esc_quote}]*) # find quoted fields
- (?> #{esc_quote*2}
- [^#{esc_quote}]* )* )#{esc_quote}
- | # ... or ...
- ([^#{esc_quote}#{esc_col_sep}]*) # unquoted fields
- )/x,
- ### End Primary Parser ###
- :line_end =>
- /#{esc_row_sep}\z/ # safer than chomp!()
+ # for empty leading fields
+ :leading_fields => encode_re("\\A(?:", esc_col_sep, ")+"),
+ # The Primary Parser
+ :csv_row => encode_re(
+ "\\G(?:\\A|", esc_col_sep, ")", # anchor the match
+ "(?:", esc_quote, # find quoted fields
+ "((?>[^", esc_quote, "]*)", # "unrolling the loop"
+ "(?>", esc_quote * 2, # double for escaping
+ "[^", esc_quote, "]*)*)",
+ esc_quote,
+ "|", # ... or ...
+ "([^", esc_quote, esc_col_sep, "]*))", # unquoted fields
+ "(?=", esc_col_sep, "|\\z)" # ensure field is ended
+ ),
+ # a test for unescaped quotes
+ :bad_field => encode_re(
+ "\\A", esc_col_sep, "?", # an optional comma
+ "(?:", esc_quote, # a quoted field
+ "(?>[^", esc_quote, "]*)", # "unrolling the loop"
+ "(?>", esc_quote * 2, # double for escaping
+ "[^", esc_quote, "]*)*",
+ esc_quote, # the closing quote
+ "[^", esc_quote, "]", # an extra character
+ "|", # ... or ...
+ "[^", esc_quote, esc_col_sep, "]+", # an unquoted field
+ esc_quote, ")" # an extra quote
+ ),
+ # safer than chomp!()
+ :line_end => encode_re(esc_row_sep, "\\z"),
+ # illegal unquoted characters
+ :return_newline => encode_str("\r\n")
}
end
@@ -1770,6 +2114,7 @@ class CSV
def init_headers(options)
@use_headers = options.delete(:headers)
@return_headers = options.delete(:return_headers)
+ @write_headers = options.delete(:write_headers)
# headers must be delayed until shift(), in case they need a row of content
@headers = nil
@@ -1812,7 +2157,7 @@ class CSV
# see if we are converting headers or fields
converters = headers ? @header_converters : @converters
- fields.each_with_index.map do |field, index| # map_with_index
+ fields.map.with_index do |field, index|
converters.each do |converter|
field = if converter.arity == 1 # straight field converter
converter[field]
@@ -1839,10 +2184,17 @@ class CSV
def parse_headers(row = nil)
if @headers.nil? # header row
@headers = case @use_headers # save headers
- when Array then @use_headers # Array of headers
- when String then self.class.parse_line(@use_headers) # CSV header String
- else row # first row headers
- end
+ # Array of headers
+ when Array then @use_headers
+ # CSV header String
+ when String
+ self.class.parse_line( @use_headers,
+ :col_sep => @col_sep,
+ :row_sep => @row_sep,
+ :quote_char => @quote_char )
+ # first row is headers
+ else row
+ end
# prepare converted and unconverted copies
row = @headers if row.nil?
@@ -1870,6 +2222,56 @@ class CSV
row.instance_eval { @unconverted_fields = fields }
row
end
+
+ #
+ # This method is an encoding safe version of Regexp::escape(). I will escape
+ # any characters that would change the meaning of a regular expression in the
+ # encoding of +str+. Regular expression characters that cannot be transcoded
+ # to the target encodign will be skipped and no escaping will be performed if
+ # a backslash cannot be transcoded.
+ #
+ def escape_re(str)
+ str.chars.map { |c| @re_chars.include?(c) ? @re_esc + c : c }.join
+ end
+
+ #
+ # Builds a regular expression in <tt>@encoding</tt>. All +chunks+ will be
+ # transcoded to that encoding.
+ #
+ def encode_re(*chunks)
+ Regexp.new(encode_str(*chunks))
+ end
+
+ #
+ # Builds a String in <tt>@encoding</tt>. All +chunks+ will be transcoded to
+ # that encoding.
+ #
+ def encode_str(*chunks)
+ chunks.map { |chunk| chunk.encode(@encoding.name) }.join
+ end
+
+ #
+ # Reads at least +bytes+ from <tt>@io</tt>, but will read on until the data
+ # read is valid in the ecoding of that data. This should ensure that it is
+ # safe to use regular expressions on the read data. The read data will be
+ # returned in <tt>@encoding</tt>.
+ #
+ def read_to_char(bytes)
+ return "" if @io.eof?
+ data = @io.read(bytes)
+ begin
+ encoded = encode_str(data)
+ raise unless encoded.valid_encoding?
+ return encoded
+ rescue # encoding error or my invalid data raise
+ if @io.eof?
+ return data
+ else
+ data += @io.read(1) until data.valid_encoding? or @io.eof?
+ retry
+ end
+ end
+ end
end
# Another name for CSV::instance().
diff --git a/lib/mathn.rb b/lib/mathn.rb
index 2af2b83da3..e918608b0d 100644
--- a/lib/mathn.rb
+++ b/lib/mathn.rb
@@ -9,11 +9,15 @@
#
#
-require "complex.rb"
-require "rational.rb"
+require "cmath.rb"
require "matrix.rb"
require "prime.rb"
+unless defined?(Math.exp!)
+ Object.instance_eval{remove_const :Math}
+ Math = CMath
+end
+
class Fixnum
remove_method :/
alias / quo
@@ -33,7 +37,7 @@ class Rational
if other.kind_of?(Rational)
other2 = other
if self < 0
- return Complex.__send__(:new!, self, 0) ** other
+ return Complex(self, 0.0) ** other
elsif other == 0
return Rational(1,1)
elsif self == 0
@@ -95,7 +99,7 @@ module Math
remove_method(:sqrt)
def sqrt(a)
if a.kind_of?(Complex)
- abs = sqrt(a.real*a.real + a.image*a.image)
+ abs = sqrt(a.real*a.real + a.imag*a.imag)
# if not abs.kind_of?(Rational)
# return a**Rational(1,2)
# end
@@ -104,7 +108,7 @@ module Math
# if !(x.kind_of?(Rational) and y.kind_of?(Rational))
# return a**Rational(1,2)
# end
- if a.image >= 0
+ if a.imag >= 0
Complex(x, y)
else
Complex(x, -y)
diff --git a/lib/matrix.rb b/lib/matrix.rb
index d31fcc5464..c672ee5198 100644
--- a/lib/matrix.rb
+++ b/lib/matrix.rb
@@ -410,17 +410,21 @@ class Matrix
other.compare_by_row_vectors(@rows)
end
- alias eql? ==
+ def eql?(other)
+ return false unless Matrix === other
+
+ other.compare_by_row_vectors(@rows, :eql?)
+ end
#
# Not really intended for general consumption.
#
- def compare_by_row_vectors(rows)
+ def compare_by_row_vectors(rows, comparison = :==)
return false unless @rows.size == rows.size
0.upto(@rows.size - 1) do
|i|
- return false unless @rows[i] == rows[i]
+ return false unless @rows[i].send(comparison, rows[i])
end
true
end
@@ -1200,13 +1204,17 @@ class Vector
other.compare_by(@elements)
end
- alias eqn? ==
+ def eql?(other)
+ return false unless Vector === other
+
+ other.compare_by(@elements, :eql?)
+ end
#
# For internal use.
#
- def compare_by(elements)
- @elements == elements
+ def compare_by(elements, comparison = :==)
+ @elements.send(comparison, elements)
end
#
diff --git a/lib/open-uri.rb b/lib/open-uri.rb
index 238d759d5f..c68aee6e97 100644
--- a/lib/open-uri.rb
+++ b/lib/open-uri.rb
@@ -542,7 +542,7 @@ module OpenURI
# :proxy => true
# :proxy => false
# :proxy => nil
- #
+ #
# If :proxy option is specified, the value should be String, URI,
# boolean or nil.
# When String or URI is given, it is treated as proxy URI.
@@ -556,7 +556,7 @@ module OpenURI
# Synopsis:
# :proxy_http_basic_authentication => ["http://proxy.foo.com:8000/", "proxy-user", "proxy-password"]
# :proxy_http_basic_authentication => [URI.parse("http://proxy.foo.com:8000/"), "proxy-user", "proxy-password"]
- #
+ #
# If :proxy option is specified, the value should be an Array with 3 elements.
# It should contain a proxy URI, a proxy user name and a proxy password.
# The proxy URI should be a String, an URI or nil.
@@ -564,7 +564,7 @@ module OpenURI
#
# If nil is given for the proxy URI, this option is just ignored.
#
- # If :proxy and :proxy_http_basic_authentication is specified,
+ # If :proxy and :proxy_http_basic_authentication is specified,
# ArgumentError is raised.
#
# [:http_basic_authentication]
@@ -579,14 +579,14 @@ module OpenURI
# [:content_length_proc]
# Synopsis:
# :content_length_proc => lambda {|content_length| ... }
- #
+ #
# If :content_length_proc option is specified, the option value procedure
# is called before actual transfer is started.
# It takes one argument which is expected content length in bytes.
- #
+ #
# If two or more transfer is done by HTTP redirection, the procedure
# is called only one for a last transfer.
- #
+ #
# When expected content length is unknown, the procedure is called with
# nil.
# It is happen when HTTP response has no Content-Length header.
diff --git a/lib/optparse.rb b/lib/optparse.rb
index 86681235a0..f457b072a9 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -632,7 +632,7 @@ class OptionParser
list.each do |opt|
if opt.respond_to?(:summarize) # perhaps OptionParser::Switch
opt.summarize(*args, &block)
- elsif !opt
+ elsif !opt or opt.empty?
yield("")
elsif opt.respond_to?(:each_line)
opt.each_line(&block)
@@ -1605,6 +1605,13 @@ class OptionParser
argv
end
+ def set_backtrace(array)
+ unless $DEBUG
+ array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~))
+ end
+ super(array)
+ end
+
def set_option(opt, eq)
if eq
@args[0] = opt
diff --git a/lib/pathname.rb b/lib/pathname.rb
index 7bee22b58f..45974545a6 100644
--- a/lib/pathname.rb
+++ b/lib/pathname.rb
@@ -43,7 +43,7 @@
# base = p.basename # Pathname:ruby
# dir, base = p.split # [Pathname:/usr/bin, Pathname:ruby]
# data = p.read
-# p.open { |f| _ }
+# p.open { |f| _ }
# p.each_line { |line| _ }
#
# === Example 2: Using standard Ruby
@@ -55,7 +55,7 @@
# base = File.basename(p) # "ruby"
# dir, base = File.split(p) # ["/usr/bin", "ruby"]
# data = File.read(p)
-# File.open(p) { |f| _ }
+# File.open(p) { |f| _ }
# File.foreach(p) { |line| _ }
#
# === Example 3: Special features
@@ -71,7 +71,7 @@
# p5.cleanpath # Pathname:articles
# p5.realpath # Pathname:/home/gavin/articles
# p5.children # [Pathname:/home/gavin/articles/linux, ...]
-#
+#
# == Breakdown of functionality
#
# === Core methods
@@ -452,7 +452,7 @@ class Pathname
# Returns a real (absolute) pathname of +self+ in the actual filesystem.
# The real pathname doesn't contain symlinks or useless dots.
#
- # No arguments should be given; the old behaviour is *obsoleted*.
+ # No arguments should be given; the old behaviour is *obsoleted*.
#
def realpath
path = @path
@@ -587,7 +587,7 @@ class Pathname
# p2 = p1 + "bin/ruby" # Pathname:/usr/bin/ruby
# p3 = p1 + "/etc/passwd" # Pathname:/etc/passwd
#
- # This method doesn't access the file system; it is pure string manipulation.
+ # This method doesn't access the file system; it is pure string manipulation.
#
def +(other)
other = Pathname.new(other) unless Pathname === other
diff --git a/lib/pp.rb b/lib/pp.rb
index ec896b3ce5..41f51b0046 100644
--- a/lib/pp.rb
+++ b/lib/pp.rb
@@ -1,10 +1,10 @@
# == Pretty-printer for Ruby objects.
-#
+#
# = Which seems better?
-#
+#
# non-pretty-printed output by #p is:
# #<PP:0x81fedf0 @genspace=#<Proc:0x81feda0>, @group_queue=#<PrettyPrint::GroupQueue:0x81fed3c @queue=[[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], []]>, @buffer=[], @newline="\n", @group_stack=[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], @buffer_width=0, @indent=0, @maxwidth=79, @output_width=2, @output=#<IO:0x8114ee4>>
-#
+#
# pretty-printed output by #pp is:
# #<PP:0x81fedf0
# @buffer=[],
@@ -22,17 +22,17 @@
# @newline="\n",
# @output=#<IO:0x8114ee4>,
# @output_width=2>
-#
+#
# I like the latter. If you do too, this library is for you.
-#
+#
# = Usage
-#
+#
# pp(obj)
#
# output +obj+ to +$>+ in pretty printed format.
-#
+#
# It returns +nil+.
-#
+#
# = Output Customization
# To define your customized pretty printing function for your classes,
# redefine a method #pretty_print(+pp+) in the class.
@@ -67,10 +67,10 @@ end
class PP < PrettyPrint
# Outputs +obj+ to +out+ in pretty printed format of
# +width+ columns in width.
- #
+ #
# If +out+ is omitted, +$>+ is assumed.
# If +width+ is omitted, 79 is assumed.
- #
+ #
# PP.pp returns +out+.
def PP.pp(obj, out=$>, width=79)
q = PP.new(out, width)
@@ -82,7 +82,7 @@ class PP < PrettyPrint
# Outputs +obj+ to +out+ like PP.pp but with no indent and
# newline.
- #
+ #
# PP.singleline_pp returns +out+.
def PP.singleline_pp(obj, out=$>)
q = SingleLine.new(out)
@@ -138,12 +138,12 @@ class PP < PrettyPrint
# Adds +obj+ to the pretty printing buffer
# using Object#pretty_print or Object#pretty_print_cycle.
- #
+ #
# Object#pretty_print_cycle is used when +obj+ is already
# printed, a.k.a the object reference chain has a cycle.
def pp(obj)
id = obj.object_id
-
+
if check_inspect_key(id)
group {obj.pretty_print_cycle self}
return
@@ -158,7 +158,7 @@ class PP < PrettyPrint
end
# A convenience method which is same as follows:
- #
+ #
# group(1, '#<' + obj.class.name, '>') { ... }
def object_group(obj, &block) # :yield:
group(1, '#<' + obj.class.name, '>', &block)
@@ -185,7 +185,7 @@ class PP < PrettyPrint
end
# A convenience method which is same as follows:
- #
+ #
# text ','
# breakable
def comma_breakable
@@ -195,23 +195,23 @@ class PP < PrettyPrint
# Adds a separated list.
# The list is separated by comma with breakable space, by default.
- #
+ #
# #seplist iterates the +list+ using +iter_method+.
# It yields each object to the block given for #seplist.
# The procedure +separator_proc+ is called between each yields.
- #
+ #
# If the iteration is zero times, +separator_proc+ is not called at all.
- #
+ #
# If +separator_proc+ is nil or not given,
# +lambda { comma_breakable }+ is used.
# If +iter_method+ is not given, :each is used.
- #
+ #
# For example, following 3 code fragments has similar effect.
- #
+ #
# q.seplist([1,2,3]) {|v| xxx v }
- #
+ #
# q.seplist([1,2,3], lambda { q.comma_breakable }, :each) {|v| xxx v }
- #
+ #
# xxx 1
# q.comma_breakable
# xxx 2
@@ -275,11 +275,11 @@ class PP < PrettyPrint
# A default pretty printing method for general objects.
# It calls #pretty_print_instance_variables to list instance variables.
- #
+ #
# If +self+ has a customized (redefined) #inspect method,
# the result of self.inspect is used but it obviously has no
# line break hints.
- #
+ #
# This module provides predefined #pretty_print methods for some of
# the most commonly used built-in classes for convenience.
def pretty_print(q)
@@ -302,7 +302,7 @@ class PP < PrettyPrint
end
# Returns a sorted array of instance variable names.
- #
+ #
# This method should return an array of names of instance variables as symbols or strings as:
# +[:@a, :@b]+.
def pretty_print_instance_variables
@@ -311,7 +311,7 @@ class PP < PrettyPrint
# Is #inspect implementation using #pretty_print.
# If you implement #pretty_print, it can be used as follows.
- #
+ #
# alias inspect pretty_print_inspect
#
# However, doing this requires that every class that #inspect is called on
@@ -629,7 +629,7 @@ if __FILE__ == $0
result = PP.pp(a, '')
assert_equal("#{a.inspect}\n", result)
end
-
+
def test_to_s_without_iv
a = Object.new
def a.to_s() "aaa" end
diff --git a/lib/prettyprint.rb b/lib/prettyprint.rb
index 315c422e9e..48f2ebf1e4 100644
--- a/lib/prettyprint.rb
+++ b/lib/prettyprint.rb
@@ -2,7 +2,7 @@
# This class implements a pretty printing algorithm. It finds line breaks and
# nice indentations for grouped structure.
-#
+#
# By default, the class assumes that primitive elements are strings and each
# byte in the strings have single column in width. But it can be used for
# other situations by giving suitable arguments for some methods:
@@ -18,28 +18,28 @@
# == Bugs
# * Box based formatting?
# * Other (better) model/algorithm?
-#
+#
# == References
# Christian Lindig, Strictly Pretty, March 2000,
# http://www.st.cs.uni-sb.de/~lindig/papers/#pretty
-#
+#
# Philip Wadler, A prettier printer, March 1998,
# http://homepages.inf.ed.ac.uk/wadler/topics/language-design.html#prettier
-#
+#
# == Author
# Tanaka Akira <akr@m17n.org>
-#
+#
class PrettyPrint
# This is a convenience method which is same as follows:
- #
+ #
# begin
# q = PrettyPrint.new(output, maxwidth, newline, &genspace)
# ...
# q.flush
# output
# end
- #
+ #
def PrettyPrint.format(output='', maxwidth=79, newline="\n", genspace=lambda {|n| ' ' * n})
q = PrettyPrint.new(output, maxwidth, newline, &genspace)
yield q
diff --git a/lib/rake.rb b/lib/rake.rb
index 0b21eb7350..caafa5caf0 100755
--- a/lib/rake.rb
+++ b/lib/rake.rb
@@ -29,13 +29,13 @@
# as a library via a require statement, but it can be distributed
# independently as an application.
-RAKEVERSION = '0.8.0'
+RAKEVERSION = '0.8.2'
require 'rbconfig'
-require 'getoptlong'
require 'fileutils'
require 'singleton'
-require 'thread'
+require 'monitor'
+require 'optparse'
require 'ostruct'
######################################################################
@@ -239,6 +239,33 @@ end # class String
##############################################################################
module Rake
+ # Errors -----------------------------------------------------------
+
+ # Error indicating an ill-formed task declaration.
+ class TaskArgumentError < ArgumentError
+ end
+
+ # Error indicating a recursion overflow error in task selection.
+ class RuleRecursionOverflowError < StandardError
+ def initialize(*args)
+ super
+ @targets = []
+ end
+
+ def add_target(target)
+ @targets << target
+ end
+
+ def message
+ super + ": [" + @targets.reverse.join(' => ') + "]"
+ end
+ end
+
+ # Error indicating a problem in locating the home directory on a
+ # Win32 system.
+ class Win32HomeError < RuntimeError
+ end
+
# --------------------------------------------------------------------------
# Rake module singleton methods.
#
@@ -266,16 +293,22 @@ module Rake
module Cloneable
# Clone an object by making a new object and setting all the instance
# variables to the same values.
- def clone
+ def dup
sibling = self.class.new
instance_variables.each do |ivar|
value = self.instance_variable_get(ivar)
new_value = value.clone rescue value
sibling.instance_variable_set(ivar, new_value)
end
+ sibling.taint if tainted?
+ sibling
+ end
+
+ def clone
+ sibling = dup
+ sibling.freeze if frozen?
sibling
end
- alias dup clone
end
####################################################################
@@ -286,12 +319,15 @@ module Rake
attr_reader :names
+ # Create a TaskArgument object with a list of named arguments
+ # (given by :names) and a set of associated values (given by
+ # :values). :parent is the parent argument object.
def initialize(names, values, parent=nil)
@names = names
@parent = parent
@hash = {}
names.each_with_index { |name, i|
- @hash[name.to_sym] = values[i]
+ @hash[name.to_sym] = values[i] unless values[i].nil?
}
end
@@ -307,6 +343,13 @@ module Rake
lookup(index.to_sym)
end
+ # Specify a hash of default values for task arguments. Use the
+ # defaults only if there is no specific value for the given
+ # argument.
+ def with_defaults(defaults)
+ @hash = defaults.merge(@hash)
+ end
+
def each(&block)
@hash.each(&block)
end
@@ -342,6 +385,8 @@ module Rake
end
end
+ EMPTY_TASK_ARGS = TaskArguments.new([], [])
+
####################################################################
# InvocationChain tracks the chain of task invocations to detect
# circular dependencies.
@@ -409,6 +454,9 @@ module Rake
# List of prerequisites for a task.
attr_reader :prerequisites
+ # List of actions attached to a task.
+ attr_reader :actions
+
# Application owning this task.
attr_accessor :application
@@ -446,12 +494,12 @@ module Rake
# +enhance+ to add actions and prerequisites.
def initialize(task_name, app)
@name = task_name.to_s
- @prerequisites = FileList[]
+ @prerequisites = []
@actions = []
@already_invoked = false
@full_comment = nil
@comment = nil
- @lock = Mutex.new
+ @lock = Monitor.new
@application = app
@scope = app.current_scope
@arg_names = nil
@@ -488,6 +536,31 @@ module Rake
@arg_names || []
end
+ # Reenable the task, allowing its tasks to be executed if the task
+ # is invoked again.
+ def reenable
+ @already_invoked = false
+ end
+
+ # Clear the existing prerequisites and actions of a rake task.
+ def clear
+ clear_prerequisites
+ clear_actions
+ self
+ end
+
+ # Clear the existing prerequisites of a rake task.
+ def clear_prerequisites
+ prerequisites.clear
+ self
+ end
+
+ # Clear the existing actions on a rake task.
+ def clear_actions
+ actions.clear
+ self
+ end
+
# Invoke the task if it is needed. Prerequites are invoked first.
def invoke(*args)
task_args = TaskArguments.new(arg_names, args)
@@ -496,7 +569,7 @@ module Rake
# Same as invoke, but explicitly pass a call chain to detect
# circular dependencies.
- def invoke_with_call_chain(task_args, invocation_chain)
+ def invoke_with_call_chain(task_args, invocation_chain) # :nodoc:
new_chain = InvocationChain.append(self, invocation_chain)
@lock.synchronize do
if application.options.trace
@@ -511,7 +584,7 @@ module Rake
protected :invoke_with_call_chain
# Invoke all the prerequisites of a task.
- def invoke_prerequisites(task_args, invocation_chain)
+ def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
@prerequisites.each { |n|
prereq = application[n, @scope]
prereq_args = task_args.new_scope(prereq.arg_names)
@@ -529,7 +602,8 @@ module Rake
private :format_trace_flags
# Execute the actions associated with this task.
- def execute(args)
+ def execute(args=nil)
+ args ||= EMPTY_TASK_ARGS
if application.options.dryrun
puts "** Execute (dry run) #{name}"
return
@@ -772,8 +846,8 @@ end
# end
# end
#
-def file(args, &block)
- Rake::FileTask.define_task(args, &block)
+def file(*args, &block)
+ Rake::FileTask.define_task(*args, &block)
end
# Declare a file creation task.
@@ -899,14 +973,38 @@ module FileUtils
ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
}
end
+ if RakeFileUtils.verbose_flag == :default
+ options[:verbose] = false
+ else
+ options[:verbose] ||= RakeFileUtils.verbose_flag
+ end
+ options[:noop] ||= RakeFileUtils.nowrite_flag
rake_check_options options, :noop, :verbose
rake_output_message cmd.join(" ") if options[:verbose]
unless options[:noop]
- res = system(*cmd)
+ res = rake_system(*cmd)
block.call(res, $?)
end
end
+ def rake_system(*cmd)
+ if Rake.application.windows?
+ rake_win32_system(*cmd)
+ else
+ system(*cmd)
+ end
+ end
+ private :rake_system
+
+ def rake_win32_system(*cmd)
+ if cmd.size == 1
+ system("call #{cmd}")
+ else
+ system(*cmd)
+ end
+ end
+ private :rake_win32_system
+
# Run a Ruby interpreter with the given arguments.
#
# Example:
@@ -917,7 +1015,7 @@ module FileUtils
if args.length > 1 then
sh(*([RUBY] + args + [options]), &block)
else
- sh("#{RUBY.sub(/.*\s.*/m, '"\&"')} #{args.first}", options, &block)
+ sh("#{RUBY} #{args.first}", options, &block)
end
end
@@ -961,7 +1059,7 @@ module RakeFileUtils
class << self
attr_accessor :verbose_flag, :nowrite_flag
end
- RakeFileUtils.verbose_flag = true
+ RakeFileUtils.verbose_flag = :default
RakeFileUtils.nowrite_flag = false
$fileutils_verbose = true
@@ -969,10 +1067,10 @@ module RakeFileUtils
FileUtils::OPT_TABLE.each do |name, opts|
default_options = []
- if opts.include?('verbose')
+ if opts.include?(:verbose) || opts.include?("verbose")
default_options << ':verbose => RakeFileUtils.verbose_flag'
end
- if opts.include?('noop')
+ if opts.include?(:noop) || opts.include?("noop")
default_options << ':noop => RakeFileUtils.nowrite_flag'
end
@@ -1029,7 +1127,7 @@ module RakeFileUtils
oldvalue
end
- # Use this function to prevent potentially destructive ruby code from
+ # Use this function to prevent protentially destructive ruby code from
# running when the :nowrite flag is set.
#
# Example:
@@ -1094,21 +1192,6 @@ private(*RakeFileUtils.instance_methods(false))
######################################################################
module Rake
- class RuleRecursionOverflowError < StandardError
- def initialize(*args)
- super
- @targets = []
- end
-
- def add_target(target)
- @targets << target
- end
-
- def message
- super + ": [" + @targets.reverse.join(' => ') + "]"
- end
- end
-
# #########################################################################
# A FileList is essentially an array with a few helper methods defined to
# make file manipulation a bit easier.
@@ -1352,7 +1435,7 @@ module Rake
private :resolve_exclude
# Return a new FileList with the results of running +sub+ against each
- # element of the original list.
+ # element of the oringal list.
#
# Example:
# FileList['a.c', 'b.c'].sub(/\.c$/, '.o') => ['a.o', 'b.o']
@@ -1503,7 +1586,7 @@ module Rake
class << self
# Yield each file or directory component.
- def each_dir_parent(dir)
+ def each_dir_parent(dir) # :nodoc:
old_length = nil
while dir != '.' && dir.length != old_length
yield(dir)
@@ -1642,23 +1725,65 @@ module Rake
# Resolve the arguments for a task/rule. Returns a triplet of
# [task_name, arg_name_list, prerequisites].
def resolve_args(args)
+ if args.last.is_a?(Hash)
+ deps = args.pop
+ resolve_args_with_dependencies(args, deps)
+ else
+ resolve_args_without_dependencies(args)
+ end
+ end
+
+ # Resolve task arguments for a task or rule when there are no
+ # dependencies declared.
+ #
+ # The patterns recognized by this argument resolving function are:
+ #
+ # task :t
+ # task :t, [:a]
+ # task :t, :a (deprecated)
+ #
+ def resolve_args_without_dependencies(args)
task_name = args.shift
- arg_names = args #.map { |a| a.to_sym }
- needs = []
- if task_name.is_a?(Hash)
- hash = task_name
- task_name = hash.keys[0]
- needs = hash[task_name]
+ if args.size == 1 && args.first.respond_to?(:to_ary)
+ arg_names = args.first.to_ary
+ else
+ arg_names = args
end
- if arg_names.last.is_a?(Hash)
- hash = arg_names.pop
- needs = hash[:needs]
- fail "Unrecognized keys in task hash: #{hash.keys.inspect}" if hash.size > 1
+ [task_name, arg_names, []]
+ end
+ private :resolve_args_without_dependencies
+
+ # Resolve task arguments for a task or rule when there are
+ # dependencies declared.
+ #
+ # The patterns recognized by this argument resolving function are:
+ #
+ # task :t => [:d]
+ # task :t, [a] => [:d]
+ # task :t, :needs => [:d] (deprecated)
+ # task :t, :a, :needs => [:d] (deprecated)
+ #
+ def resolve_args_with_dependencies(args, hash) # :nodoc:
+ fail "Task Argument Error" if hash.size != 1
+ key, value = hash.map { |k, v| [k,v] }.first
+ if args.empty?
+ task_name = key
+ arg_names = []
+ deps = value
+ elsif key == :needs
+ task_name = args.shift
+ arg_names = args
+ deps = value
+ else
+ task_name = args.shift
+ arg_names = key
+ deps = value
end
- needs = [needs] unless needs.respond_to?(:to_ary)
- [task_name, arg_names, needs]
+ deps = [deps] unless deps.respond_to?(:to_ary)
+ [task_name, arg_names, deps]
end
-
+ private :resolve_args_with_dependencies
+
# If a rule can be found that matches the task name, enhance the
# task with the prerequisites and actions from the rule. Set the
# source attribute of the task appropriately for the rule. Return
@@ -1749,15 +1874,23 @@ module Rake
"_anon_#{@seed}"
end
+ def trace_rule(level, message)
+ puts "#{" "*level}#{message}" if Rake.application.options.trace_rules
+ end
+
# Attempt to create a rule given the list of prerequisites.
def attempt_rule(task_name, extensions, block, level)
sources = make_sources(task_name, extensions)
prereqs = sources.collect { |source|
+ trace_rule level, "Attempting Rule #{task_name} => #{source}"
if File.exist?(source) || Rake::Task.task_defined?(source)
+ trace_rule level, "(#{task_name} => #{source} ... EXIST)"
source
- elsif parent = enhance_with_matching_rule(sources.first, level+1)
+ elsif parent = enhance_with_matching_rule(source, level+1)
+ trace_rule level, "(#{task_name} => #{source} ... ENHANCE)"
parent.name
else
+ trace_rule level, "(#{task_name} => #{source} ... FAIL)"
return nil
end
}
@@ -1814,41 +1947,6 @@ module Rake
DEFAULT_RAKEFILES = ['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb'].freeze
- OPTIONS = [ # :nodoc:
- ['--classic-namespace', '-C', GetoptLong::NO_ARGUMENT,
- "Put Task and FileTask in the top level namespace"],
- ['--describe', '-D', GetoptLong::OPTIONAL_ARGUMENT,
- "Describe the tasks (matching optional PATTERN), then exit."],
- ['--rakefile', '-f', GetoptLong::OPTIONAL_ARGUMENT,
- "Use FILE as the rakefile."],
- ['--help', '-h', '-H', GetoptLong::NO_ARGUMENT,
- "Display this help message."],
- ['--libdir', '-I', GetoptLong::REQUIRED_ARGUMENT,
- "Include LIBDIR in the search path for required modules."],
- ['--dry-run', '-n', GetoptLong::NO_ARGUMENT,
- "Do a dry run without executing actions."],
- ['--nosearch', '-N', GetoptLong::NO_ARGUMENT,
- "Do not search parent directories for the Rakefile."],
- ['--prereqs', '-P', GetoptLong::NO_ARGUMENT,
- "Display the tasks and dependencies, then exit."],
- ['--quiet', '-q', GetoptLong::NO_ARGUMENT,
- "Do not log messages to standard output."],
- ['--require', '-r', GetoptLong::REQUIRED_ARGUMENT,
- "Require MODULE before executing rakefile."],
- ['--rakelibdir', '-R', GetoptLong::REQUIRED_ARGUMENT,
- "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')"],
- ['--silent', '-s', GetoptLong::NO_ARGUMENT,
- "Like --quiet, but also suppresses the 'in directory' announcement."],
- ['--tasks', '-T', GetoptLong::OPTIONAL_ARGUMENT,
- "Display the tasks (matching optional PATTERN) with descriptions, then exit."],
- ['--trace', '-t', GetoptLong::NO_ARGUMENT,
- "Turn on invoke/execute tracing, enable full backtrace."],
- ['--verbose', '-v', GetoptLong::NO_ARGUMENT,
- "Log message to standard output (default)."],
- ['--version', '-V', GetoptLong::NO_ARGUMENT,
- "Display the program version."],
- ]
-
# Initialize a Rake::Application object.
def initialize
super
@@ -1861,8 +1959,10 @@ module Rake
@default_loader = Rake::DefaultLoader.new
@original_dir = Dir.pwd
@top_level_tasks = []
+ add_loader('rb', DefaultLoader.new)
add_loader('rf', DefaultLoader.new)
add_loader('rake', DefaultLoader.new)
+ @tty_output = STDOUT.tty?
end
# Run the Rake application. The run method performs the following three steps:
@@ -1886,8 +1986,7 @@ module Rake
def init(app_name='rake')
standard_exception_handling do
@name = app_name
- handle_options
- collect_tasks
+ collect_tasks handle_options
end
end
@@ -1942,16 +2041,16 @@ module Rake
[name, args]
end
- # Provide standard exception handling for the given block.
+ # Provide standard execption handling for the given block.
def standard_exception_handling
begin
yield
rescue SystemExit => ex
# Exit silently with current status
- exit(ex.status)
- rescue SystemExit, GetoptLong::InvalidOption => ex
+ raise
+ rescue OptionParser::InvalidOption => ex
# Exit silently
- exit(1)
+ exit(false)
rescue Exception => ex
# Exit with error message
$stderr.puts "rake aborted!"
@@ -1962,7 +2061,7 @@ module Rake
$stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
$stderr.puts "(See full trace by running task with --trace)"
end
- exit(1)
+ exit(false)
end
end
@@ -1971,33 +2070,26 @@ module Rake
def have_rakefile
@rakefiles.each do |fn|
if File.exist?(fn) || fn == ''
- @rakefile = fn
- return true
+ return fn
end
end
- return false
+ return nil
end
- # Display the rake command line help.
- def help
- puts "rake [-f rakefile] {options} targets..."
- puts
- puts "Options are ..."
- puts
- OPTIONS.sort.each do |long, *short, mode, desc|
- case mode
- when GetoptLong::REQUIRED_ARGUMENT
- if desc =~ /\b([A-Z]{2,})\b/
- long = long + "=#{$1}"
- end
- when GetoptLong::OPTIONAL_ARGUMENT
- if desc =~ /\b([A-Z]{2,})\b/
- long = long + "[=#{$1}]"
- end
- end
- printf " %-20s (%s)\n", long, short.join(", ")
- printf " %s\n", desc
- end
+ # True if we are outputting to TTY, false otherwise
+ def tty_output?
+ @tty_output
+ end
+
+ # Override the detected TTY output state (mostly for testing)
+ def tty_output=( tty_output_state )
+ @tty_output = tty_output_state
+ end
+
+ # We will truncate output if we are outputting to a TTY or if we've been
+ # given an explicit column width to honor
+ def truncate_output?
+ tty_output? || ENV['RAKE_COLUMNS']
end
# Display the tasks and dependencies.
@@ -2015,19 +2107,51 @@ module Rake
end
else
width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10
- max_column = 80 - name.size - width - 7
+ max_column = truncate_output? ? terminal_width - name.size - width - 7 : nil
displayable_tasks.each do |t|
printf "#{name} %-#{width}s # %s\n",
- t.name_with_args, truncate(t.comment, max_column)
+ t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment
end
end
end
+ def terminal_width
+ if ENV['RAKE_COLUMNS']
+ result = ENV['RAKE_COLUMNS'].to_i
+ else
+ result = unix? ? dynamic_width : 80
+ end
+ (result < 10) ? 80 : result
+ rescue
+ 80
+ end
+
+ # Calculate the dynamic width of the
+ def dynamic_width
+ @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
+ end
+
+ def dynamic_width_stty
+ %x{stty size 2>/dev/null}.split[1].to_i
+ end
+
+ def dynamic_width_tput
+ %x{tput cols 2>/dev/null}.to_i
+ end
+
+ def unix?
+ RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
+ end
+
+ def windows?
+ Config::CONFIG['host_os'] =~ /mswin/
+ end
+
def truncate(string, width)
if string.length <= width
string
else
- string[0, width-3] + "..."
+ ( string[0, width-3] || "" ) + "..."
end
end
@@ -2039,77 +2163,141 @@ module Rake
end
end
- # Return a list of the command line options supported by the
- # program.
- def command_line_options
- OPTIONS.collect { |lst| lst[0..-2] }
- end
-
- # Do the option defined by +opt+ and +value+.
- def do_option(opt, value)
- case opt
- when '--describe'
- options.show_tasks = true
- options.show_task_pattern = Regexp.new(value || '.')
- options.full_description = true
- when '--dry-run'
- verbose(true)
- nowrite(true)
- options.dryrun = true
- options.trace = true
- when '--help'
- help
- exit
- when '--libdir'
- $:.push(value)
- when '--nosearch'
- options.nosearch = true
- when '--prereqs'
- options.show_prereqs = true
- when '--quiet'
- verbose(false)
- when '--rakefile'
- @rakefiles.clear
- @rakefiles << value
- when '--rakelibdir'
- options.rakelib = value.split(':')
- when '--require'
- begin
- require value
- rescue LoadError => ex
- begin
- rake_require value
- rescue LoadError => ex2
- raise ex
- end
- end
- when '--silent'
- verbose(false)
- options.silent = true
- when '--tasks'
- options.show_tasks = true
- options.show_task_pattern = Regexp.new(value || '.')
- options.full_description = false
- when '--trace'
- options.trace = true
- verbose(true)
- when '--verbose'
- verbose(true)
- when '--version'
- puts "rake, version #{RAKEVERSION}"
- exit
- when '--classic-namespace'
- require 'rake/classic_namespace'
- options.classic_namespace = true
- end
+ # A list of all the standard options used in rake, suitable for
+ # passing to OptionParser.
+ def standard_rake_options
+ [
+ ['--classic-namespace', '-C', "Put Task and FileTask in the top level namespace",
+ lambda { |value|
+ require 'rake/classic_namespace'
+ options.classic_namespace = true
+ }
+ ],
+ ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.",
+ lambda { |value|
+ options.show_tasks = true
+ options.full_description = true
+ options.show_task_pattern = Regexp.new(value || '')
+ }
+ ],
+ ['--dry-run', '-n', "Do a dry run without executing actions.",
+ lambda { |value|
+ verbose(true)
+ nowrite(true)
+ options.dryrun = true
+ options.trace = true
+ }
+ ],
+ ['--execute', '-e CODE', "Execute some Ruby code and exit.",
+ lambda { |value|
+ eval(value)
+ exit
+ }
+ ],
+ ['--execute-print', '-p CODE', "Execute some Ruby code, print the result, then exit.",
+ lambda { |value|
+ puts eval(value)
+ exit
+ }
+ ],
+ ['--execute-continue', '-E CODE',
+ "Execute some Ruby code, then continue with normal task processing.",
+ lambda { |value| eval(value) }
+ ],
+ ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.",
+ lambda { |value| $:.push(value) }
+ ],
+ ['--prereqs', '-P', "Display the tasks and dependencies, then exit.",
+ lambda { |value| options.show_prereqs = true }
+ ],
+ ['--quiet', '-q', "Do not log messages to standard output.",
+ lambda { |value| verbose(false) }
+ ],
+ ['--rakefile', '-f [FILE]', "Use FILE as the rakefile.",
+ lambda { |value|
+ value ||= ''
+ @rakefiles.clear
+ @rakefiles << value
+ }
+ ],
+ ['--rakelibdir', '--rakelib', '-R RAKELIBDIR',
+ "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')",
+ lambda { |value| options.rakelib = value.split(':') }
+ ],
+ ['--require', '-r MODULE', "Require MODULE before executing rakefile.",
+ lambda { |value|
+ begin
+ require value
+ rescue LoadError => ex
+ begin
+ rake_require value
+ rescue LoadError => ex2
+ raise ex
+ end
+ end
+ }
+ ],
+ ['--rules', "Trace the rules resolution.",
+ lambda { |value| options.trace_rules = true }
+ ],
+ ['--no-search', '--nosearch', '-N', "Do not search parent directories for the Rakefile.",
+ lambda { |value| options.nosearch = true }
+ ],
+ ['--silent', '-s', "Like --quiet, but also suppresses the 'in directory' announcement.",
+ lambda { |value|
+ verbose(false)
+ options.silent = true
+ }
+ ],
+ ['--system', '-g',
+ "Using system wide (global) rakefiles (usually '~/.rake/*.rake').",
+ lambda { |value| options.load_system = true }
+ ],
+ ['--no-system', '--nosystem', '-G',
+ "Use standard project Rakefile search paths, ignore system wide rakefiles.",
+ lambda { |value| options.ignore_system = true }
+ ],
+ ['--tasks', '-T [PATTERN]', "Display the tasks (matching optional PATTERN) with descriptions, then exit.",
+ lambda { |value|
+ options.show_tasks = true
+ options.show_task_pattern = Regexp.new(value || '')
+ options.full_description = false
+ }
+ ],
+ ['--trace', '-t', "Turn on invoke/execute tracing, enable full backtrace.",
+ lambda { |value|
+ options.trace = true
+ verbose(true)
+ }
+ ],
+ ['--verbose', '-v', "Log message to standard output (default).",
+ lambda { |value| verbose(true) }
+ ],
+ ['--version', '-V', "Display the program version.",
+ lambda { |value|
+ puts "rake, version #{RAKEVERSION}"
+ exit
+ }
+ ]
+ ]
end
# Read and handle the command line options.
def handle_options
options.rakelib = ['rakelib']
- opts = GetoptLong.new(*command_line_options)
- opts.each { |opt, value| do_option(opt, value) }
+ opts = OptionParser.new
+ opts.banner = "rake [-f rakefile] {options} targets..."
+ opts.separator ""
+ opts.separator "Options are ..."
+
+ opts.on_tail("-h", "--help", "-H", "Display this help message.") do
+ puts opts
+ exit
+ end
+
+ standard_rake_options.each { |args| opts.on(*args) }
+ parsed_argv = opts.parse(ARGV)
# If class namespaces are requested, set the global options
# according to the values in the options structure.
@@ -2120,12 +2308,11 @@ module Rake
$dryrun = options.dryrun
$silent = options.silent
end
- rescue NoMethodError => ex
- raise GetoptLong::InvalidOption, "While parsing options, error = #{ex.class}:#{ex.message}"
+ parsed_argv
end
# Similar to the regular Ruby +require+ command, but will check
- # for .rake files in addition to .rb files.
+ # for *.rake files in addition to *.rb files.
def rake_require(file_name, paths=$LOAD_PATH, loaded=$")
return false if loaded.include?(file_name)
paths.each do |path|
@@ -2140,34 +2327,95 @@ module Rake
fail LoadError, "Can't find #{file_name}"
end
- def raw_load_rakefile # :nodoc:
+ def find_rakefile_location
here = Dir.pwd
- while ! have_rakefile
+ while ! (fn = have_rakefile)
Dir.chdir("..")
if Dir.pwd == here || options.nosearch
- fail "No Rakefile found (looking for: #{@rakefiles.join(', ')})"
+ return nil
end
here = Dir.pwd
end
- puts "(in #{Dir.pwd})" unless options.silent
- $rakefile = @rakefile
- load File.expand_path(@rakefile) if @rakefile != ''
- options.rakelib.each do |rlib|
- Dir["#{rlib}/*.rake"].each do |name| add_import name end
+ [fn, here]
+ ensure
+ Dir.chdir(Rake.original_dir)
+ end
+
+ def raw_load_rakefile # :nodoc:
+ rakefile, location = find_rakefile_location
+ if (! options.ignore_system) &&
+ (options.load_system || rakefile.nil?) &&
+ directory?(system_dir)
+ puts "(in #{Dir.pwd})" unless options.silent
+ glob("#{system_dir}/*.rake") do |name|
+ add_import name
+ end
+ else
+ fail "No Rakefile found (looking for: #{@rakefiles.join(', ')})" if
+ rakefile.nil?
+ @rakefile = rakefile
+ Dir.chdir(location)
+ puts "(in #{Dir.pwd})" unless options.silent
+ $rakefile = @rakefile if options.classic_namespace
+ load File.expand_path(@rakefile) if @rakefile && @rakefile != ''
+ options.rakelib.each do |rlib|
+ glob("#{rlib}/*.rake") do |name|
+ add_import name
+ end
+ end
end
load_imports
end
+ def glob(path, &block)
+ Dir[path.gsub("\\", '/')].each(&block)
+ end
+ private :glob
+
+ # The directory path containing the system wide rakefiles.
+ def system_dir
+ if ENV['RAKE_SYSTEM']
+ ENV['RAKE_SYSTEM']
+ elsif windows?
+ win32_system_dir
+ else
+ standard_system_dir
+ end
+ end
+
+ # The standard directory containing system wide rake files.
+ def standard_system_dir #:nodoc:
+ File.join(File.expand_path('~'), '.rake')
+ end
+ private :standard_system_dir
+
+ # The standard directory containing system wide rake files on Win
+ # 32 systems.
+ def win32_system_dir #:nodoc:
+ win32home = File.join(ENV['APPDATA'], 'Rake')
+ unless directory?(win32home)
+ raise Win32HomeError, "Unable to determine home path environment variable."
+ else
+ win32home
+ end
+ end
+ private :win32_system_dir
+
+ def directory?(path)
+ File.directory?(path)
+ end
+ private :directory?
+
# Collect the list of tasks on the command line. If no tasks are
# given, return a list containing only the default task.
# Environmental assignments are processed at this time as well.
- def collect_tasks
+ def collect_tasks(argv)
@top_level_tasks = []
- ARGV.each do |arg|
+ argv.each do |arg|
if arg =~ /^(\w+)=(.*)$/
ENV[$1] = $2
else
- @top_level_tasks << arg
+ @top_level_tasks << arg unless arg =~ /^-/
end
end
@top_level_tasks.push("default") if @top_level_tasks.size == 0
diff --git a/lib/rake/loaders/makefile.rb b/lib/rake/loaders/makefile.rb
index f66eb3b35f..9ade098a1b 100644
--- a/lib/rake/loaders/makefile.rb
+++ b/lib/rake/loaders/makefile.rb
@@ -7,31 +7,26 @@ module Rake
# Load the makefile dependencies in +fn+.
def load(fn)
- buffer = ''
open(fn) do |mf|
- mf.each do |line|
- next if line =~ /^\s*#/
- buffer << line
- if buffer =~ /\\$/
- buffer.sub!(/\\\n/, ' ')
- state = :append
- else
- process_line(buffer)
- buffer = ''
- end
+ lines = mf.read
+ lines.gsub!(/#[^\n]*\n/m, "")
+ lines.gsub!(/\\\n/, ' ')
+ lines.split("\n").each do |line|
+ process_line(line)
end
end
- process_line(buffer) if buffer != ''
end
private
# Process one logical line of makefile data.
def process_line(line)
- file_task, args = line.split(':')
+ file_tasks, args = line.split(':')
return if args.nil?
dependents = args.split
- file file_task => dependents
+ file_tasks.strip.split.each do |file_task|
+ file file_task => dependents
+ end
end
end
diff --git a/lib/rake/packagetask.rb b/lib/rake/packagetask.rb
index 71b66a6481..4b0775d09c 100644
--- a/lib/rake/packagetask.rb
+++ b/lib/rake/packagetask.rb
@@ -122,6 +122,7 @@ module Rake
task :package => ["#{package_dir}/#{file}"]
file "#{package_dir}/#{file}" => [package_dir_path] + package_files do
chdir(package_dir) do
+ sh %{env}
sh %{#{@tar_command} #{flag}cvf #{file} #{package_name}}
end
end
diff --git a/lib/rake/rdoctask.rb b/lib/rake/rdoctask.rb
index 54adc6feb5..6cfbda1d6a 100644
--- a/lib/rake/rdoctask.rb
+++ b/lib/rake/rdoctask.rb
@@ -55,7 +55,7 @@ module Rake
# RDoc. (default is none)
attr_accessor :main
- # Name of template to be used by rdoc. (default is 'html')
+ # Name of template to be used by rdoc. (defaults to rdoc's default)
attr_accessor :template
# List of files to be included in the rdoc generation. (default is [])
@@ -74,7 +74,7 @@ module Rake
@rdoc_dir = 'html'
@main = nil
@title = nil
- @template = 'html'
+ @template = nil
@external = false
@options = []
yield self if block_given?
@@ -91,18 +91,18 @@ module Rake
task name
desc "Force a rebuild of the RDOC files"
- task paste("re", name) => [paste("clobber_", name), name]
+ task "re#{name}" => ["clobber_#{name}", name]
desc "Remove rdoc products"
- task paste("clobber_", name) do
+ task "clobber_#{name}" do
rm_r rdoc_dir rescue nil
end
-
- task :clobber => [paste("clobber_", name)]
+
+ task :clobber => ["clobber_#{name}"]
directory @rdoc_dir
task name => [rdoc_target]
- file rdoc_target => @rdoc_files + [$rakefile] do
+ file rdoc_target => @rdoc_files + [Rake.application.rakefile] do
rm_r @rdoc_dir rescue nil
args = option_list + @rdoc_files
if @external
diff --git a/lib/rake/tasklib.rb b/lib/rake/tasklib.rb
index 465a58a0c7..c7fd98133c 100644
--- a/lib/rake/tasklib.rb
+++ b/lib/rake/tasklib.rb
@@ -6,11 +6,16 @@ module Rake
# Base class for Task Libraries.
class TaskLib
-
include Cloneable
- # Make a symbol by pasting two strings together.
- def paste(a,b)
+ # Make a symbol by pasting two strings together.
+ #
+ # NOTE: DEPRECATED! This method is kinda stupid. I don't know why
+ # I didn't just use string interpolation. But now other task
+ # libraries depend on this so I can't remove it without breaking
+ # other people's code. So for now it stays for backwards
+ # compatibility. BUT DON'T USE IT.
+ def paste(a,b) # :nodoc:
(a.to_s + b.to_s).intern
end
end
diff --git a/lib/rake/testtask.rb b/lib/rake/testtask.rb
index f5b77e5957..79154e422b 100644
--- a/lib/rake/testtask.rb
+++ b/lib/rake/testtask.rb
@@ -136,7 +136,12 @@ module Rake
end
def fix # :nodoc:
- ''
+ case RUBY_VERSION
+ when '1.8.2'
+ find_file 'rake/ruby182_test_unit_fix'
+ else
+ nil
+ end || ''
end
def rake_loader # :nodoc:
diff --git a/lib/resolv.rb b/lib/resolv.rb
index d1494b46c9..fc3c78215b 100644
--- a/lib/resolv.rb
+++ b/lib/resolv.rb
@@ -13,24 +13,24 @@ end
# interpreter.
#
# See also resolv-replace.rb to replace the libc resolver with # Resolv.
-#
+#
# Resolv can look up various DNS resources using the DNS module directly.
-#
+#
# Examples:
-#
+#
# p Resolv.getaddress "www.ruby-lang.org"
# p Resolv.getname "210.251.121.214"
-#
+#
# Resolv::DNS.open do |dns|
# ress = dns.getresources "www.ruby-lang.org", Resolv::DNS::Resource::IN::A
# p ress.map { |r| r.address }
# ress = dns.getresources "ruby-lang.org", Resolv::DNS::Resource::IN::MX
# p ress.map { |r| [r.exchange.to_s, r.preference] }
# end
-#
-#
+#
+#
# == Bugs
-#
+#
# * NIS is not supported.
# * /etc/nsswitch.conf is not supported.
@@ -38,14 +38,14 @@ class Resolv
##
# Looks up the first IP address for +name+.
-
+
def self.getaddress(name)
DefaultResolver.getaddress(name)
end
##
# Looks up all IP address for +name+.
-
+
def self.getaddresses(name)
DefaultResolver.getaddresses(name)
end
@@ -87,7 +87,7 @@ class Resolv
##
# Looks up the first IP address for +name+.
-
+
def getaddress(name)
each_address(name) {|address| return address}
raise ResolvError.new("no address for #{name}")
@@ -95,7 +95,7 @@ class Resolv
##
# Looks up all IP address for +name+.
-
+
def getaddresses(name)
ret = []
each_address(name) {|address| ret << address}
@@ -309,7 +309,7 @@ class Resolv
# Creates a new DNS resolver.
#
# +config_info+ can be:
- #
+ #
# nil:: Uses /etc/resolv.conf.
# String:: Path to a file using /etc/resolv.conf's format.
# Hash:: Must contain :nameserver, :search and :ndots keys.
@@ -457,7 +457,7 @@ class Resolv
##
# Looks up all +typeclass+ DNS resources for +name+. See #getresource for
# argument details.
-
+
def getresources(name, typeclass)
ret = []
each_resource(name, typeclass) {|resource| ret << resource}
@@ -467,7 +467,7 @@ class Resolv
##
# Iterates over all +typeclass+ DNS resources for +name+. See
# #getresource for argument details.
-
+
def each_resource(name, typeclass, &proc)
lazy_initialize
requester = make_requester
@@ -569,7 +569,7 @@ class Resolv
h = (RequestID[[host, port]] ||= {})
begin
id = rangerand(0x0000..0xffff)
- end while h[id]
+ end while h[id]
h[id] = true
}
id
@@ -1037,7 +1037,7 @@ class Resolv
# A representation of a DNS name.
class Name
-
+
##
# Creates a new DNS name from +arg+. +arg+ can be:
#
@@ -1460,11 +1460,11 @@ class Resolv
class Query
def encode_rdata(msg) # :nodoc:
- raise EncodeError.new("#{self.class} is query.")
+ raise EncodeError.new("#{self.class} is query.")
end
def self.decode_rdata(msg) # :nodoc:
- raise DecodeError.new("#{self.class} is query.")
+ raise DecodeError.new("#{self.class} is query.")
end
end
@@ -1939,7 +1939,7 @@ class Resolv
def initialize(address)
@address = IPv6.create(address)
end
-
+
##
# The Resolv::IPv6 address for this AAAA.
@@ -1956,7 +1956,7 @@ class Resolv
##
# SRV resource record defined in RFC 2782
- #
+ #
# These records identify the hostname and port that a service is
# available at.
diff --git a/lib/time.rb b/lib/time.rb
index 96f3945320..85c715b80b 100644
--- a/lib/time.rb
+++ b/lib/time.rb
@@ -1,37 +1,37 @@
#
# == Introduction
-#
+#
# This library extends the Time class:
# * conversion between date string and time object.
# * date-time defined by RFC 2822
# * HTTP-date defined by RFC 2616
# * dateTime defined by XML Schema Part 2: Datatypes (ISO 8601)
# * various formats handled by Date._parse (string to time only)
-#
+#
# == Design Issues
-#
+#
# === Specialized interface
-#
+#
# This library provides methods dedicated to special purposes:
# * RFC 2822, RFC 2616 and XML Schema.
# * They makes usual life easier.
-#
+#
# === Doesn't depend on strftime
-#
+#
# This library doesn't use +strftime+. Especially #rfc2822 doesn't depend
# on +strftime+ because:
-#
+#
# * %a and %b are locale sensitive
-#
+#
# Since they are locale sensitive, they may be replaced to
# invalid weekday/month name in some locales.
# Since ruby-1.6 doesn't invoke setlocale by default,
# the problem doesn't arise until some external library invokes setlocale.
# Ruby/GTK is the example of such library.
-#
+#
# * %z is not portable
-#
+#
# %z is required to generate zone in date-time of RFC 2822
# but it is not portable.
#
@@ -61,9 +61,9 @@ class Time
'PST' => -8, 'PDT' => -7,
# Following definition of military zones is original one.
# See RFC 1123 and RFC 2822 for the error in RFC 822.
- 'A' => +1, 'B' => +2, 'C' => +3, 'D' => +4, 'E' => +5, 'F' => +6,
+ 'A' => +1, 'B' => +2, 'C' => +3, 'D' => +4, 'E' => +5, 'F' => +6,
'G' => +7, 'H' => +8, 'I' => +9, 'K' => +10, 'L' => +11, 'M' => +12,
- 'N' => -1, 'O' => -2, 'P' => -3, 'Q' => -4, 'R' => -5, 'S' => -6,
+ 'N' => -1, 'O' => -2, 'P' => -3, 'Q' => -4, 'R' => -5, 'S' => -6,
'T' => -7, 'U' => -8, 'V' => -9, 'W' => -10, 'X' => -11, 'Y' => -12,
}
def zone_offset(zone, year=self.now.year)
@@ -436,8 +436,8 @@ class Time
#
# Returns a string which represents the time as rfc1123-date of HTTP-date
- # defined by RFC 2616:
- #
+ # defined by RFC 2616:
+ #
# day-of-week, DD month-name CCYY hh:mm:ss GMT
#
# Note that the result is always UTC (GMT).
@@ -768,21 +768,21 @@ if __FILE__ == $0
def test_rfc2822_leap_second
t = Time.utc(1998,12,31,23,59,59)
assert_equal(t, Time.rfc2822("Thu, 31 Dec 1998 23:59:59 UTC"))
- assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 -0000"));t.localtime
+ assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 -0000"));t.localtime
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 08:59:59 +0900"))
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:59:59 +0100"))
assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 +0000"))
- assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:59 -0100"));t.utc
+ assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:59 -0100"));t.utc
t += 1
assert_equal(t, Time.rfc2822("Thu, 31 Dec 1998 23:59:60 UTC"))
- assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 -0000"));t.localtime
+ assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 -0000"));t.localtime
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 08:59:60 +0900"))
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:59:60 +0100"))
assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 +0000"))
- assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:60 -0100"));t.utc
+ assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:60 -0100"));t.utc
t += 1 if t.sec == 60
assert_equal(t, Time.rfc2822("Thu, 1 Jan 1999 00:00:00 UTC"))
- assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 -0000"));t.localtime
+ assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 -0000"));t.localtime
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 09:00:00 +0900"))
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 01:00:00 +0100"))
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 +0000"))
diff --git a/lib/tsort.rb b/lib/tsort.rb
index a014e7f6c2..9fc4feadcd 100644
--- a/lib/tsort.rb
+++ b/lib/tsort.rb
@@ -32,7 +32,7 @@
# array using the user-supplied block.
#
# require 'tsort'
-#
+#
# class Hash
# include TSort
# alias tsort_each_node each_key
@@ -40,10 +40,10 @@
# fetch(node).each(&block)
# end
# end
-#
+#
# {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort
# #=> [3, 2, 1, 4]
-#
+#
# {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components
# #=> [[4], [2, 3], [1]]
#
@@ -52,19 +52,19 @@
# A very simple `make' like tool can be implemented as follows:
#
# require 'tsort'
-#
+#
# class Make
# def initialize
# @dep = {}
# @dep.default = []
# end
-#
+#
# def rule(outputs, inputs=[], &block)
# triple = [outputs, inputs, block]
# outputs.each {|f| @dep[f] = [triple]}
# @dep[triple] = inputs
# end
-#
+#
# def build(target)
# each_strongly_connected_component_from(target) {|ns|
# if ns.length != 1
@@ -88,18 +88,18 @@
# end
# }
# end
-#
+#
# def tsort_each_child(node, &block)
# @dep[node].each(&block)
# end
# include TSort
# end
-#
+#
# def command(arg)
# print arg, "\n"
# system arg
# end
-#
+#
# m = Make.new
# m.rule(%w[t1]) { command 'date > t1' }
# m.rule(%w[t2]) { command 'date > t2' }
@@ -189,7 +189,7 @@ module TSort
end
#
- # Iterates over strongly connected component in the subgraph reachable from
+ # Iterates over strongly connected component in the subgraph reachable from
# _node_.
#
# Return value is unspecified.
diff --git a/lib/uri/common.rb b/lib/uri/common.rb
index 98dda2a350..9a6a06894a 100644
--- a/lib/uri/common.rb
+++ b/lib/uri/common.rb
@@ -227,7 +227,7 @@ module URI
end
def unescape(str, escaped = @regexp[:ESCAPED])
- str.gsub(escaped) { [$&.hex].pack('U') }
+ str.gsub(escaped) { [$&[1, 2].hex].pack('U') }
end
@@to_s = Kernel.instance_method(:to_s)
diff --git a/load.c b/load.c
index a6daff43f6..08238a1c9d 100644
--- a/load.c
+++ b/load.c
@@ -698,5 +698,5 @@ Init_load()
rb_define_global_function("autoload?", rb_f_autoload_p, 1);
ruby_dln_librefs = rb_ary_new();
- rb_register_mark_object(ruby_dln_librefs);
+ rb_gc_register_mark_object(ruby_dln_librefs);
}
diff --git a/marshal.c b/marshal.c
index 0cba2f7bf5..352ab443e9 100644
--- a/marshal.c
+++ b/marshal.c
@@ -1723,9 +1723,9 @@ Init_marshal(void)
rb_define_const(rb_mMarshal, "MINOR_VERSION", INT2FIX(MARSHAL_MINOR));
compat_allocator_tbl = st_init_numtable();
- rb_gc_register_address(&compat_allocator_tbl_wrapper);
compat_allocator_tbl_wrapper =
Data_Wrap_Struct(rb_cData, mark_marshal_compat_t, 0, compat_allocator_tbl);
+ rb_gc_register_mark_object(compat_allocator_tbl_wrapper);
}
VALUE
diff --git a/math.c b/math.c
index ac0d4c1fe7..340014b624 100644
--- a/math.c
+++ b/math.c
@@ -353,7 +353,7 @@ math_log(int argc, VALUE *argv)
Need_Float(x);
errno = 0;
d = log(RFLOAT_VALUE(x));
- if (!NIL_P(base)) {
+ if (argc == 2) {
Need_Float(base);
d /= log(RFLOAT_VALUE(base));
}
diff --git a/numeric.c b/numeric.c
index 45e17d2801..06351eca31 100644
--- a/numeric.c
+++ b/numeric.c
@@ -78,6 +78,9 @@ round(double x)
}
return x;
}
+#elif defined(__BEOS__)
+/* appears to be a bug in the BeOS headers */
+double round(double x);
#endif
static ID id_coerce, id_to_i, id_eq;
@@ -385,14 +388,14 @@ num_remainder(VALUE x, VALUE y)
/*
* call-seq:
- * num.scalar? -> true or false
+ * num.real? -> true or false
*
- * Returns <code>true</code> if <i>num</i> is an <code>Scalar</code>
+ * Returns <code>true</code> if <i>num</i> is a <code>Real</code>
* (i.e. non <code>Complex</code>).
*/
static VALUE
-num_scalar_p(VALUE num)
+num_real_p(VALUE num)
{
return Qtrue;
}
@@ -1948,66 +1951,6 @@ int_denominator(VALUE num)
/*
* call-seq:
- * Fixnum.induced_from(obj) => fixnum
- *
- * Convert <code>obj</code> to a Fixnum. Works with numeric parameters.
- * Also works with Symbols, but this is deprecated.
- */
-
-static VALUE
-rb_fix_induced_from(VALUE klass, VALUE x)
-{
- return rb_num2fix(x);
-}
-
-/*
- * call-seq:
- * Integer.induced_from(obj) => fixnum, bignum
- *
- * Convert <code>obj</code> to an Integer.
- */
-
-static VALUE
-rb_int_induced_from(VALUE klass, VALUE x)
-{
- switch (TYPE(x)) {
- case T_FIXNUM:
- case T_BIGNUM:
- return x;
- case T_FLOAT:
- case T_RATIONAL:
- return rb_funcall(x, id_to_i, 0);
- default:
- rb_raise(rb_eTypeError, "failed to convert %s into Integer",
- rb_obj_classname(x));
- }
-}
-
-/*
- * call-seq:
- * Float.induced_from(obj) => float
- *
- * Convert <code>obj</code> to a float.
- */
-
-static VALUE
-rb_flo_induced_from(VALUE klass, VALUE x)
-{
- switch (TYPE(x)) {
- case T_FIXNUM:
- case T_BIGNUM:
- case T_RATIONAL:
- return rb_funcall(x, rb_intern("to_f"), 0);
- case T_FLOAT:
- return x;
- default:
- rb_raise(rb_eTypeError, "failed to convert %s into Float",
- rb_obj_classname(x));
- }
-}
-
-/*
- * call-seq:
* -fix => integer
*
* Negates <code>fix</code> (which might return a Bignum).
@@ -2447,7 +2390,7 @@ fix_pow(VALUE x, VALUE y)
long b = FIX2LONG(y);
if (b < 0)
- return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
+ return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
if (b == 0) return INT2FIX(1);
if (b == 1) return x;
@@ -2468,7 +2411,7 @@ fix_pow(VALUE x, VALUE y)
case T_BIGNUM:
if (rb_funcall(y, '<', 1, INT2FIX(0)))
- return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
+ return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
if (a == 0) return INT2FIX(0);
if (a == 1) return INT2FIX(1);
@@ -3145,7 +3088,7 @@ Init_Numeric(void)
rb_define_method(rb_cNumeric, "magnitude", num_abs, 0);
rb_define_method(rb_cNumeric, "to_int", num_to_int, 0);
- rb_define_method(rb_cNumeric, "scalar?", num_scalar_p, 0);
+ rb_define_method(rb_cNumeric, "real?", num_real_p, 0);
rb_define_method(rb_cNumeric, "integer?", num_int_p, 0);
rb_define_method(rb_cNumeric, "zero?", num_zero_p, 0);
rb_define_method(rb_cNumeric, "nonzero?", num_nonzero_p, 0);
@@ -3169,7 +3112,6 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "upto", int_upto, 1);
rb_define_method(rb_cInteger, "downto", int_downto, 1);
rb_define_method(rb_cInteger, "times", int_dotimes, 0);
- rb_include_module(rb_cInteger, rb_mPrecision);
rb_define_method(rb_cInteger, "succ", int_succ, 0);
rb_define_method(rb_cInteger, "next", int_succ, 0);
rb_define_method(rb_cInteger, "pred", int_pred, 0);
@@ -3182,9 +3124,6 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "round", int_round, -1);
rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
- rb_include_module(rb_cFixnum, rb_mPrecision);
- rb_define_singleton_method(rb_cFixnum, "induced_from", rb_fix_induced_from, 1);
- rb_define_singleton_method(rb_cInteger, "induced_from", rb_int_induced_from, 1);
rb_define_method(rb_cInteger, "numerator", int_numerator, 0);
rb_define_method(rb_cInteger, "denominator", int_denominator, 0);
@@ -3234,9 +3173,6 @@ Init_Numeric(void)
rb_undef_alloc_func(rb_cFloat);
rb_undef_method(CLASS_OF(rb_cFloat), "new");
- rb_define_singleton_method(rb_cFloat, "induced_from", rb_flo_induced_from, 1);
- rb_include_module(rb_cFloat, rb_mPrecision);
-
rb_define_const(rb_cFloat, "ROUNDS", INT2FIX(FLT_ROUNDS));
rb_define_const(rb_cFloat, "RADIX", INT2FIX(FLT_RADIX));
rb_define_const(rb_cFloat, "MANT_DIG", INT2FIX(DBL_MANT_DIG));
diff --git a/object.c b/object.c
index 58b6235a82..560092d07b 100644
--- a/object.c
+++ b/object.c
@@ -2369,6 +2369,12 @@ boot_defclass(const char *name, VALUE super)
return obj;
}
+static void
+boot_defmetametaclass(VALUE klass, VALUE metametaclass)
+{
+ RBASIC(RBASIC(klass)->klass)->klass = metametaclass;
+}
+
/*
* Document-class: Class
*
@@ -2467,6 +2473,9 @@ Init_Object(void)
metaclass = rb_make_metaclass(rb_cObject, metaclass);
metaclass = rb_make_metaclass(rb_cModule, metaclass);
metaclass = rb_make_metaclass(rb_cClass, metaclass);
+ boot_defmetametaclass(rb_cModule, metaclass);
+ boot_defmetametaclass(rb_cObject, metaclass);
+ boot_defmetametaclass(rb_cBasicObject, metaclass);
rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);
rb_define_alloc_func(rb_cBasicObject, rb_class_allocate_instance);
diff --git a/parse.y b/parse.y
index eab982b75f..485a3979f7 100644
--- a/parse.y
+++ b/parse.y
@@ -264,12 +264,11 @@ struct parser_params {
#define UTF8_ENC() (parser->utf8 ? parser->utf8 : \
(parser->utf8 = rb_utf8_encoding()))
#define STR_NEW(p,n) rb_enc_str_new((p),(n),parser->enc)
-#define STR_NEW0() rb_usascii_str_new(0,0)
+#define STR_NEW0() rb_enc_str_new(0,0,parser->enc)
#define STR_NEW2(p) rb_enc_str_new((p),strlen(p),parser->enc)
#define STR_NEW3(p,n,e,func) parser_str_new((p),(n),(e),(func),parser->enc)
-#define STR_ENC(m) ((m)?parser->enc:rb_usascii_encoding())
#define ENC_SINGLE(cr) ((cr)==ENC_CODERANGE_7BIT)
-#define TOK_INTERN(mb) rb_intern3(tok(), toklen(), STR_ENC(mb))
+#define TOK_INTERN(mb) rb_intern3(tok(), toklen(), parser->enc)
#ifdef YYMALLOC
void *rb_parser_malloc(struct parser_params *, size_t);
@@ -4877,11 +4876,11 @@ parser_yyerror(struct parser_params *parser, const char *msg)
if (len > max_line_margin * 2 + 10) {
if (lex_p - p > max_line_margin) {
- p = rb_enc_prev_char(p, lex_p - max_line_margin, rb_enc_get(lex_lastline));
+ p = rb_enc_prev_char(p, lex_p - max_line_margin, pe, rb_enc_get(lex_lastline));
pre = "...";
}
if (pe - lex_p > max_line_margin) {
- pe = rb_enc_prev_char(lex_p, lex_p + max_line_margin, rb_enc_get(lex_lastline));
+ pe = rb_enc_prev_char(lex_p, lex_p + max_line_margin, pe, rb_enc_get(lex_lastline));
post = "...";
}
len = pe - p;
@@ -5150,7 +5149,6 @@ parser_str_new(const char *p, long n, rb_encoding *enc, int func, rb_encoding *e
str = rb_enc_str_new(p, n, enc);
if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) {
if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
- rb_enc_associate(str, rb_usascii_encoding());
}
else if (enc0 == rb_usascii_encoding() && enc != rb_utf8_encoding()) {
rb_enc_associate(str, rb_ascii8bit_encoding());
diff --git a/prec.c b/prec.c
deleted file mode 100644
index 84de958be8..0000000000
--- a/prec.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/**********************************************************************
-
- prec.c -
-
- $Author$
- created at: Tue Jan 26 02:40:41 2000
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby/ruby.h"
-
-VALUE rb_mPrecision;
-
-static ID prc_pr, prc_if;
-
-
-/*
- * call-seq:
- * num.prec(klass) => a_class
- *
- * Converts _self_ into an instance of _klass_. By default,
- * +prec+ invokes
- *
- * klass.induced_from(num)
- *
- * and returns its value. So, if <code>klass.induced_from</code>
- * doesn't return an instance of _klass_, it will be necessary
- * to reimplement +prec+.
- */
-
-static VALUE
-prec_prec(VALUE x, VALUE klass)
-{
- return rb_funcall(klass, prc_if, 1, x);
-}
-
-/*
- * call-seq:
- * num.prec_i => Integer
- *
- * Returns an +Integer+ converted from _num_. It is equivalent
- * to <code>prec(Integer)</code>.
- */
-
-static VALUE
-prec_prec_i(VALUE x)
-{
- VALUE klass = rb_cInteger;
-
- return rb_funcall(x, prc_pr, 1, klass);
-}
-
-/*
- * call-seq:
- * num.prec_f => Float
- *
- * Returns a +Float+ converted from _num_. It is equivalent
- * to <code>prec(Float)</code>.
- */
-
-static VALUE
-prec_prec_f(VALUE x)
-{
- VALUE klass = rb_cFloat;
-
- return rb_funcall(x, prc_pr, 1, klass);
-}
-
-/*
- * call-seq:
- * Mod.induced_from(number) => a_mod
- *
- * Creates an instance of mod from. This method is overridden
- * by concrete +Numeric+ classes, so that (for example)
- *
- * Fixnum.induced_from(9.9) #=> 9
- *
- * Note that a use of +prec+ in a redefinition may cause
- * an infinite loop.
- */
-
-static VALUE
-prec_induced_from(VALUE module, VALUE x)
-{
- rb_raise(rb_eTypeError, "undefined conversion from %s into %s",
- rb_obj_classname(x), rb_class2name(module));
- return Qnil; /* not reached */
-}
-
-/*
- * call_seq:
- * included
- *
- * When the +Precision+ module is mixed-in to a class, this +included+
- * method is used to add our default +induced_from+ implementation
- * to the host class.
- */
-
-static VALUE
-prec_included(VALUE module, VALUE include)
-{
- switch (TYPE(include)) {
- case T_CLASS:
- case T_MODULE:
- break;
- default:
- Check_Type(include, T_CLASS);
- break;
- }
- rb_define_singleton_method(include, "induced_from", prec_induced_from, 1);
- return module;
-}
-
-/*
- * Precision is a mixin for concrete numeric classes with
- * precision. Here, `precision' means the fineness of approximation
- * of a real number, so, this module should not be included into
- * anything which is not a subset of Real (so it should not be
- * included in classes such as +Complex+ or +Matrix+).
-*/
-
-void
-Init_Precision(void)
-{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
- rb_mPrecision = rb_define_module("Precision");
- rb_define_singleton_method(rb_mPrecision, "included", prec_included, 1);
- rb_define_method(rb_mPrecision, "prec", prec_prec, 1);
- rb_define_method(rb_mPrecision, "prec_i", prec_prec_i, 0);
- rb_define_method(rb_mPrecision, "prec_f", prec_prec_f, 0);
-
- prc_pr = rb_intern("prec");
- prc_if = rb_intern("induced_from");
-}
diff --git a/rational.c b/rational.c
index 7274ace1ff..3b352ea9da 100644
--- a/rational.c
+++ b/rational.c
@@ -27,8 +27,8 @@
VALUE rb_cRational;
static ID id_Unify, id_abs, id_cmp, id_convert, id_equal_p, id_expt,
- id_floor, id_format, id_idiv, id_inspect, id_integer_p, id_negate,
- id_new, id_new_bang, id_to_f, id_to_i, id_to_s, id_truncate;
+ id_floor, id_format, id_hash, id_idiv, id_inspect, id_integer_p,
+ id_negate, id_to_f, id_to_i, id_to_s, id_truncate;
#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
@@ -139,6 +139,7 @@ binop(xor, '^')
fun1(abs)
fun1(floor)
+fun1(hash)
fun1(inspect)
fun1(integer_p)
fun1(negate)
@@ -166,6 +167,8 @@ f_negative_p(VALUE x)
return rb_funcall(x, '<', 1, ZERO);
}
+#define f_positive_p(x) (!f_negative_p(x))
+
inline static VALUE
f_zero_p(VALUE x)
{
@@ -174,6 +177,8 @@ f_zero_p(VALUE x)
return rb_funcall(x, id_equal_p, 1, ZERO);
}
+#define f_nonzero_p(x) (!f_zero_p(x))
+
inline static VALUE
f_one_p(VALUE x)
{
@@ -212,6 +217,9 @@ k_rational_p(VALUE x)
return f_kind_of_p(x, rb_cRational);
}
+#define k_exact_p(x) (!k_float_p(x))
+#define k_inexact_p(x) k_float_p(x)
+
#ifndef NDEBUG
#define f_gcd f_gcd_orig
#endif
@@ -276,7 +284,7 @@ inline static VALUE
f_gcd(VALUE x, VALUE y)
{
VALUE r = f_gcd_orig(x, y);
- if (!f_zero_p(r)) {
+ if (f_nonzero_p(r)) {
assert(f_zero_p(f_mod(x, r)));
assert(f_zero_p(f_mod(y, r)));
}
@@ -362,8 +370,8 @@ f_rational_new_bang1(VALUE klass, VALUE x)
inline static VALUE
f_rational_new_bang2(VALUE klass, VALUE x, VALUE y)
{
- assert(!f_negative_p(y));
- assert(!f_zero_p(y));
+ assert(f_positive_p(y));
+ assert(f_nonzero_p(y));
return nurat_s_new_internal(klass, x, y);
}
@@ -772,7 +780,7 @@ nurat_fdiv(VALUE self, VALUE other)
static VALUE
nurat_expt(VALUE self, VALUE other)
{
- if (f_zero_p(other))
+ if (k_exact_p(other) && f_zero_p(other))
return f_rational_new_bang1(CLASS_OF(self), ONE);
if (k_rational_p(other)) {
@@ -951,7 +959,7 @@ nurat_quotrem(VALUE self, VALUE other)
static VALUE
nurat_abs(VALUE self)
{
- if (!f_negative_p(self))
+ if (f_positive_p(self))
return self;
return f_negate(self);
}
@@ -1102,7 +1110,7 @@ static VALUE
nurat_hash(VALUE self)
{
get_dat1(self);
- return f_xor(dat->num, dat->den);
+ return f_xor(f_hash(dat->num), f_hash(dat->den));
}
static VALUE
@@ -1124,8 +1132,12 @@ nurat_inspect(VALUE self)
static VALUE
nurat_marshal_dump(VALUE self)
{
+ VALUE a;
get_dat1(self);
- return rb_assoc_new(dat->num, dat->den);
+
+ a = rb_assoc_new(dat->num, dat->den);
+ rb_copy_generic_ivar(a, self);
+ return a;
}
static VALUE
@@ -1134,6 +1146,7 @@ nurat_marshal_load(VALUE self, VALUE a)
get_dat1(self);
dat->num = RARRAY_PTR(a)[0];
dat->den = RARRAY_PTR(a)[1];
+ rb_copy_generic_ivar(self, a);
if (f_zero_p(dat->den))
rb_raise_zerodiv();
@@ -1251,20 +1264,20 @@ make_patterns(void)
if (rat_pat) return;
rat_pat = rb_reg_new(rat_pat_source, sizeof rat_pat_source - 1, 0);
- rb_global_variable(&rat_pat);
+ rb_gc_register_mark_object(rat_pat);
an_e_pat = rb_reg_new(an_e_pat_source, sizeof an_e_pat_source - 1, 0);
- rb_global_variable(&an_e_pat);
+ rb_gc_register_mark_object(an_e_pat);
a_dot_pat = rb_reg_new(a_dot_pat_source, sizeof a_dot_pat_source - 1, 0);
- rb_global_variable(&a_dot_pat);
+ rb_gc_register_mark_object(a_dot_pat);
underscores_pat = rb_reg_new(underscores_pat_source,
sizeof underscores_pat_source - 1, 0);
- rb_global_variable(&underscores_pat);
+ rb_gc_register_mark_object(underscores_pat);
an_underscore = rb_str_new2("_");
- rb_global_variable(&an_underscore);
+ rb_gc_register_mark_object(an_underscore);
}
#define id_match rb_intern("match")
@@ -1393,26 +1406,18 @@ nurat_s_convert(int argc, VALUE *argv, VALUE klass)
{
VALUE a1, a2, backref;
- rb_scan_args(argc, argv, "02", &a1, &a2);
+ rb_scan_args(argc, argv, "11", &a1, &a2);
switch (TYPE(a1)) {
case T_COMPLEX:
- if (k_float_p(RCOMPLEX(a1)->image) || !f_zero_p(RCOMPLEX(a1)->image)) {
- VALUE s = f_to_s(a1);
- rb_raise(rb_eRangeError, "can't accept %s",
- StringValuePtr(s));
- }
- a1 = RCOMPLEX(a1)->real;
+ if (k_exact_p(RCOMPLEX(a1)->imag) && f_zero_p(RCOMPLEX(a1)->imag))
+ a1 = RCOMPLEX(a1)->real;
}
switch (TYPE(a2)) {
case T_COMPLEX:
- if (k_float_p(RCOMPLEX(a2)->image) || !f_zero_p(RCOMPLEX(a2)->image)) {
- VALUE s = f_to_s(a2);
- rb_raise(rb_eRangeError, "can't accept %s",
- StringValuePtr(s));
- }
- a2 = RCOMPLEX(a2)->real;
+ if (k_exact_p(RCOMPLEX(a2)->imag) && f_zero_p(RCOMPLEX(a2)->imag))
+ a2 = RCOMPLEX(a2)->real;
}
backref = rb_backref_get();
@@ -1446,14 +1451,18 @@ nurat_s_convert(int argc, VALUE *argv, VALUE klass)
switch (TYPE(a1)) {
case T_RATIONAL:
- if (NIL_P(a2) || f_zero_p(a2))
+ if (argc == 1 || (k_exact_p(a2) && f_one_p(a2)))
return a1;
- return f_div(a1, a2);
}
- switch (TYPE(a2)) {
- case T_RATIONAL:
- return f_div(a1, a2);
+ if (argc == 1) {
+ if (k_numeric_p(a1) && !f_integer_p(a1))
+ return a1;
+ }
+ else {
+ if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
+ (!f_integer_p(a1) || !f_integer_p(a2)))
+ return f_div(a1, a2);
}
{
@@ -1464,12 +1473,6 @@ nurat_s_convert(int argc, VALUE *argv, VALUE klass)
}
}
-static VALUE
-nurat_s_induced_from(VALUE klass, VALUE n)
-{
- return f_to_r(n);
-}
-
void
Init_Rational(void)
{
@@ -1486,12 +1489,11 @@ Init_Rational(void)
id_expt = rb_intern("**");
id_floor = rb_intern("floor");
id_format = rb_intern("format");
+ id_hash = rb_intern("hash");
id_idiv = rb_intern("div");
id_inspect = rb_intern("inspect");
id_integer_p = rb_intern("integer?");
id_negate = rb_intern("-@");
- id_new = rb_intern("new");
- id_new_bang = rb_intern("new!");
id_to_f = rb_intern("to_f");
id_to_i = rb_intern("to_i");
id_to_s = rb_intern("to_s");
@@ -1587,8 +1589,10 @@ Init_Rational(void)
rb_define_singleton_method(rb_cRational, "convert", nurat_s_convert, -1);
rb_funcall(rb_cRational, rb_intern("private_class_method"), 1,
ID2SYM(rb_intern("convert")));
-
- rb_include_module(rb_cRational, rb_mPrecision);
- rb_define_singleton_method(rb_cRational, "induced_from",
- nurat_s_induced_from, 1);
}
+
+/*
+Local variables:
+c-file-style: "ruby"
+End:
+*/
diff --git a/re.c b/re.c
index a17874ab71..9b9cb87d02 100644
--- a/re.c
+++ b/re.c
@@ -380,8 +380,12 @@ static VALUE
rb_reg_desc(const char *s, long len, VALUE re)
{
VALUE str = rb_str_buf_new2("/");
-
- rb_enc_copy(str, re);
+ if (rb_enc_asciicompat(rb_enc_get(re))) {
+ rb_enc_copy(str, re);
+ }
+ else {
+ rb_enc_associate(str, rb_usascii_encoding());
+ }
rb_reg_expr_str(str, s, len);
rb_str_buf_cat2(str, "/");
if (re) {
@@ -1264,10 +1268,10 @@ rb_reg_adjust_startpos(VALUE re, VALUE str, int pos, int reverse)
string = (UChar*)RSTRING_PTR(str);
if (range > 0) {
- p = onigenc_get_right_adjust_char_head(enc, string, string + pos);
+ p = onigenc_get_right_adjust_char_head(enc, string, string + pos, string + RSTRING_LEN(str));
}
else {
- p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, string, string + pos);
+ p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, string, string + pos, string + RSTRING_LEN(str));
}
return p - string;
}
@@ -2860,34 +2864,34 @@ rb_reg_quote(VALUE str)
case '*': case '.': case '\\':
case '?': case '+': case '^': case '$':
case '#':
- *t++ = '\\';
+ t += rb_enc_mbcput('\\', t, enc);
break;
case ' ':
- *t++ = '\\';
- *t++ = ' ';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput(' ', t, enc);
continue;
case '\t':
- *t++ = '\\';
- *t++ = 't';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput('t', t, enc);
continue;
case '\n':
- *t++ = '\\';
- *t++ = 'n';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput('n', t, enc);
continue;
case '\r':
- *t++ = '\\';
- *t++ = 'r';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput('r', t, enc);
continue;
case '\f':
- *t++ = '\\';
- *t++ = 'f';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput('f', t, enc);
continue;
case '\v':
- *t++ = '\\';
- *t++ = 'v';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput('v', t, enc);
continue;
}
- *t++ = c;
+ t += rb_enc_mbcput(c, t, enc);
}
rb_str_resize(tmp, t - RSTRING_PTR(tmp));
OBJ_INFECT(tmp, str);
diff --git a/regenc.c b/regenc.c
index 935e8d33d1..634afd8883 100644
--- a/regenc.c
+++ b/regenc.c
@@ -62,24 +62,24 @@ onigenc_mbclen_approximate(const OnigUChar* p,const OnigUChar* e, struct OnigEnc
}
extern UChar*
-onigenc_get_right_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s)
+onigenc_get_right_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s, const UChar* end)
{
- UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s);
+ UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s, end);
if (p < s) {
- p += enclen(enc, p, s);
+ p += enclen(enc, p, end);
}
return p;
}
extern UChar*
onigenc_get_right_adjust_char_head_with_prev(OnigEncoding enc,
- const UChar* start, const UChar* s, const UChar** prev)
+ const UChar* start, const UChar* s, const UChar* end, const UChar** prev)
{
- UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s);
+ UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s, end);
if (p < s) {
if (prev) *prev = (const UChar* )p;
- p += enclen(enc, p, s);
+ p += enclen(enc, p, end);
}
else {
if (prev) *prev = (const UChar* )NULL; /* Sorry */
@@ -88,22 +88,22 @@ onigenc_get_right_adjust_char_head_with_prev(OnigEncoding enc,
}
extern UChar*
-onigenc_get_prev_char_head(OnigEncoding enc, const UChar* start, const UChar* s)
+onigenc_get_prev_char_head(OnigEncoding enc, const UChar* start, const UChar* s, const UChar* end)
{
if (s <= start)
return (UChar* )NULL;
- return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1);
+ return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1, end);
}
extern UChar*
-onigenc_step_back(OnigEncoding enc, const UChar* start, const UChar* s, int n)
+onigenc_step_back(OnigEncoding enc, const UChar* start, const UChar* s, const UChar* end, int n)
{
while (ONIG_IS_NOT_NULL(s) && n-- > 0) {
if (s <= start)
return (UChar* )NULL;
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1);
+ s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1, end);
}
return (UChar* )s;
}
@@ -369,9 +369,9 @@ onigenc_set_default_caseconv_table(const UChar* table ARG_UNUSED)
}
extern UChar*
-onigenc_get_left_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s)
+onigenc_get_left_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s, const UChar* end)
{
- return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s);
+ return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s, end);
}
const OnigPairCaseFoldCodes OnigAsciiLowerMap[] = {
@@ -637,6 +637,7 @@ onigenc_single_byte_code_to_mbc(OnigCodePoint code, UChar *buf, OnigEncoding enc
extern UChar*
onigenc_single_byte_left_adjust_char_head(const UChar* start ARG_UNUSED, const UChar* s,
+ const UChar* end,
OnigEncoding enc ARG_UNUSED)
{
return (UChar* )s;
diff --git a/regenc.h b/regenc.h
index 317175f5df..3844e4108d 100644
--- a/regenc.h
+++ b/regenc.h
@@ -125,7 +125,7 @@ ONIG_EXTERN int onigenc_single_byte_mbc_enc_len P_((const UChar* p, const UChar*
ONIG_EXTERN OnigCodePoint onigenc_single_byte_mbc_to_code P_((const UChar* p, const UChar* end, OnigEncoding enc));
ONIG_EXTERN int onigenc_single_byte_code_to_mbclen P_((OnigCodePoint code, OnigEncoding enc));
ONIG_EXTERN int onigenc_single_byte_code_to_mbc P_((OnigCodePoint code, UChar *buf, OnigEncoding enc));
-ONIG_EXTERN UChar* onigenc_single_byte_left_adjust_char_head P_((const UChar* start, const UChar* s, OnigEncoding enc));
+ONIG_EXTERN UChar* onigenc_single_byte_left_adjust_char_head P_((const UChar* start, const UChar* s, const OnigUChar* end, OnigEncoding enc));
ONIG_EXTERN int onigenc_always_true_is_allowed_reverse_match P_((const UChar* s, const UChar* end, OnigEncoding enc));
ONIG_EXTERN int onigenc_always_false_is_allowed_reverse_match P_((const UChar* s, const UChar* end, OnigEncoding enc));
ONIG_EXTERN int onigenc_ascii_is_code_ctype P_((OnigCodePoint code, unsigned int ctype, OnigEncoding enc));
diff --git a/regexec.c b/regexec.c
index b0cc6647a0..260505901d 100644
--- a/regexec.c
+++ b/regexec.c
@@ -977,25 +977,24 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
}\
} while(0)
-#define STRING_CMP_IC(case_fold_flag,s1,ps2,len) do {\
- if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len) == 0) \
+#define STRING_CMP_IC(case_fold_flag,s1,ps2,len,text_end) do {\
+ if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len, text_end) == 0) \
goto fail; \
} while(0)
static int string_cmp_ic(OnigEncoding enc, int case_fold_flag,
- UChar* s1, UChar** ps2, int mblen)
+ UChar* s1, UChar** ps2, int mblen, const UChar* text_end)
{
UChar buf1[ONIGENC_MBC_CASE_FOLD_MAXLEN];
UChar buf2[ONIGENC_MBC_CASE_FOLD_MAXLEN];
- UChar *p1, *p2, *end1, *s2, *end2;
+ UChar *p1, *p2, *end1, *s2;
int len1, len2;
s2 = *ps2;
end1 = s1 + mblen;
- end2 = s2 + mblen;
while (s1 < end1) {
- len1 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s1, end1, buf1);
- len2 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s2, end2, buf2);
+ len1 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s1, text_end, buf1);
+ len2 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s2, text_end, buf2);
if (len1 != len2) return 0;
p1 = buf1;
p2 = buf2;
@@ -1019,8 +1018,8 @@ static int string_cmp_ic(OnigEncoding enc, int case_fold_flag,
}\
} while(0)
-#define STRING_CMP_VALUE_IC(case_fold_flag,s1,ps2,len,is_fail) do {\
- if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len) == 0) \
+#define STRING_CMP_VALUE_IC(case_fold_flag,s1,ps2,len,text_end,is_fail) do {\
+ if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len, text_end) == 0) \
is_fail = 1; \
else \
is_fail = 0; \
@@ -1126,7 +1125,7 @@ static int backref_match_at_nested_level(regex_t* reg
if (ignore_case != 0) {
if (string_cmp_ic(reg->enc, case_fold_flag,
- pstart, &ss, (int )(pend - pstart)) == 0)
+ pstart, &ss, (int )(pend - pstart), send) == 0)
return 0; /* or goto next_mem; */
}
else {
@@ -2199,7 +2198,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
n = pend - pstart;
DATA_ENSURE(n);
sprev = s;
- STRING_CMP_IC(case_fold_flag, pstart, &s, n);
+ STRING_CMP_IC(case_fold_flag, pstart, &s, n, end);
while (sprev + (len = enclen(encode, sprev, end)) < s)
sprev += len;
@@ -2271,7 +2270,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
DATA_ENSURE(n);
sprev = s;
swork = s;
- STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, is_fail);
+ STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, end, is_fail);
if (is_fail) continue;
s = swork;
while (sprev + (len = enclen(encode, sprev, end)) < s)
@@ -2647,9 +2646,9 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
case OP_LOOK_BEHIND: MOP_IN(OP_LOOK_BEHIND);
GET_LENGTH_INC(tlen, p);
- s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);
+ s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, end, (int )tlen);
if (IS_NULL(s)) goto fail;
- sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);
+ sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s, end);
MOP_OUT;
continue;
break;
@@ -2657,7 +2656,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
case OP_PUSH_LOOK_BEHIND_NOT: MOP_IN(OP_PUSH_LOOK_BEHIND_NOT);
GET_RELADDR_INC(addr, p);
GET_LENGTH_INC(tlen, p);
- q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);
+ q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, end, (int )tlen);
if (IS_NULL(q)) {
/* too short case -> success. ex. /(?<!XXX)a/.match("a")
If you want to change to fail, replace following line. */
@@ -2667,7 +2666,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
else {
STACK_PUSH_LOOK_BEHIND_NOT(p + addr, s, sprev);
s = q;
- sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);
+ sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s, end);
}
MOP_OUT;
continue;
@@ -2780,7 +2779,7 @@ slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
if (target_end == t || memcmp(t, p, target_end - t) == 0)
return s;
}
- s += enclen(enc, s, end);
+ s += enclen(enc, s, text_end);
}
return (UChar* )NULL;
@@ -2843,7 +2842,7 @@ slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
if (s > text_start)
s = (UChar* )text_start;
else
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s);
+ s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s, text_end);
while (s >= text) {
if (*s == *target) {
@@ -2857,7 +2856,7 @@ slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
if (t == target_end)
return s;
}
- s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);
+ s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
}
return (UChar* )NULL;
@@ -2876,14 +2875,14 @@ slow_search_backward_ic(OnigEncoding enc, int case_fold_flag,
if (s > text_start)
s = (UChar* )text_start;
else
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s);
+ s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s, text_end);
while (s >= text) {
if (str_lower_case_match(enc, case_fold_flag,
target, target_end, s, text_end))
return s;
- s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);
+ s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
}
return (UChar* )NULL;
@@ -3018,7 +3017,7 @@ bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
if (text_start < s)
s = text_start;
else
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s);
+ s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s, text_end);
while (s >= text) {
p = s;
@@ -3030,7 +3029,7 @@ bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
return (UChar* )s;
s -= reg->int_map_backward[*s];
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s);
+ s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s, text_end);
}
return (UChar* )NULL;
@@ -3038,14 +3037,14 @@ bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
static UChar*
map_search(OnigEncoding enc, UChar map[],
- const UChar* text, const UChar* text_range)
+ const UChar* text, const UChar* text_range, const UChar* text_end)
{
const UChar *s = text;
while (s < text_range) {
if (map[*s]) return (UChar* )s;
- s += enclen(enc, s, text_range);
+ s += enclen(enc, s, text_end);
}
return (UChar* )NULL;
}
@@ -3053,14 +3052,14 @@ map_search(OnigEncoding enc, UChar map[],
static UChar*
map_search_backward(OnigEncoding enc, UChar map[],
const UChar* text, const UChar* adjust_text,
- const UChar* text_start)
+ const UChar* text_start, const UChar* text_end)
{
const UChar *s = text_start;
while (s >= text) {
if (map[*s]) return (UChar* )s;
- s = onigenc_get_prev_char_head(enc, adjust_text, s);
+ s = onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
}
return (UChar* )NULL;
}
@@ -3117,7 +3116,7 @@ onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, On
r = 0;
if (r == 0) {
- prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at);
+ prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at, end);
r = match_at(reg, str, end,
#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
end,
@@ -3171,7 +3170,7 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
break;
case ONIG_OPTIMIZE_MAP:
- p = map_search(reg->enc, reg->map, p, range);
+ p = map_search(reg->enc, reg->map, p, range, end);
break;
}
@@ -3190,7 +3189,7 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
case ANCHOR_BEGIN_LINE:
if (!ON_STR_BEGIN(p)) {
prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), p);
+ (pprev ? pprev : str), p, end);
if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end))
goto retry_gate;
}
@@ -3219,10 +3218,10 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
*low = p;
if (low_prev) {
if (*low > s)
- *low_prev = onigenc_get_prev_char_head(reg->enc, s, p);
+ *low_prev = onigenc_get_prev_char_head(reg->enc, s, p, end);
else
*low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), p);
+ (pprev ? pprev : str), p, end);
}
}
else {
@@ -3230,15 +3229,15 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
*low = p - reg->dmax;
if (*low > s) {
*low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,
- *low, (const UChar** )low_prev);
+ *low, end, (const UChar** )low_prev);
if (low_prev && IS_NULL(*low_prev))
*low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : s), *low);
+ (pprev ? pprev : s), *low, end);
}
else {
if (low_prev)
*low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), *low);
+ (pprev ? pprev : str), *low, end);
}
}
}
@@ -3301,7 +3300,7 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
break;
case ONIG_OPTIMIZE_MAP:
- p = map_search_backward(reg->enc, reg->map, range, adjrange, p);
+ p = map_search_backward(reg->enc, reg->map, range, adjrange, p, end);
break;
}
@@ -3312,7 +3311,7 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
switch (reg->sub_anchor) {
case ANCHOR_BEGIN_LINE:
if (!ON_STR_BEGIN(p)) {
- prev = onigenc_get_prev_char_head(reg->enc, str, p);
+ prev = onigenc_get_prev_char_head(reg->enc, str, p, end);
if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) {
p = prev;
goto retry;
@@ -3336,7 +3335,7 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
&& ! ONIGENC_IS_MBC_CRNL(reg->enc, p, end)
#endif
) {
- p = onigenc_get_prev_char_head(reg->enc, adjrange, p);
+ p = onigenc_get_prev_char_head(reg->enc, adjrange, p, end);
if (IS_NULL(p)) goto fail;
goto retry;
}
@@ -3348,7 +3347,7 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
if (reg->dmax != ONIG_INFINITE_DISTANCE) {
*low = p - reg->dmax;
*high = p - reg->dmin;
- *high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high);
+ *high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high, end);
}
#ifdef ONIG_DEBUG_SEARCH
@@ -3506,9 +3505,9 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
if ((OnigDistance )(min_semi_end - start) > reg->anchor_dmax) {
start = min_semi_end - reg->anchor_dmax;
if (start < end)
- start = onigenc_get_right_adjust_char_head(reg->enc, str, start);
+ start = onigenc_get_right_adjust_char_head(reg->enc, str, start, end);
else { /* match with empty at end */
- start = onigenc_get_prev_char_head(reg->enc, str, end);
+ start = onigenc_get_prev_char_head(reg->enc, str, end, end);
}
}
if ((OnigDistance )(max_semi_end - (range - 1)) < reg->anchor_dmin) {
@@ -3523,20 +3522,20 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
}
if ((OnigDistance )(max_semi_end - start) < reg->anchor_dmin) {
start = max_semi_end - reg->anchor_dmin;
- start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start);
+ start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start, end);
}
if (range > start) goto mismatch_no_msa;
}
}
else if (reg->anchor & ANCHOR_SEMI_END_BUF) {
- UChar* pre_end = ONIGENC_STEP_BACK(reg->enc, str, end, 1);
+ UChar* pre_end = ONIGENC_STEP_BACK(reg->enc, str, end, end, 1);
max_semi_end = (UChar* )end;
if (ONIGENC_IS_MBC_NEWLINE(reg->enc, pre_end, end)) {
min_semi_end = pre_end;
#ifdef USE_CRNL_AS_LINE_TERMINATOR
- pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, 1);
+ pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, end, 1);
if (IS_NOT_NULL(pre_end) &&
ONIGENC_IS_MBC_CRNL(reg->enc, pre_end, end)) {
min_semi_end = pre_end;
@@ -3594,7 +3593,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
s = (UChar* )start;
if (range > start) { /* forward search */
if (s > str)
- prev = onigenc_get_prev_char_head(reg->enc, str, s);
+ prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
else
prev = (UChar* )NULL;
@@ -3670,7 +3669,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
UChar *low, *high, *adjrange, *sch_start;
if (range < end)
- adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range);
+ adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range, end);
else
adjrange = (UChar* )end;
@@ -3687,7 +3686,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
s = high;
while (s >= low) {
- prev = onigenc_get_prev_char_head(reg->enc, str, s);
+ prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
MATCH_AND_RETURN_CHECK(orig_start);
s = prev;
}
@@ -3706,7 +3705,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
if (sch_start > end) sch_start = (UChar* )end;
else
sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,
- start, sch_start);
+ start, sch_start, end);
}
}
if (backward_search_range(reg, str, end, sch_start, range, adjrange,
@@ -3715,7 +3714,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
}
do {
- prev = onigenc_get_prev_char_head(reg->enc, str, s);
+ prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
MATCH_AND_RETURN_CHECK(orig_start);
s = prev;
} while (s >= range);
diff --git a/regparse.c b/regparse.c
index 168b175758..0bd898b771 100644
--- a/regparse.c
+++ b/regparse.c
@@ -1540,7 +1540,7 @@ str_node_split_last_char(StrNode* sn, OnigEncoding enc)
Node* n = NULL_NODE;
if (sn->end > sn->s) {
- p = onigenc_get_prev_char_head(enc, sn->s, sn->end);
+ p = onigenc_get_prev_char_head(enc, sn->s, sn->end, sn->end);
if (p && p > sn->s) { /* can be splitted. */
n = node_new_str(p, sn->end);
if ((sn->flag & NSTR_RAW) != 0)
diff --git a/ruby.c b/ruby.c
index 5a51bbb52a..c773fafc15 100644
--- a/ruby.c
+++ b/ruby.c
@@ -967,6 +967,7 @@ process_options(VALUE arg)
NODE *tree = 0;
VALUE parser;
VALUE iseq;
+ VALUE args;
rb_encoding *enc, *lenc;
const char *s;
char fbuf[MAXPATHLEN];
@@ -1067,7 +1068,7 @@ process_options(VALUE arg)
#if defined DOSISH || defined __CYGWIN__
translate_char(RSTRING_PTR(rb_progname), '\\', '/');
#endif
- opt->script_name = rb_str_new4(rb_progname);
+ opt->script_name = rb_progname;
opt->script = RSTRING_PTR(opt->script_name);
safe = rb_safe_level();
rb_set_safe_level_force(0);
@@ -1077,8 +1078,10 @@ process_options(VALUE arg)
ruby_init_loadpath();
ruby_init_gems(!(opt->disable & DISABLE_BIT(gems)));
lenc = rb_locale_encoding();
- for (i = 0; i < RARRAY_LEN(rb_argv); i++) {
- rb_enc_associate(RARRAY_PTR(rb_argv)[i], lenc);
+ rb_enc_associate(rb_progname, lenc);
+ opt->script_name = rb_str_new4(rb_progname);
+ for (i = 0, args = rb_argv; i < RARRAY_LEN(args); i++) {
+ rb_enc_associate(RARRAY_PTR(args)[i], lenc);
}
parser = rb_parser_new();
if (opt->yydebug) rb_parser_set_yydebug(parser, Qtrue);
@@ -1475,7 +1478,6 @@ ruby_prog_init(void)
rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
rb_define_global_const("ARGV", rb_argv);
- rb_global_variable(&rb_argv0);
#ifdef MSDOS
/*
@@ -1532,6 +1534,7 @@ ruby_process_options(int argc, char **argv)
ruby_script(argv[0]); /* for the time being */
rb_argv0 = rb_str_new4(rb_progname);
+ rb_gc_register_mark_object(rb_argv0);
args.argc = argc;
args.argv = argv;
args.opt = cmdline_options_init(&opt);
diff --git a/st.c b/st.c
index a51d7cf8c8..54e10721b0 100644
--- a/st.c
+++ b/st.c
@@ -6,9 +6,7 @@
#include "regint.h"
#include "st.h"
#else
-#include "ruby/config.h"
-#include "ruby/defines.h"
-#include "ruby/st.h"
+#include "ruby/ruby.h"
#endif
#include <stdio.h>
@@ -135,6 +133,9 @@ new_size(int size)
if (newsize > size) return primes[i];
}
/* Ran out of polynomials */
+#ifndef NOT_RUBY
+ rb_raise(rb_eRuntimeError, "st_table too big");
+#endif
return -1; /* should raise exception */
#endif
}
diff --git a/string.c b/string.c
index 24d33ef508..a56dbf66a3 100644
--- a/string.c
+++ b/string.c
@@ -43,6 +43,7 @@
VALUE rb_cString;
VALUE rb_cSymbol;
+#define RUBY_MAX_CHAR_LEN 16
#define STR_TMPLOCK FL_USER7
#define STR_NOEMBED FL_USER1
#define STR_SHARED FL_USER2 /* = ELTS_SHARED */
@@ -111,18 +112,19 @@ VALUE rb_cSymbol;
#define STR_ENC_GET(str) rb_enc_from_index(ENCODING_GET(str))
-static int
+static inline int
single_byte_optimizable(VALUE str)
{
- rb_encoding *enc = STR_ENC_GET(str);
-
- if (rb_enc_mbmaxlen(enc) == 1)
- return 1;
+ rb_encoding *enc;
/* Conservative. It may be ENC_CODERANGE_UNKNOWN. */
if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT)
return 1;
+ enc = STR_ENC_GET(str);
+ if (rb_enc_mbmaxlen(enc) == 1)
+ return 1;
+
/* Conservative. Possibly single byte.
* "\xa1" in Shift_JIS for example. */
return 0;
@@ -1057,6 +1059,17 @@ rb_str_modify(VALUE str)
ENC_CODERANGE_CLEAR(str);
}
+/* As rb_str_modify(), but don't clear coderange */
+static void
+str_modify_keep_cr(VALUE str)
+{
+ if (!str_independent(str))
+ str_make_independent(str);
+ if (ENC_CODERANGE(str) == ENC_CODERANGE_BROKEN)
+ /* Force re-scan later */
+ ENC_CODERANGE_CLEAR(str);
+}
+
void
rb_str_associate(VALUE str, VALUE add)
{
@@ -1281,20 +1294,35 @@ rb_str_substr(VALUE str, long beg, long len)
rb_encoding *enc = STR_ENC_GET(str);
VALUE str2;
char *p, *s = RSTRING_PTR(str), *e = s + RSTRING_LEN(str);
- int singlebyte;
if (len < 0) return Qnil;
if (!RSTRING_LEN(str)) {
len = 0;
}
+ if (single_byte_optimizable(str)) {
+ if (beg > RSTRING_LEN(str)) return Qnil;
+ if (beg < 0) {
+ beg += RSTRING_LEN(str);
+ if (beg < 0) return Qnil;
+ }
+ if (beg + len > RSTRING_LEN(str))
+ len = RSTRING_LEN(str) - beg;
+ if (len <= 0) {
+ len = 0;
+ p = 0;
+ }
+ else
+ p = s + beg;
+ goto sub;
+ }
if (beg < 0) {
if (len > -beg) len = -beg;
if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_LEN(str) / 8) {
beg = -beg;
- while (beg-- > len && (e = rb_enc_prev_char(s, e, enc)) != 0);
+ while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0);
p = e;
if (!p) return Qnil;
- while (len-- > 0 && (p = rb_enc_prev_char(s, p, enc)) != 0);
+ while (len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0);
if (!p) return Qnil;
len = e - p;
goto sub;
@@ -1307,7 +1335,6 @@ rb_str_substr(VALUE str, long beg, long len)
else if (beg > 0 && beg > str_strlen(str, enc)) {
return Qnil;
}
- singlebyte = single_byte_optimizable(str);
if (len == 0) {
p = 0;
}
@@ -1318,17 +1345,24 @@ rb_str_substr(VALUE str, long beg, long len)
len = str_utf8_offset(p, e, len);
}
#endif
- else if ((p = str_nth(s, e, beg, enc, singlebyte)) == e) {
- len = 0;
- }
else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
- if (len * rb_enc_mbmaxlen(enc) > e - p)
+ int char_sz = rb_enc_mbmaxlen(enc);
+
+ p = s + beg * char_sz;
+ if (p > e) {
+ p = e;
+ len = 0;
+ }
+ else if (len * char_sz > e - p)
len = e - p;
else
- len *= rb_enc_mbmaxlen(enc);
+ len *= char_sz;
+ }
+ else if ((p = str_nth(s, e, beg, enc, 0)) == e) {
+ len = 0;
}
else {
- len = str_offset(p, e, len, enc, singlebyte);
+ len = str_offset(p, e, len, enc, 0);
}
sub:
if (len > RSTRING_EMBED_LEN_MAX && beg + len == RSTRING_LEN(str)) {
@@ -1623,7 +1657,7 @@ rb_str_buf_cat_ascii(VALUE str, const char *ptr)
else {
char *buf = ALLOCA_N(char, rb_enc_mbmaxlen(enc));
while (*ptr) {
- int c = (unsigned char)*ptr;
+ unsigned int c = (unsigned char)*ptr;
int len = rb_enc_codelen(c, enc);
rb_enc_mbcput(c, buf, enc);
rb_enc_cr_str_buf_cat(str, buf, len,
@@ -1678,13 +1712,13 @@ rb_str_append(VALUE str, VALUE str2)
/*
* call-seq:
- * str << fixnum => str
- * str.concat(fixnum) => str
+ * str << integer => str
+ * str.concat(integer) => str
* str << obj => str
* str.concat(obj) => str
*
* Append---Concatenates the given object to <i>str</i>. If the object is a
- * <code>Fixnum</code>, it is considered as a codepoint, and is converted
+ * <code>Integer</code>, it is considered as a codepoint, and is converted
* to a character before concatenation.
*
* a = "hello "
@@ -1695,9 +1729,9 @@ rb_str_append(VALUE str, VALUE str2)
VALUE
rb_str_concat(VALUE str1, VALUE str2)
{
- if (FIXNUM_P(str2)) {
+ if (FIXNUM_P(str2) || TYPE(str2) == T_BIGNUM) {
rb_encoding *enc = STR_ENC_GET(str1);
- int c = FIX2INT(str2);
+ unsigned int c = NUM2UINT(str2);
int pos = RSTRING_LEN(str1);
int len = rb_enc_codelen(c, enc);
int cr = ENC_CODERANGE(str1);
@@ -1892,6 +1926,7 @@ rb_str_comparable(VALUE str1, VALUE str2)
{
int idx1, idx2;
int rc1, rc2;
+ int a8;
if (RSTRING_LEN(str1) == 0) return Qtrue;
if (RSTRING_LEN(str2) == 0) return Qtrue;
@@ -1909,6 +1944,8 @@ rb_str_comparable(VALUE str1, VALUE str2)
if (rb_enc_asciicompat(rb_enc_from_index(idx1)))
return Qtrue;
}
+ a8 = rb_ascii8bit_encindex();
+ if (idx1 == a8 || idx2 == a8) return Qtrue;
return Qfalse;
}
@@ -1922,7 +1959,7 @@ rb_str_cmp(VALUE str1, VALUE str2)
retval = memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len);
if (retval == 0) {
if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) {
- if (!rb_enc_compatible(str1, str2)) {
+ if (!rb_str_comparable(str1, str2)) {
if (ENCODING_GET(str1) - ENCODING_GET(str2) > 0)
return 1;
return -1;
@@ -2065,19 +2102,33 @@ rb_str_casecmp(VALUE str1, VALUE str2)
p1 = RSTRING_PTR(str1); p1end = RSTRING_END(str1);
p2 = RSTRING_PTR(str2); p2end = RSTRING_END(str2);
- while (p1 < p1end && p2 < p2end) {
- unsigned int c1 = rb_enc_codepoint(p1, p1end, enc);
- unsigned int c2 = rb_enc_codepoint(p2, p2end, enc);
-
- if (c1 != c2) {
- c1 = rb_enc_toupper(c1, enc);
- c2 = rb_enc_toupper(c2, enc);
- if (c1 > c2) return INT2FIX(1);
- if (c1 < c2) return INT2FIX(-1);
+ if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
+ while (p1 < p1end && p2 < p2end) {
+ if (*p1 != *p2) {
+ unsigned int c1 = rb_enc_toupper(*p1 & 0xff, enc);
+ unsigned int c2 = rb_enc_toupper(*p2 & 0xff, enc);
+ if (c1 > c2) return INT2FIX(1);
+ if (c1 < c2) return INT2FIX(-1);
+ }
+ p1++;
+ p2++;
+ }
+ }
+ else {
+ while (p1 < p1end && p2 < p2end) {
+ unsigned int c1 = rb_enc_codepoint(p1, p1end, enc);
+ unsigned int c2 = rb_enc_codepoint(p2, p2end, enc);
+
+ if (c1 != c2) {
+ c1 = rb_enc_toupper(c1, enc);
+ c2 = rb_enc_toupper(c2, enc);
+ if (c1 > c2) return INT2FIX(1);
+ if (c1 < c2) return INT2FIX(-1);
+ }
+ len = rb_enc_codelen(c1, enc);
+ p1 += len;
+ p2 += len;
}
- len = rb_enc_codelen(c1, enc);
- p1 += len;
- p2 += len;
}
if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) return INT2FIX(0);
if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return INT2FIX(1);
@@ -2088,7 +2139,7 @@ static long
rb_str_index(VALUE str, VALUE sub, long offset)
{
long pos;
- char *s, *sptr;
+ char *s, *sptr, *e;
long len, slen;
rb_encoding *enc;
@@ -2104,6 +2155,7 @@ rb_str_index(VALUE str, VALUE sub, long offset)
}
if (len - offset < slen) return -1;
s = RSTRING_PTR(str);
+ e = s + RSTRING_LEN(str);
if (offset) {
offset = str_offset(s, RSTRING_END(str), offset, enc, single_byte_optimizable(str));
s += offset;
@@ -2117,7 +2169,7 @@ rb_str_index(VALUE str, VALUE sub, long offset)
char *t;
pos = rb_memsearch(sptr, slen, s, len, enc);
if (pos < 0) return pos;
- t = rb_enc_right_char_head(s, s+pos, enc);
+ t = rb_enc_right_char_head(s, s+pos, e, enc);
if (t == s + pos) break;
if ((len -= t - s) <= 0) return -1;
offset += t - s;
@@ -2571,7 +2623,7 @@ rb_str_succ(VALUE orig)
sbeg = RSTRING_PTR(str);
s = e = sbeg + RSTRING_LEN(str);
- while ((s = rb_enc_prev_char(sbeg, s, enc)) != 0) {
+ while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
if (ISALPHA(*last_alnum) ? ISDIGIT(*s) :
ISDIGIT(*last_alnum) ? ISALPHA(*s) : 0) {
@@ -2596,7 +2648,7 @@ rb_str_succ(VALUE orig)
}
if (c == -1) { /* str contains no alnum */
s = e;
- while ((s = rb_enc_prev_char(sbeg, s, enc)) != 0) {
+ while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
enum neighbor_char neighbor;
if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
neighbor = enc_succ_char(s, l, enc);
@@ -2894,11 +2946,11 @@ rb_str_splice(VALUE str, long beg, long len, VALUE val)
char *p, *e;
rb_encoding *enc;
int singlebyte = single_byte_optimizable(str);
+ int cr;
if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
StringValue(val);
- rb_str_modify(str);
enc = rb_enc_check(str, val);
slen = str_strlen(str, enc);
@@ -2915,6 +2967,7 @@ rb_str_splice(VALUE str, long beg, long len, VALUE val)
if (slen < len || slen < beg + len) {
len = slen - beg;
}
+ str_modify_keep_cr(str);
p = str_nth(RSTRING_PTR(str), RSTRING_END(str), beg, enc, singlebyte);
if (!p) p = RSTRING_END(str);
e = str_nth(p, RSTRING_END(str), len, enc, singlebyte);
@@ -2924,6 +2977,9 @@ rb_str_splice(VALUE str, long beg, long len, VALUE val)
len = e - p; /* physical length */
rb_str_splice_0(str, beg, len, val);
rb_enc_associate(str, enc);
+ cr = ENC_CODERANGE_AND(ENC_CODERANGE(str), ENC_CODERANGE(val));
+ if (cr != ENC_CODERANGE_BROKEN)
+ ENC_CODERANGE_SET(str, cr);
}
void
@@ -3114,7 +3170,7 @@ rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
for (i=0; i<argc; i++) {
buf[i] = argv[i];
}
- rb_str_modify(str);
+ str_modify_keep_cr(str);
buf[i] = rb_str_new(0,0);
result = rb_str_aref_m(argc, buf, str);
if (!NIL_P(result)) {
@@ -3524,7 +3580,10 @@ rb_str_clear(VALUE str)
STR_SET_EMBED(str);
STR_SET_EMBED_LEN(str, 0);
RSTRING_PTR(str)[0] = 0;
- ENC_CODERANGE_CLEAR(str);
+ if (rb_enc_asciicompat(STR_ENC_GET(str)))
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
+ else
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
return str;
}
@@ -3656,22 +3715,15 @@ rb_str_reverse_bang(VALUE str)
if (RSTRING_LEN(str) > 1) {
if (single_byte_optimizable(str)) {
char *s, *e, c;
- int cr = ENC_CODERANGE(str);
- int single = 1;
- rb_str_modify(str);
+ str_modify_keep_cr(str);
s = RSTRING_PTR(str);
e = RSTRING_END(str) - 1;
while (s < e) {
c = *s;
- if (*s & 0x80) single = 0;
*s++ = *e;
*e-- = c;
}
- if (cr == ENC_CODERANGE_UNKNOWN && single) {
- cr = ENC_CODERANGE_7BIT;
- }
- ENC_CODERANGE_SET(str, cr);
}
else {
rb_str_shared_replace(str, rb_str_reverse(str));
@@ -3787,9 +3839,9 @@ rb_str_to_s(VALUE str)
}
static void
-str_cat_char(VALUE str, int c, rb_encoding *enc)
+str_cat_char(VALUE str, unsigned int c, rb_encoding *enc)
{
- char s[16];
+ char s[RUBY_MAX_CHAR_LEN];
int n = rb_enc_codelen(c, enc);
rb_enc_mbcput(c, s, enc);
@@ -3797,7 +3849,7 @@ str_cat_char(VALUE str, int c, rb_encoding *enc)
}
static void
-prefix_escape(VALUE str, int c, rb_encoding *enc)
+prefix_escape(VALUE str, unsigned int c, rb_encoding *enc)
{
str_cat_char(str, '\\', enc);
str_cat_char(str, c, enc);
@@ -4033,23 +4085,46 @@ rb_str_upcase_bang(VALUE str)
rb_encoding *enc;
char *s, *send;
int modify = 0;
- int cr = ENC_CODERANGE(str);
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
s = RSTRING_PTR(str); send = RSTRING_END(str);
- while (s < send) {
- unsigned int c = rb_enc_codepoint(s, send, enc);
+ if (single_byte_optimizable(str)) {
+ while (s < send) {
+ unsigned int c = *(unsigned char*)s;
- if (rb_enc_islower(c, enc)) {
- /* assuming toupper returns codepoint with same size */
- rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
- modify = 1;
+ if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') {
+ *s = 'A' + (c - 'a');
+ modify = 1;
+ }
+ s++;
+ }
+ }
+ else {
+ int ascompat = rb_enc_asciicompat(enc);
+
+ while (s < send) {
+ unsigned int c;
+
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') {
+ *s = 'A' + (c - 'a');
+ modify = 1;
+ }
+ s++;
+ }
+ else {
+ c = rb_enc_codepoint(s, send, enc);
+ if (rb_enc_islower(c, enc)) {
+ /* assuming toupper returns codepoint with same size */
+ rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
+ modify = 1;
+ }
+ s += rb_enc_codelen(c, enc);
+ }
}
- s += rb_enc_codelen(c, enc);
}
- ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
}
@@ -4091,23 +4166,46 @@ rb_str_downcase_bang(VALUE str)
rb_encoding *enc;
char *s, *send;
int modify = 0;
- int cr = ENC_CODERANGE(str);
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
s = RSTRING_PTR(str); send = RSTRING_END(str);
- while (s < send) {
- unsigned int c = rb_enc_codepoint(s, send, enc);
+ if (single_byte_optimizable(str)) {
+ while (s < send) {
+ unsigned int c = *(unsigned char*)s;
- if (rb_enc_isupper(c, enc)) {
- /* assuming toupper returns codepoint with same size */
- rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
- modify = 1;
+ if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') {
+ *s = 'a' + (c - 'A');
+ modify = 1;
+ }
+ s++;
+ }
+ }
+ else {
+ int ascompat = rb_enc_asciicompat(enc);
+
+ while (s < send) {
+ unsigned int c;
+
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') {
+ *s = 'a' + (c - 'A');
+ modify = 1;
+ }
+ s++;
+ }
+ else {
+ c = rb_enc_codepoint(s, send, enc);
+ if (rb_enc_isupper(c, enc)) {
+ /* assuming toupper returns codepoint with same size */
+ rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
+ modify = 1;
+ }
+ s += rb_enc_codelen(c, enc);
+ }
}
- s += rb_enc_codelen(c, enc);
}
- ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
}
@@ -4155,9 +4253,8 @@ rb_str_capitalize_bang(VALUE str)
char *s, *send;
int modify = 0;
unsigned int c;
- int cr = ENC_CODERANGE(str);
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
s = RSTRING_PTR(str); send = RSTRING_END(str);
@@ -4177,7 +4274,6 @@ rb_str_capitalize_bang(VALUE str)
s += rb_enc_codelen(c, enc);
}
- ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
}
@@ -4220,9 +4316,8 @@ rb_str_swapcase_bang(VALUE str)
rb_encoding *enc;
char *s, *send;
int modify = 0;
- int cr = ENC_CODERANGE(str);
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
s = RSTRING_PTR(str); send = RSTRING_END(str);
while (s < send) {
@@ -4234,14 +4329,13 @@ rb_str_swapcase_bang(VALUE str)
modify = 1;
}
else if (rb_enc_islower(c, enc)) {
- /* assuming toupper returns codepoint with same size */
+ /* assuming tolower returns codepoint with same size */
rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
modify = 1;
}
- s += rb_enc_codelen(c, enc);
+ s += rb_enc_mbclen(s, send, enc);
}
- ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
}
@@ -4323,6 +4417,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
char *s, *send;
VALUE hash = 0;
int singlebyte = single_byte_optimizable(str);
+ int cr;
StringValue(src);
StringValue(repl);
@@ -4331,6 +4426,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
return rb_str_delete_bang(1, &src, str);
}
+ cr = ENC_CODERANGE(str);
e1 = rb_enc_check(str, src);
e2 = rb_enc_check(str, repl);
if (e1 == e2) {
@@ -4394,7 +4490,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
}
}
- rb_str_modify(str);
+ str_modify_keep_cr(str);
s = RSTRING_PTR(str); send = RSTRING_END(str);
if (sflag) {
int clen, tlen, max = RSTRING_LEN(str);
@@ -4516,6 +4612,9 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
}
if (modify) {
+ cr = ENC_CODERANGE_AND(cr, ENC_CODERANGE(repl));
+ if (cr != ENC_CODERANGE_BROKEN)
+ ENC_CODERANGE_SET(str, cr);
rb_enc_associate(str, enc);
return str;
}
@@ -4654,11 +4753,9 @@ rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
char *s, *send, *t;
VALUE del = 0, nodel = 0;
int modify = 0;
- int i;
- int cr;
+ int i, ascompat;
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
- cr = ENC_CODERANGE(str);
if (argc < 1) {
rb_raise(rb_eArgError, "wrong number of arguments");
}
@@ -4670,27 +4767,41 @@ rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
}
- rb_str_modify(str);
+ str_modify_keep_cr(str);
+ ascompat = rb_enc_asciicompat(enc);
s = t = RSTRING_PTR(str);
- if (!s || RSTRING_LEN(str) == 0) return Qnil;
send = RSTRING_END(str);
while (s < send) {
- unsigned int c = rb_enc_codepoint(s, send, enc);
- int clen = rb_enc_codelen(c, enc);
+ unsigned int c;
+ int clen;
- if (tr_find(c, squeez, del, nodel)) {
- modify = 1;
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ if (squeez[c]) {
+ modify = 1;
+ }
+ else {
+ if (t != s) *t = c;
+ t++;
+ }
+ s++;
}
else {
- if (t != s) rb_enc_mbcput(c, t, enc);
- t += clen;
+ c = rb_enc_codepoint(s, send, enc);
+ clen = rb_enc_codelen(c, enc);
+
+ if (tr_find(c, squeez, del, nodel)) {
+ modify = 1;
+ }
+ else {
+ if (t != s) rb_enc_mbcput(c, t, enc);
+ t += clen;
+ }
+ s += clen;
}
- s += clen;
}
*t = '\0';
STR_SET_LEN(str, t - RSTRING_PTR(str));
- ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
}
@@ -4736,6 +4847,7 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
char *s, *send, *t;
int save, modify = 0;
int i;
+ int ascompat, singlebyte = single_byte_optimizable(str);
if (argc == 0) {
enc = STR_ENC_GET(str);
@@ -4746,26 +4858,51 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
StringValue(s);
enc = rb_enc_check(str, s);
+ if (singlebyte && !single_byte_optimizable(s))
+ singlebyte = 0;
tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
}
}
- rb_str_modify(str);
+ str_modify_keep_cr(str);
s = t = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return Qnil;
send = RSTRING_END(str);
save = -1;
- while (s < send) {
- unsigned int c = rb_enc_codepoint(s, send, enc);
- int clen = rb_enc_codelen(c, enc);
+ ascompat = rb_enc_asciicompat(enc);
- if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
- if (t != s) rb_enc_mbcput(c, t, enc);
- save = c;
- t += clen;
+ if (singlebyte) {
+ while (s < send) {
+ unsigned int c = *(unsigned char*)s++;
+ if (c != save || (argc > 0 && !squeez[c])) {
+ *t++ = save = c;
+ }
+ }
+ } else {
+ while (s < send) {
+ unsigned int c;
+ int clen;
+
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ if (c != save || (argc > 0 && !squeez[c])) {
+ *t++ = save = c;
+ }
+ s++;
+ }
+ else {
+ c = rb_enc_codepoint(s, send, enc);
+ clen = rb_enc_codelen(c, enc);
+
+ if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
+ if (t != s) rb_enc_mbcput(c, t, enc);
+ save = c;
+ t += clen;
+ }
+ s += clen;
+ }
}
- s += clen;
}
+
*t = '\0';
if (t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
STR_SET_LEN(str, t - RSTRING_PTR(str));
@@ -4777,7 +4914,7 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
}
-/*
+/*
* call-seq:
* str.squeeze([other_str]*) => new_str
*
@@ -4862,6 +4999,7 @@ rb_str_count(int argc, VALUE *argv, VALUE str)
VALUE del = 0, nodel = 0;
char *s, *send;
int i;
+ int ascompat;
if (argc < 1) {
rb_raise(rb_eArgError, "wrong number of arguments");
@@ -4871,22 +5009,36 @@ rb_str_count(int argc, VALUE *argv, VALUE str)
StringValue(s);
enc = rb_enc_check(str, s);
- tr_setup_table(s, table,i==0, &del, &nodel, enc);
+ tr_setup_table(s, table, i==0, &del, &nodel, enc);
}
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
send = RSTRING_END(str);
i = 0;
+ ascompat = rb_enc_asciicompat(enc);
+
while (s < send) {
- unsigned int c = rb_enc_codepoint(s, send, enc);
- int clen = rb_enc_codelen(c, enc);
+ unsigned int c;
+ int clen;
- if (tr_find(c, table, del, nodel)) {
- i++;
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ clen = 1;
+ if (table[c]) {
+ i++;
+ }
+ s++;
+ }
+ else {
+ c = rb_enc_codepoint(s, send, enc);
+ clen = rb_enc_codelen(c, enc);
+ if (tr_find(c, table, del, nodel)) {
+ i++;
+ }
+ s += clen;
}
- s += clen;
}
+
return INT2NUM(i);
}
@@ -4939,7 +5091,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
rb_encoding *enc;
VALUE spat;
VALUE limit;
- int awk_split = Qfalse;
+ enum {awk, string, regexp} split_type;
long beg, end, i = 0;
int lim = 0;
VALUE result, tmp;
@@ -4961,37 +5113,41 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
spat = rb_fs;
goto fs_set;
}
- awk_split = Qtrue;
+ split_type = awk;
}
else {
fs_set:
if (TYPE(spat) == T_STRING) {
rb_encoding *enc2 = STR_ENC_GET(spat);
- if (rb_enc_mbminlen(enc2) == 1) {
+ split_type = string;
+ if (RSTRING_LEN(spat) == 0) {
+ /* Special case - split into chars */
+ spat = rb_reg_regcomp(spat);
+ split_type = regexp;
+ }
+ else if (rb_enc_mbminlen(enc2) == 1) {
if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){
- awk_split = Qtrue;
+ split_type = awk;
}
}
else {
int l;
if (rb_enc_ascget(RSTRING_PTR(spat), RSTRING_END(spat), &l, enc2) == ' ' &&
RSTRING_LEN(spat) == l) {
- awk_split = Qtrue;
+ split_type = awk;
}
}
- if (!awk_split) {
- spat = rb_reg_regcomp(rb_reg_quote(spat));
- }
}
else {
spat = get_pat(spat, 1);
+ split_type = regexp;
}
}
result = rb_ary_new();
beg = 0;
- if (awk_split) {
+ if (split_type == awk) {
char *ptr = RSTRING_PTR(str);
char *eptr = RSTRING_END(str);
char *bptr = ptr;
@@ -5025,6 +5181,33 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
}
}
}
+ else if (split_type == string) {
+ char *ptr = RSTRING_PTR(str);
+ char *eptr = RSTRING_END(str);
+ char *sptr = RSTRING_PTR(spat);
+ int slen = RSTRING_LEN(spat);
+
+ if (is_broken_string(str)) {
+ rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(str)));
+ }
+ if (is_broken_string(spat)) {
+ rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(spat)));
+ }
+ enc = rb_enc_check(str, spat);
+ while (ptr < eptr &&
+ (end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
+ /* Check we are at the start of a char */
+ char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc);
+ if (t != ptr + end) {
+ ptr = t;
+ continue;
+ }
+ rb_ary_push(result, rb_str_substr(str, ptr - RSTRING_PTR(str), end));
+ ptr += end + slen;
+ if (!NIL_P(limit) && lim <= ++i) break;
+ }
+ beg = ptr - RSTRING_PTR(str);
+ }
else {
long start = beg;
long idx;
@@ -5178,7 +5361,7 @@ rb_str_each_line(int argc, VALUE *argv, VALUE str)
p = memchr(p, '\n', pend - p);
if (!p) break;
- p0 = rb_enc_left_char_head(s, p, enc);
+ p0 = rb_enc_left_char_head(s, p, pend, enc);
if (!rb_enc_is_newline(p0, pend, enc)) {
p++;
continue;
@@ -5326,6 +5509,59 @@ rb_str_each_char(VALUE str)
return str;
}
+/*
+ * Document-method: codepoints
+ * call-seq:
+ * str.codepoints => anEnumerator
+ * str.codepoints {|fixnum| block } => str
+ *
+ * Returns an enumerator that gives the <code>Integer</code> ordinal
+ * of each character in the string, also known as a <i>codepoint</i>
+ * when applied to Unicode strings. If a block is given, it iterates
+ * over each character in the string.
+ *
+ * "foo\u0635".chars.to_a #=> [102, 111, 111, 1589]
+ */
+
+/*
+ * Document-method: each_codepoint
+ * call-seq:
+ * str.each_codepoint {|integer| block } => str
+ *
+ * Passes the <code>Integer</code> ordinal of each character in <i>str</i>,
+ * also known as a <i>codepoint</i> when applied to Unicode strings to the
+ * given block.
+ *
+ * "hello\u0639".each_codepoint {|c| print c, ' ' }
+ *
+ * <em>produces:</em>
+ *
+ * 104 101 108 108 111 1593
+ */
+
+static VALUE
+rb_str_each_codepoint(VALUE str)
+{
+ int len, n;
+ unsigned int c;
+ const char *ptr, *end;
+ rb_encoding *enc;
+
+ if (single_byte_optimizable(str)) return rb_str_each_byte(str);
+ RETURN_ENUMERATOR(str, 0, 0);
+ ptr = RSTRING_PTR(str);
+ len = RSTRING_LEN(str);
+ end = RSTRING_END(str);
+ enc = STR_ENC_GET(str);
+ while (ptr < end) {
+ c = rb_enc_codepoint(ptr, end, enc);
+ n = rb_enc_codelen(c, enc);
+ rb_yield(UINT2NUM(c));
+ ptr += n;
+ }
+ return str;
+}
+
static long
chopped_length(VALUE str)
{
@@ -5335,10 +5571,10 @@ chopped_length(VALUE str)
beg = RSTRING_PTR(str);
end = beg + RSTRING_LEN(str);
if (beg > end) return 0;
- p = rb_enc_prev_char(beg, end, enc);
+ p = rb_enc_prev_char(beg, end, end, enc);
if (!p) return 0;
if (p > beg && rb_enc_codepoint(p, end, enc) == '\n') {
- p2 = rb_enc_prev_char(beg, p, enc);
+ p2 = rb_enc_prev_char(beg, p, end, enc);
if (p2 && rb_enc_codepoint(p2, end, enc) == '\r') p = p2;
}
return p - beg;
@@ -5358,7 +5594,7 @@ rb_str_chop_bang(VALUE str)
{
if (RSTRING_LEN(str) > 0) {
long len;
- rb_str_modify(str);
+ str_modify_keep_cr(str);
len = chopped_length(str);
STR_SET_LEN(str, len);
RSTRING_PTR(str)[len] = '\0';
@@ -5420,16 +5656,16 @@ rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
rs = rb_rs;
if (rs == rb_default_rs) {
smart_chomp:
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = rb_enc_get(str);
if (rb_enc_mbminlen(enc) > 1) {
- pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), enc);
+ pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
if (rb_enc_is_newline(pp, e, enc)) {
e = pp;
}
pp = e - rb_enc_mbminlen(enc);
if (pp >= p) {
- pp = rb_enc_left_char_head(p, pp, enc);
+ pp = rb_enc_left_char_head(p, pp, e, enc);
if (rb_enc_ascget(pp, e, 0, enc) == '\r') {
e = pp;
}
@@ -5472,7 +5708,7 @@ rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
len--;
}
if (len < RSTRING_LEN(str)) {
- rb_str_modify(str);
+ str_modify_keep_cr(str);
STR_SET_LEN(str, len);
RSTRING_PTR(str)[len] = '\0';
return str;
@@ -5492,9 +5728,9 @@ rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
if (p[len-1] == newline &&
(rslen <= 1 ||
memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) {
- if (rb_enc_left_char_head(p, pp, enc) != pp)
+ if (rb_enc_left_char_head(p, pp, e, enc) != pp)
return Qnil;
- rb_str_modify(str);
+ str_modify_keep_cr(str);
STR_SET_LEN(str, RSTRING_LEN(str) - rslen);
RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
return str;
@@ -5548,7 +5784,7 @@ rb_str_lstrip_bang(VALUE str)
rb_encoding *enc;
char *s, *t, *e;
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return Qnil;
@@ -5562,7 +5798,6 @@ rb_str_lstrip_bang(VALUE str)
}
if (s > RSTRING_PTR(str)) {
- rb_str_modify(str);
STR_SET_LEN(str, t-s);
memmove(RSTRING_PTR(str), s, RSTRING_LEN(str));
RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
@@ -5609,30 +5844,33 @@ rb_str_rstrip_bang(VALUE str)
{
rb_encoding *enc;
char *s, *t, *e;
- int space_seen = Qfalse;
- rb_str_modify(str);
enc = STR_ENC_GET(str);
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return Qnil;
t = e = RSTRING_END(str);
- while (s < e) {
- unsigned int cc = rb_enc_codepoint(s, e, enc);
- if (!cc || rb_enc_isspace(cc, enc)) {
- if (!space_seen) t = s;
- space_seen = Qtrue;
- }
- else {
- space_seen = Qfalse;
+ if (single_byte_optimizable(str)) {
+ /* remove trailing '\0's */
+ while (s < t && t[-1] == '\0') t--;
+
+ /* remove trailing spaces */
+ while (s < t && rb_enc_isspace(*(t-1), enc)) t--;
+ }
+ else {
+ char *tp;
+
+ while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
+ if (!rb_enc_isspace(rb_enc_codepoint(tp, e, enc), enc)) break;
+ t = tp;
}
- s += rb_enc_codelen(cc, enc);
}
- if (!space_seen) t = s;
if (t < e) {
- rb_str_modify(str);
- STR_SET_LEN(str, t-RSTRING_PTR(str));
- RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
+ int len = t-RSTRING_PTR(str);
+
+ str_modify_keep_cr(str);
+ STR_SET_LEN(str, len);
+ RSTRING_PTR(str)[len] = '\0';
return str;
}
return Qnil;
@@ -5864,30 +6102,27 @@ rb_str_crypt(VALUE str, VALUE salt)
{
extern char *crypt(const char *, const char *);
VALUE result;
- const char *s;
+ const char *s, *saltp;
#ifdef BROKEN_CRYPT
- VALUE salt_8bit_clean;
- rb_encoding *enc;
+ char salt_8bit_clean[3];
#endif
StringValue(salt);
if (RSTRING_LEN(salt) < 2)
rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
- if (RSTRING_PTR(str)) s = RSTRING_PTR(str);
- else s = "";
+ s = RSTRING_PTR(str);
+ if (!s) s = "";
+ saltp = RSTRING_PTR(salt);
#ifdef BROKEN_CRYPT
- salt_8bit_clean = rb_str_dup(salt);
- enc = rb_ascii8bit_encoding();
- str_modifiable(salt_8bit_clean);
- rb_enc_associate(salt_8bit_clean, enc);
- salt_8bit_clean = rb_str_tr(salt_8bit_clean,
- rb_enc_str_new("\x80-\xFF", 3, enc),
- rb_usascii_str_new("\x00-\x7F", 3));
- result = rb_str_new2(crypt(s, RSTRING_PTR(salt_8bit_clean)));
-#else
- result = rb_str_new2(crypt(s, RSTRING_PTR(salt)));
+ if (!ISASCII((unsigned char)saltp[0]) || !ISASCII((unsigned char)saltp[1])) {
+ salt_8bit_clean[0] = saltp[0] & 0x7f;
+ salt_8bit_clean[1] = saltp[1] & 0x7f;
+ salt_8bit_clean[2] = '\0';
+ saltp = salt_8bit_clean;
+ }
#endif
+ result = rb_str_new2(crypt(s, saltp));
OBJ_INFECT(result, str);
OBJ_INFECT(result, salt);
return result;
@@ -6029,7 +6264,7 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
const char *f = " ";
long n, llen, rlen;
volatile VALUE pad;
- int singlebyte = 1;
+ int singlebyte = 1, cr;
rb_scan_args(argc, argv, "11", &w, &pad);
enc = STR_ENC_GET(str);
@@ -6050,6 +6285,7 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
n = width - len;
llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
rlen = n - llen;
+ cr = ENC_CODERANGE(str);
res = rb_str_new5(str, 0, RSTRING_LEN(str)+n*flen/fclen+2);
p = RSTRING_PTR(res);
while (llen) {
@@ -6095,6 +6331,10 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
OBJ_INFECT(res, str);
if (!NIL_P(pad)) OBJ_INFECT(res, pad);
rb_enc_associate(res, enc);
+ if (argc == 2)
+ cr = ENC_CODERANGE_AND(cr, ENC_CODERANGE(pad));
+ if (cr != ENC_CODERANGE_BROKEN)
+ ENC_CODERANGE_SET(res, cr);
return res;
}
@@ -6283,7 +6523,7 @@ static VALUE
rb_str_end_with(int argc, VALUE *argv, VALUE str)
{
int i;
- char *p, *s;
+ char *p, *s, *e;
rb_encoding *enc;
for (i=0; i<argc; i++) {
@@ -6292,8 +6532,9 @@ rb_str_end_with(int argc, VALUE *argv, VALUE str)
enc = rb_enc_check(str, tmp);
if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
p = RSTRING_PTR(str);
- s = p + RSTRING_LEN(str) - RSTRING_LEN(tmp);
- if (rb_enc_left_char_head(p, s, enc) != s)
+ e = p + RSTRING_LEN(str);
+ s = e - RSTRING_LEN(tmp);
+ if (rb_enc_left_char_head(p, s, e, enc) != s)
continue;
if (memcmp(s, RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
return Qtrue;
@@ -6695,6 +6936,7 @@ Init_String(void)
rb_define_method(rb_cString, "lines", rb_str_each_line, -1);
rb_define_method(rb_cString, "bytes", rb_str_each_byte, 0);
rb_define_method(rb_cString, "chars", rb_str_each_char, 0);
+ rb_define_method(rb_cString, "codepoints", rb_str_each_codepoint, 0);
rb_define_method(rb_cString, "reverse", rb_str_reverse, 0);
rb_define_method(rb_cString, "reverse!", rb_str_reverse_bang, 0);
rb_define_method(rb_cString, "concat", rb_str_concat, 1);
@@ -6744,6 +6986,7 @@ Init_String(void)
rb_define_method(rb_cString, "each_line", rb_str_each_line, -1);
rb_define_method(rb_cString, "each_byte", rb_str_each_byte, 0);
rb_define_method(rb_cString, "each_char", rb_str_each_char, 0);
+ rb_define_method(rb_cString, "each_codepoint", rb_str_each_codepoint, 0);
rb_define_method(rb_cString, "sum", rb_str_sum, -1);
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
new file mode 100644
index 0000000000..99ce108458
--- /dev/null
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -0,0 +1,689 @@
+require "test/unit"
+require "bigdecimal"
+
+class TestBigDecimal < Test::Unit::TestCase
+ def setup
+ BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true)
+ BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true)
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true)
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP)
+ BigDecimal.limit(0)
+ end
+
+ def test_version
+ assert_equal("1.0.1", BigDecimal.ver)
+ end
+
+ def test_global_new
+ assert_equal(1, BigDecimal("1"))
+ assert_equal(1, BigDecimal("1", 1))
+ assert_raise(ArgumentError) { BigDecimal("1", -1) }
+ end
+
+ def test_new
+ assert_equal(1, BigDecimal.new("1"))
+ assert_equal(1, BigDecimal.new("1", 1))
+ assert_equal(1, BigDecimal.new(" 1 "))
+ assert_equal(111, BigDecimal.new("1_1_1_"))
+ assert_equal(0, BigDecimal.new("_1_1_1"))
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_equal( 1, BigDecimal.new("Infinity").infinite?)
+ assert_equal(-1, BigDecimal.new("-Infinity").infinite?)
+ assert_equal(true, BigDecimal.new("NaN").nan?)
+ end
+
+ def _test_mode(type)
+ BigDecimal.mode(type, true)
+ assert_raise(FloatDomainError) { yield }
+
+ BigDecimal.mode(type, false)
+ assert_nothing_raised { yield }
+ end
+
+ def test_mode
+ assert_raise(TypeError) { BigDecimal.mode(BigDecimal::EXCEPTION_ALL, 1) }
+ assert_raise(TypeError) { BigDecimal.mode(BigDecimal::ROUND_MODE, 256) }
+ assert_raise(TypeError) { BigDecimal.mode(0xf000, true) }
+ end
+
+ def test_exception_nan
+ _test_mode(BigDecimal::EXCEPTION_NaN) { BigDecimal.new("NaN") }
+ end
+
+ def test_exception_infinity
+ _test_mode(BigDecimal::EXCEPTION_INFINITY) { BigDecimal.new("Infinity") }
+ end
+
+ def test_exception_underflow
+ _test_mode(BigDecimal::EXCEPTION_UNDERFLOW) do
+ x = BigDecimal.new("0.1")
+ 100.times do
+ x *= x
+ break if x == false
+ end
+ end
+ end
+
+ def test_exception_overflow
+ _test_mode(BigDecimal::EXCEPTION_OVERFLOW) do
+ x = BigDecimal.new("10")
+ 100.times do
+ x *= x
+ break if x == false
+ end
+ end
+ end
+
+ def test_exception_zerodivide
+ _test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { 1 / BigDecimal.new("0") }
+ _test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { -1 / BigDecimal.new("0") }
+ end
+
+ def test_round_up
+ n4 = BigDecimal.new("4") # n4 / 9 = 0.44444...
+ n5 = BigDecimal.new("5") # n5 / 9 = 0.55555...
+ n6 = BigDecimal.new("6") # n6 / 9 = 0.66666...
+ m4, m5, m6 = -n4, -n5, -n6
+ n2h = BigDecimal.new("2.5")
+ n3h = BigDecimal.new("3.5")
+ m2h, m3h = -n2h, -n3h
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_UP)
+ assert_operator(n4, :<, n4 / 9 * 9)
+ assert_operator(n5, :<, n5 / 9 * 9)
+ assert_operator(n6, :<, n6 / 9 * 9)
+ assert_operator(m4, :>, m4 / 9 * 9)
+ assert_operator(m5, :>, m5 / 9 * 9)
+ assert_operator(m6, :>, m6 / 9 * 9)
+ assert_equal(3, n2h.round)
+ assert_equal(4, n3h.round)
+ assert_equal(-3, m2h.round)
+ assert_equal(-4, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_DOWN)
+ assert_operator(n4, :>, n4 / 9 * 9)
+ assert_operator(n5, :>, n5 / 9 * 9)
+ assert_operator(n6, :>, n6 / 9 * 9)
+ assert_operator(m4, :<, m4 / 9 * 9)
+ assert_operator(m5, :<, m5 / 9 * 9)
+ assert_operator(m6, :<, m6 / 9 * 9)
+ assert_equal(2, n2h.round)
+ assert_equal(3, n3h.round)
+ assert_equal(-2, m2h.round)
+ assert_equal(-3, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP)
+ assert_operator(n4, :>, n4 / 9 * 9)
+ assert_operator(n5, :<, n5 / 9 * 9)
+ assert_operator(n6, :<, n6 / 9 * 9)
+ assert_operator(m4, :<, m4 / 9 * 9)
+ assert_operator(m5, :>, m5 / 9 * 9)
+ assert_operator(m6, :>, m6 / 9 * 9)
+ assert_equal(3, n2h.round)
+ assert_equal(4, n3h.round)
+ assert_equal(-3, m2h.round)
+ assert_equal(-4, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_DOWN)
+ assert_operator(n4, :>, n4 / 9 * 9)
+ assert_operator(n5, :>, n5 / 9 * 9)
+ assert_operator(n6, :<, n6 / 9 * 9)
+ assert_operator(m4, :<, m4 / 9 * 9)
+ assert_operator(m5, :<, m5 / 9 * 9)
+ assert_operator(m6, :>, m6 / 9 * 9)
+ assert_equal(2, n2h.round)
+ assert_equal(3, n3h.round)
+ assert_equal(-2, m2h.round)
+ assert_equal(-3, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN)
+ assert_operator(n4, :>, n4 / 9 * 9)
+ assert_operator(n5, :<, n5 / 9 * 9)
+ assert_operator(n6, :<, n6 / 9 * 9)
+ assert_operator(m4, :<, m4 / 9 * 9)
+ assert_operator(m5, :>, m5 / 9 * 9)
+ assert_operator(m6, :>, m6 / 9 * 9)
+ assert_equal(2, n2h.round)
+ assert_equal(4, n3h.round)
+ assert_equal(-2, m2h.round)
+ assert_equal(-4, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_CEILING)
+ assert_operator(n4, :<, n4 / 9 * 9)
+ assert_operator(n5, :<, n5 / 9 * 9)
+ assert_operator(n6, :<, n6 / 9 * 9)
+ assert_operator(m4, :<, m4 / 9 * 9)
+ assert_operator(m5, :<, m5 / 9 * 9)
+ assert_operator(m6, :<, m6 / 9 * 9)
+ assert_equal(3, n2h.round)
+ assert_equal(4, n3h.round)
+ assert_equal(-2, m2h.round)
+ assert_equal(-3, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR)
+ assert_operator(n4, :>, n4 / 9 * 9)
+ assert_operator(n5, :>, n5 / 9 * 9)
+ assert_operator(n6, :>, n6 / 9 * 9)
+ assert_operator(m4, :>, m4 / 9 * 9)
+ assert_operator(m5, :>, m5 / 9 * 9)
+ assert_operator(m6, :>, m6 / 9 * 9)
+ assert_equal(2, n2h.round)
+ assert_equal(3, n3h.round)
+ assert_equal(-3, m2h.round)
+ assert_equal(-4, m3h.round)
+ end
+
+ def test_zero_p
+ assert_equal(true, BigDecimal.new("0").zero?)
+ assert_equal(false, BigDecimal.new("1").zero?)
+ end
+
+ def test_nonzero_p
+ assert_equal(nil, BigDecimal.new("0").nonzero?)
+ assert_equal(BigDecimal.new("1"), BigDecimal.new("1").nonzero?)
+ end
+
+ def test_double_fig
+ assert_kind_of(Integer, BigDecimal.double_fig)
+ end
+
+ def test_cmp
+ n1 = BigDecimal.new("1")
+ n2 = BigDecimal.new("2")
+ assert_equal( 0, n1 <=> n1)
+ assert_equal( 1, n2 <=> n1)
+ assert_equal(-1, n1 <=> n2)
+ assert_operator(n1, :==, n1)
+ assert_operator(n1, :!=, n2)
+ assert_operator(n1, :<, n2)
+ assert_operator(n1, :<=, n1)
+ assert_operator(n1, :<=, n2)
+ assert_operator(n2, :>, n1)
+ assert_operator(n2, :>=, n1)
+ assert_operator(n1, :>=, n1)
+
+ assert_operator(BigDecimal.new("-0"), :==, BigDecimal.new("0"))
+ assert_operator(BigDecimal.new("0"), :<, BigDecimal.new("1"))
+ assert_operator(BigDecimal.new("1"), :>, BigDecimal.new("0"))
+ assert_operator(BigDecimal.new("1"), :>, BigDecimal.new("-1"))
+ assert_operator(BigDecimal.new("-1"), :<, BigDecimal.new("1"))
+ assert_operator(BigDecimal.new((2**100).to_s), :>, BigDecimal.new("1"))
+ assert_operator(BigDecimal.new("1"), :<, BigDecimal.new((2**100).to_s))
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ inf = BigDecimal.new("Infinity")
+ assert_operator(inf, :>, 1)
+ assert_operator(1, :<, inf)
+ end
+
+ def test_cmp_corece
+ n1 = BigDecimal.new("1")
+ n2 = BigDecimal.new("2")
+ o1 = Object.new; def o1.coerce(x); [x, BigDecimal.new("1")]; end
+ o2 = Object.new; def o2.coerce(x); [x, BigDecimal.new("2")]; end
+ assert_equal( 0, n1 <=> o1)
+ assert_equal( 1, n2 <=> o1)
+ assert_equal(-1, n1 <=> o2)
+ assert_operator(n1, :==, o1)
+ assert_operator(n1, :!=, o2)
+ assert_operator(n1, :<, o2)
+ assert_operator(n1, :<=, o1)
+ assert_operator(n1, :<=, o2)
+ assert_operator(n2, :>, o1)
+ assert_operator(n2, :>=, o1)
+ assert_operator(n1, :>=, 1)
+ end
+
+ def test_cmp_bignum
+ assert_operator(BigDecimal.new((2**100).to_s), :==, 2**100)
+ end
+
+ def test_cmp_data
+ d = Time.now; def d.coerce(x); [x, x]; end
+ assert_operator(BigDecimal.new((2**100).to_s), :==, d)
+ end
+
+ def test_precs
+ a = BigDecimal.new("1").precs
+ assert_instance_of(Array, a)
+ assert_equal(2, a.size)
+ assert_kind_of(Integer, a[0])
+ assert_kind_of(Integer, a[1])
+ end
+
+ def test_hash
+ a = []
+ x = BigDecimal.new("1")
+ 10.times { a << x *= 10 }
+ h = {}
+ a.each_with_index {|x, i| h[x] = i }
+ a.each_with_index do |x, i|
+ assert_equal(i, h[x])
+ end
+ end
+
+ def test_marshal
+ s = Marshal.dump(BigDecimal("1", 1))
+ assert_equal(BigDecimal("1", 1), Marshal.load(s))
+
+ # corrupt data
+ s = s.gsub(/BigDecimal.*\z/m) {|x| x.gsub(/\d/m, "-") }
+ assert_raise(TypeError) { Marshal.load(s) }
+ end
+
+ def test_finite_infinite_nan
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+
+ x = BigDecimal.new("0")
+ assert_equal(true, x.finite?)
+ assert_equal(nil, x.infinite?)
+ assert_equal(false, x.nan?)
+ y = 1 / x
+ assert_equal(false, y.finite?)
+ assert_equal(1, y.infinite?)
+ assert_equal(false, y.nan?)
+ y = -1 / x
+ assert_equal(false, y.finite?)
+ assert_equal(-1, y.infinite?)
+ assert_equal(false, y.nan?)
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ y = 0 / x
+ assert_equal(false, y.finite?)
+ assert_equal(nil, y.infinite?)
+ assert_equal(true, y.nan?)
+ end
+
+ def test_to_i
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+
+ x = BigDecimal.new("0")
+ assert_kind_of(Integer, x.to_i)
+ assert_equal(0, x.to_i)
+ assert_nil(( 1 / x).to_i)
+ assert_nil((-1 / x).to_i)
+ assert_nil(( 0 / x).to_i)
+ x = BigDecimal.new("1")
+ assert_equal(1, x.to_i)
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(2**100, x.to_i)
+ end
+
+ def test_to_f
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+
+ x = BigDecimal.new("0")
+ assert_instance_of(Float, x.to_f)
+ assert_equal(0.0, x.to_f)
+ assert_equal( 1.0 / 0.0, ( 1 / x).to_f)
+ assert_equal(-1.0 / 0.0, (-1 / x).to_f)
+ assert_equal(true, ( 0 / x).to_f.nan?)
+ x = BigDecimal.new("1")
+ assert_equal(1.0, x.to_f)
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal((2**100).to_f, x.to_f)
+ x = BigDecimal.new("1" + "0" * 10000)
+ assert_equal(0, BigDecimal.new("-0").to_f)
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true)
+ assert_raise(FloatDomainError) { x.to_f }
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ assert_kind_of(Float, x .to_f)
+ assert_kind_of(Float, (-x).to_f)
+ end
+
+ def test_coerce
+ a, b = BigDecimal.new("1").coerce(1.0)
+ assert_instance_of(Float, a)
+ assert_instance_of(Float, b)
+ end
+
+ def test_uplus
+ x = BigDecimal.new("1")
+ assert_equal(x, x.send(:+@))
+ end
+
+ def test_add
+ x = BigDecimal.new("1")
+ assert_equal(BigDecimal.new("2"), x + x)
+ assert_equal(1, BigDecimal.new("0") + 1)
+ assert_equal(1, x + 0)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("0") + 0).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("-0") + 0).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal.new("-0") + BigDecimal.new("-0")).sign)
+
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(BigDecimal.new((2**100+1).to_s), x + 1)
+ end
+
+ def test_sub
+ x = BigDecimal.new("1")
+ assert_equal(BigDecimal.new("0"), x - x)
+ assert_equal(-1, BigDecimal.new("0") - 1)
+ assert_equal(1, x - 0)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("0") - 0).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal.new("-0") - 0).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("-0") - BigDecimal.new("-0")).sign)
+
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(BigDecimal.new((2**100-1).to_s), x - 1)
+ end
+
+ def test_mult
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(BigDecimal.new((2**100 * 3).to_s), (x * 3).to_i)
+ assert_equal(x, (x * 1).to_i)
+ assert_equal(x, (BigDecimal("1") * x).to_i)
+ assert_equal(BigDecimal.new((2**200).to_s), (x * x).to_i)
+ end
+
+ def test_div
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(BigDecimal.new((2**100 / 3).to_s), (x / 3).to_i)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("0") / 1).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal.new("-0") / 1).sign)
+ assert_equal(2, BigDecimal.new("2") / 1)
+ assert_equal(-2, BigDecimal.new("2") / -1)
+ end
+
+ def test_mod
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(1, x % 3)
+ assert_equal(2, (-x) % 3)
+ assert_equal(-2, x % -3)
+ assert_equal(-1, (-x) % -3)
+ end
+
+ def test_remainder
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(1, x.remainder(3))
+ assert_equal(-1, (-x).remainder(3))
+ assert_equal(1, x.remainder(-3))
+ assert_equal(-1, (-x).remainder(-3))
+ end
+
+ def test_divmod
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal([(x / 3).floor, 1], x.divmod(3))
+ assert_equal([(-x / 3).floor, 2], (-x).divmod(3))
+
+ assert_equal([0, 0], BigDecimal.new("0").divmod(2))
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ a, b = BigDecimal.new("0").divmod(0)
+ assert_equal(true, a.nan?)
+ assert_equal(true, b.nan?)
+ end
+
+ def test_add_bigdecimal
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(3000000000000000000000000000000, x.add(x, 1))
+ assert_equal(2500000000000000000000000000000, x.add(x, 2))
+ assert_equal(2540000000000000000000000000000, x.add(x, 3))
+ end
+
+ def test_sub_bigdecimal
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(1000000000000000000000000000000, x.sub(1, 1))
+ assert_equal(1300000000000000000000000000000, x.sub(1, 2))
+ assert_equal(1270000000000000000000000000000, x.sub(1, 3))
+ end
+
+ def test_mult_bigdecimal
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(4000000000000000000000000000000, x.mult(3, 1))
+ assert_equal(3800000000000000000000000000000, x.mult(3, 2))
+ assert_equal(3800000000000000000000000000000, x.mult(3, 3))
+ end
+
+ def test_div_bigdecimal
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(422550200076076467165567735125, x.div(3))
+ assert_equal(400000000000000000000000000000, x.div(3, 1))
+ assert_equal(420000000000000000000000000000, x.div(3, 2))
+ assert_equal(423000000000000000000000000000, x.div(3, 3))
+ end
+
+ def test_abs_bigdecimal
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(1267650600228229401496703205376, x.abs)
+ x = BigDecimal.new("-" + (2**100).to_s)
+ assert_equal(1267650600228229401496703205376, x.abs)
+ x = BigDecimal.new("0")
+ assert_equal(0, x.abs)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ x = BigDecimal.new("NaN")
+ assert_equal(true, x.abs.nan?)
+ end
+
+ def test_sqrt_bigdecimal
+ x = BigDecimal.new("0.09")
+ assert_in_delta(0.3, x.sqrt(1), 0.001)
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(1125899906842624, x.sqrt(1))
+ assert_equal(1125899906842624, x.sqrt(2))
+ assert_equal(1125899906842624, x.sqrt(3)) # I don't understand the meaning of argument...
+ x = BigDecimal.new("-" + (2**100).to_s)
+ assert_raise(FloatDomainError) { x.sqrt(1) }
+ x = BigDecimal.new((2**200).to_s)
+ assert_equal(2**100, x.sqrt(1))
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_raise(FloatDomainError) { BigDecimal.new("NaN").sqrt(1) }
+
+ assert_equal(0, BigDecimal.new("0").sqrt(1))
+ assert_equal(1, BigDecimal.new("1").sqrt(1))
+ end
+
+ def test_fix
+ x = BigDecimal.new("1.1")
+ assert_equal(1, x.fix)
+ end
+
+ def test_frac
+ x = BigDecimal.new("1.1")
+ assert_equal(0.1, x.frac)
+ assert_equal(0.1, BigDecimal.new("0.1").frac)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_equal(true, BigDecimal.new("NaN").frac.nan?)
+ end
+
+ def test_round
+ assert_equal(3, BigDecimal.new("3.14159").round)
+ assert_equal(9, BigDecimal.new("8.7").round)
+ assert_equal(3.142, BigDecimal.new("3.14159").round(3))
+ assert_equal(13300.0, BigDecimal.new("13345.234").round(-2))
+
+ x = BigDecimal.new("111.111")
+ assert_equal(111 , x.round)
+ assert_equal(111.1 , x.round(1))
+ assert_equal(111.11 , x.round(2))
+ assert_equal(111.111, x.round(3))
+ assert_equal(111.111, x.round(4))
+ assert_equal(110 , x.round(-1))
+ assert_equal(100 , x.round(-2))
+ assert_equal( 0 , x.round(-3))
+ assert_equal( 0 , x.round(-4))
+
+ x = BigDecimal.new("2.5")
+ assert_equal(3, x.round(0, BigDecimal::ROUND_UP))
+ assert_equal(2, x.round(0, BigDecimal::ROUND_DOWN))
+ assert_equal(3, x.round(0, BigDecimal::ROUND_HALF_UP))
+ assert_equal(2, x.round(0, BigDecimal::ROUND_HALF_DOWN))
+ assert_equal(2, x.round(0, BigDecimal::ROUND_HALF_EVEN))
+ assert_equal(3, x.round(0, BigDecimal::ROUND_CEILING))
+ assert_equal(2, x.round(0, BigDecimal::ROUND_FLOOR))
+ assert_raise(TypeError) { x.round(0, 256) }
+ end
+
+ def test_truncate
+ assert_equal(3, BigDecimal.new("3.14159").truncate)
+ assert_equal(8, BigDecimal.new("8.7").truncate)
+ assert_equal(3.141, BigDecimal.new("3.14159").truncate(3))
+ assert_equal(13300.0, BigDecimal.new("13345.234").truncate(-2))
+ end
+
+ def test_floor
+ assert_equal(3, BigDecimal.new("3.14159").floor)
+ assert_equal(-10, BigDecimal.new("-9.1").floor)
+ assert_equal(3.141, BigDecimal.new("3.14159").floor(3))
+ assert_equal(13300.0, BigDecimal.new("13345.234").floor(-2))
+ end
+
+ def test_ceil
+ assert_equal(4, BigDecimal.new("3.14159").ceil)
+ assert_equal(-9, BigDecimal.new("-9.1").ceil)
+ assert_equal(3.142, BigDecimal.new("3.14159").ceil(3))
+ assert_equal(13400.0, BigDecimal.new("13345.234").ceil(-2))
+ end
+
+ def test_to_s
+ assert_equal('-123.45678 90123 45678 9', BigDecimal.new('-123.45678901234567890').to_s('5F'))
+ assert_equal('+123.45678901 23456789', BigDecimal.new('123.45678901234567890').to_s('+8F'))
+ assert_equal(' 123.4567890123456789', BigDecimal.new('123.45678901234567890').to_s(' F'))
+ assert_equal('0.1234567890123456789E3', BigDecimal.new('123.45678901234567890').to_s)
+ assert_equal('0.12345 67890 12345 6789E3', BigDecimal.new('123.45678901234567890').to_s(5))
+ end
+
+ def test_split
+ x = BigDecimal.new('-123.45678901234567890')
+ assert_equal([-1, "1234567890123456789", 10, 3], x.split)
+ assert_equal([1, "0", 10, 0], BigDecimal.new("0").split)
+ assert_equal([-1, "0", 10, 0], BigDecimal.new("-0").split)
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_equal([0, "NaN", 10, 0], BigDecimal.new("NaN").split)
+ assert_equal([1, "Infinity", 10, 0], BigDecimal.new("Infinity").split)
+ assert_equal([-1, "Infinity", 10, 0], BigDecimal.new("-Infinity").split)
+ end
+
+ def test_exponent
+ x = BigDecimal.new('-123.45678901234567890')
+ assert_equal(3, x.exponent)
+ end
+
+ def test_inspect
+ x = BigDecimal.new("1234.5678")
+ assert_match(/^#<BigDecimal:[0-9a-f]+,'0.12345678E4',8\(12\)>$/, x.inspect)
+ end
+
+ def test_power
+ x = BigDecimal.new("3")
+ assert_equal(81, x ** 4)
+ assert_equal(1.0/81, x ** -4)
+ assert_equal(1, x ** 0)
+ assert_raise(TypeError) { x ** x }
+ assert_equal(0, BigDecimal.new("0") ** 4)
+ assert_equal(1, BigDecimal.new("0") ** 0)
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ assert_equal(BigDecimal.new("Infinity"), BigDecimal.new("0") ** -1)
+ assert_equal(BigDecimal.new("-Infinity"), BigDecimal.new("-0") ** -1)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_equal(true, (BigDecimal.new("NaN") ** 1).nan?)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, (BigDecimal.new("Infinity") ** 2).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, (BigDecimal.new("Infinity") ** 1).sign)
+ assert_equal(1, BigDecimal.new("Infinity") ** 0)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("Infinity") ** -1).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("Infinity") ** -2).sign)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, (BigDecimal.new("-Infinity") ** 2).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_INFINITE, (BigDecimal.new("-Infinity") ** 1).sign)
+ assert_equal(1, BigDecimal.new("-Infinity") ** 0)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal.new("-Infinity") ** -1).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("-Infinity") ** -2).sign)
+ end
+
+ def test_limit
+ BigDecimal.limit(1)
+ x = BigDecimal.new("3")
+ assert_equal(90, x ** 4) # OK? must it be 80?
+ # 3 * 3 * 3 * 3 = 10 * 3 * 3 = 30 * 3 = 90 ???
+ assert_raise(ArgumentError) { BigDecimal.limit(-1) }
+ end
+
+ def test_sign
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal.new("0").sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, BigDecimal.new("-0").sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_FINITE, BigDecimal.new("1").sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_FINITE, BigDecimal.new("-1").sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, (BigDecimal.new("1") / 0).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_INFINITE, (BigDecimal.new("-1") / 0).sign)
+ assert_equal(BigDecimal::SIGN_NaN, (BigDecimal.new("0") / 0).sign)
+ end
+
+ def test_inf
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ inf = BigDecimal.new("Infinity")
+
+ assert_equal(inf, inf + inf)
+ assert_equal(true, (inf + (-inf)).nan?)
+ assert_equal(true, (inf - inf).nan?)
+ assert_equal(inf, inf - (-inf))
+ assert_equal(inf, inf * inf)
+ assert_equal(true, (inf / inf).nan?)
+
+ assert_equal(inf, inf + 1)
+ assert_equal(inf, inf - 1)
+ assert_equal(inf, inf * 1)
+ assert_equal(true, (inf * 0).nan?)
+ assert_equal(inf, inf / 1)
+
+ assert_equal(inf, 1 + inf)
+ assert_equal(-inf, 1 - inf)
+ assert_equal(inf, 1 * inf)
+ assert_equal(-inf, -1 * inf)
+ assert_equal(true, (0 * inf).nan?)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (1 / inf).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (-1 / inf).sign)
+ end
+
+ def test_to_special_string
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ nan = BigDecimal.new("NaN")
+ assert_equal("NaN", nan.to_s)
+ inf = BigDecimal.new("Infinity")
+ assert_equal("Infinity", inf.to_s)
+ assert_equal(" Infinity", inf.to_s(" "))
+ assert_equal("+Infinity", inf.to_s("+"))
+ assert_equal("-Infinity", (-inf).to_s)
+ pzero = BigDecimal.new("0")
+ assert_equal("0.0", pzero.to_s)
+ assert_equal(" 0.0", pzero.to_s(" "))
+ assert_equal("+0.0", pzero.to_s("+"))
+ assert_equal("-0.0", (-pzero).to_s)
+ end
+
+ def test_to_string
+ assert_equal("0.01", BigDecimal("0.01").to_s("F"))
+ s = "0." + "0" * 100 + "1"
+ assert_equal(s, BigDecimal(s).to_s("F"))
+ s = "1" + "0" * 100 + ".0"
+ assert_equal(s, BigDecimal(s).to_s("F"))
+ end
+
+ def test_ctov
+ assert_equal(0.1, BigDecimal.new("1E-1"))
+ assert_equal(10, BigDecimal.new("1E+1"))
+ assert_equal(1, BigDecimal.new("+1"))
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, BigDecimal.new("1E1" + "0" * 10000).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_INFINITE, BigDecimal.new("-1E1" + "0" * 10000).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal.new("1E-1" + "0" * 10000).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, BigDecimal.new("-1E-1" + "0" * 10000).sign)
+ end
+end
diff --git a/test/csv/tc_csv_parsing.rb b/test/csv/tc_csv_parsing.rb
index 965af929f3..635ae90531 100644
--- a/test/csv/tc_csv_parsing.rb
+++ b/test/csv/tc_csv_parsing.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_csv_parsing.rb
#
@@ -7,6 +8,7 @@
# under the terms of Ruby's license.
require "test/unit"
+require "timeout"
require "csv"
@@ -17,6 +19,8 @@ require "csv"
# separator <tt>$/</tt>.
#
class TestCSVParsing < Test::Unit::TestCase
+ BIG_DATA = "123456789\n" * 1024
+
def test_mastering_regex_example
ex = %Q{Ten Thousand,10000, 2710 ,,"10,000","It's ""10 Grand"", baby",10K}
assert_equal( [ "Ten Thousand", "10000", " 2710 ", nil, "10,000",
@@ -158,7 +162,31 @@ class TestCSVParsing < Test::Unit::TestCase
assert_send([csv.lineno, :<, 4])
end
rescue CSV::MalformedCSVError
- assert_equal("Unclosed quoted field on line 4.", $!.message)
+ assert_equal("Illegal quoting on line 4.", $!.message)
+ end
+ end
+
+ def test_the_parse_fails_fast_when_it_can_for_unquoted_fields
+ assert_parse_errors_out('valid,fields,bad start"' + BIG_DATA)
+ end
+
+ def test_the_parse_fails_fast_when_it_can_for_unescaped_quotes
+ assert_parse_errors_out('valid,fields,"bad start"unescaped' + BIG_DATA)
+ end
+
+ def test_field_size_limit_controls_lookahead
+ assert_parse_errors_out( 'valid,fields,"' + BIG_DATA + '"',
+ :field_size_limit => 2048 )
+ end
+
+ private
+
+ def assert_parse_errors_out(*args)
+ assert_raise(CSV::MalformedCSVError) do
+ Timeout.timeout(0.2) do
+ CSV.parse(*args)
+ fail("Parse didn't error out")
+ end
end
end
end
diff --git a/test/csv/tc_csv_writing.rb b/test/csv/tc_csv_writing.rb
index 4677284306..a1ce4de97e 100644
--- a/test/csv/tc_csv_writing.rb
+++ b/test/csv/tc_csv_writing.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_csv_writing.rb
#
diff --git a/test/csv/tc_data_converters.rb b/test/csv/tc_data_converters.rb
index 24c6b6b76f..acf27a6669 100644
--- a/test/csv/tc_data_converters.rb
+++ b/test/csv/tc_data_converters.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_data_converters.rb
#
diff --git a/test/csv/tc_features.rb b/test/csv/tc_features.rb
index ae5a8a451b..ad6732a1ec 100644
--- a/test/csv/tc_features.rb
+++ b/test/csv/tc_features.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_features.rb
#
@@ -67,18 +68,25 @@ class TestCSVFeatures < Test::Unit::TestCase
end
end
+ def test_csv_char_readers
+ %w[col_sep row_sep quote_char].each do |reader|
+ csv = CSV.new("abc,def", reader.to_sym => "|")
+ assert_equal("|", csv.send(reader))
+ end
+ end
+
def test_row_sep_auto_discovery
["\r\n", "\n", "\r"].each do |line_end|
data = "1,2,3#{line_end}4,5#{line_end}"
- discovered = CSV.new(data).instance_eval { @row_sep }
+ discovered = CSV.new(data).row_sep
assert_equal(line_end, discovered)
end
- assert_equal("\n", CSV.new("\n\r\n\r").instance_eval { @row_sep })
+ assert_equal("\n", CSV.new("\n\r\n\r").row_sep)
- assert_equal($/, CSV.new("").instance_eval { @row_sep })
+ assert_equal($/, CSV.new("").row_sep)
- assert_equal($/, CSV.new(STDERR).instance_eval { @row_sep })
+ assert_equal($/, CSV.new(STDERR).row_sep)
end
def test_lineno
@@ -117,6 +125,51 @@ class TestCSVFeatures < Test::Unit::TestCase
assert_equal(3, count)
end
+ def test_csv_behavior_readers
+ %w[ unconverted_fields return_headers write_headers
+ skip_blanks force_quotes ].each do |behavior|
+ assert( !CSV.new("abc,def").send("#{behavior}?"),
+ "Behavior defaulted to on." )
+ csv = CSV.new("abc,def", behavior.to_sym => true)
+ assert(csv.send("#{behavior}?"), "Behavior change now registered.")
+ end
+ end
+
+ def test_converters_reader
+ # no change
+ assert_equal( [:integer],
+ CSV.new("abc,def", :converters => [:integer]).converters )
+
+ # just one
+ assert_equal( [:integer],
+ CSV.new("abc,def", :converters => :integer).converters )
+
+ # expanded
+ assert_equal( [:integer, :float],
+ CSV.new("abc,def", :converters => :numeric).converters )
+
+ # custom
+ csv = CSV.new("abc,def", :converters => [:integer, lambda { }])
+ assert_equal(2, csv.converters.size)
+ assert_equal(:integer, csv.converters.first)
+ assert_instance_of(Proc, csv.converters.last)
+ end
+
+ def test_header_converters_reader
+ # no change
+ hc = :header_converters
+ assert_equal([:downcase], CSV.new("abc,def", hc => [:downcase]).send(hc))
+
+ # just one
+ assert_equal([:downcase], CSV.new("abc,def", hc => :downcase).send(hc))
+
+ # custom
+ csv = CSV.new("abc,def", hc => [:symbol, lambda { }])
+ assert_equal(2, csv.send(hc).size)
+ assert_equal(:symbol, csv.send(hc).first)
+ assert_instance_of(Proc, csv.send(hc).last)
+ end
+
# reported by Kev Jackson
def test_failing_to_escape_col_sep_bug_fix
assert_nothing_raised(Exception) { CSV.new(String.new, :col_sep => "|") }
@@ -149,7 +202,7 @@ class TestCSVFeatures < Test::Unit::TestCase
)
)
end
- assert_equal("\r\n", zipped.instance_eval { @row_sep })
+ assert_equal("\r\n", zipped.row_sep)
end
def test_gzip_writer_bug_fix
@@ -168,6 +221,41 @@ class TestCSVFeatures < Test::Unit::TestCase
File.unlink(file)
end
+ def test_inspect_is_smart_about_io_types
+ str = CSV.new("string,data").inspect
+ assert(str.include?("io_type:StringIO"), "IO type not detected.")
+
+ str = CSV.new($stderr).inspect
+ assert(str.include?("io_type:$stderr"), "IO type not detected.")
+
+ path = File.join(File.dirname(__FILE__), "temp.csv")
+ File.open(path, "w") { |csv| csv << "one,two,three\n1,2,3\n" }
+ str = CSV.open(path) { |csv| csv.inspect }
+ assert(str.include?("io_type:File"), "IO type not detected.")
+ File.unlink(path)
+ end
+
+ def test_inspect_shows_key_attributes
+ str = @csv.inspect
+ %w[lineno col_sep row_sep quote_char].each do |attr_name|
+ assert_match(/\b#{attr_name}:[^\s>]+/, str)
+ end
+ end
+
+ def test_inspect_shows_headers_when_available
+ CSV.new("one,two,three\n1,2,3\n", :headers => true) do |csv|
+ assert(csv.inspect.include?("headers:true"), "Header hint not shown.")
+ csv.shift # load headers
+ assert_match(/headers:\[[^\]]+\]/, csv.inspect)
+ end
+ end
+
+ def test_inspect_is_ascii_8bit_encoded
+ CSV.new("one,two,three\n1,2,3\n".encode("UTF-16BE")) do |csv|
+ assert_equal("ASCII-8BIT", csv.inspect.encoding.name)
+ end
+ end
+
def test_version
assert_not_nil(CSV::VERSION)
assert_instance_of(String, CSV::VERSION)
diff --git a/test/csv/tc_headers.rb b/test/csv/tc_headers.rb
index 74e2f54ad4..e0f544dadf 100644
--- a/test/csv/tc_headers.rb
+++ b/test/csv/tc_headers.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_headers.rb
#
@@ -129,6 +130,21 @@ class TestCSVHeaders < Test::Unit::TestCase
assert(!row.field_row?)
end
+ def test_csv_header_string_inherits_separators
+ # parse with custom col_sep
+ csv = nil
+ assert_nothing_raised(Exception) do
+ csv = CSV.parse( @data.tr(",", "|"), :col_sep => "|",
+ :headers => "my|new|headers" )
+ end
+
+ # verify headers were recognized
+ row = csv[0]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([%w{my first}, %w{new second}, %w{headers third}], row.to_a)
+ end
+
def test_return_headers
# activate headers and request they are returned
csv = nil
@@ -250,6 +266,17 @@ class TestCSVHeaders < Test::Unit::TestCase
end
end
+ def test_headers_reader
+ # no headers
+ assert_nil(CSV.new(@data).headers)
+
+ # headers
+ csv = CSV.new(@data, :headers => true)
+ assert_equal(true, csv.headers) # before headers are read
+ csv.shift # set headers
+ assert_equal(%w[first second third], csv.headers) # after headers are read
+ end
+
def test_blank_row_bug_fix
@data += "\n#{@data}" # add a blank row
diff --git a/test/csv/tc_interface.rb b/test/csv/tc_interface.rb
index e8cc920f9d..9cacc28b0a 100644
--- a/test/csv/tc_interface.rb
+++ b/test/csv/tc_interface.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_interface.rb
#
@@ -42,8 +43,9 @@ class TestCSVInterface < Test::Unit::TestCase
csv.close
assert(csv.closed?)
- ret = CSV.open(@path) do |csv|
- assert_instance_of(CSV, csv)
+ ret = CSV.open(@path) do |new_csv|
+ csv = new_csv
+ assert_instance_of(CSV, new_csv)
"Return value."
end
assert(csv.closed?)
@@ -161,7 +163,6 @@ class TestCSVInterface < Test::Unit::TestCase
lines = [{:a => 1, :b => 2, :c => 3}, {:a => 4, :b => 5, :c => 6}]
CSV.open( @path, "w", :headers => true,
- :converters => :all,
:header_converters => :symbol ) do |csv|
csv << lines.first.keys
lines.each { |line| csv << line }
@@ -173,6 +174,74 @@ class TestCSVInterface < Test::Unit::TestCase
end
end
+ def test_write_hash_with_headers_array
+ File.unlink(@path)
+
+ lines = [{:a => 1, :b => 2, :c => 3}, {:a => 4, :b => 5, :c => 6}]
+ CSV.open(@path, "w", :headers => [:b, :a, :c]) do |csv|
+ lines.each { |line| csv << line }
+ end
+
+ # test writing fields in the correct order
+ File.open(@path, "r") do |f|
+ assert_equal("2,1,3", f.gets.strip)
+ assert_equal("5,4,6", f.gets.strip)
+ end
+
+ # test reading CSV with headers
+ CSV.open( @path, "r", :headers => [:b, :a, :c],
+ :converters => :all ) do |csv|
+ csv.each { |line| assert_equal(lines.shift, line.to_hash) }
+ end
+ end
+
+ def test_write_hash_with_headers_string
+ File.unlink(@path)
+
+ lines = [{"a" => 1, "b" => 2, "c" => 3}, {"a" => 4, "b" => 5, "c" => 6}]
+ CSV.open(@path, "w", :headers => "b|a|c", :col_sep => "|") do |csv|
+ lines.each { |line| csv << line }
+ end
+
+ # test writing fields in the correct order
+ File.open(@path, "r") do |f|
+ assert_equal("2|1|3", f.gets.strip)
+ assert_equal("5|4|6", f.gets.strip)
+ end
+
+ # test reading CSV with headers
+ CSV.open( @path, "r", :headers => "b|a|c",
+ :col_sep => "|",
+ :converters => :all ) do |csv|
+ csv.each { |line| assert_equal(lines.shift, line.to_hash) }
+ end
+ end
+
+ def test_write_headers
+ File.unlink(@path)
+
+ lines = [{"a" => 1, "b" => 2, "c" => 3}, {"a" => 4, "b" => 5, "c" => 6}]
+ CSV.open( @path, "w", :headers => "b|a|c",
+ :write_headers => true,
+ :col_sep => "|" ) do |csv|
+ lines.each { |line| csv << line }
+ end
+
+ # test writing fields in the correct order
+ File.open(@path, "r") do |f|
+ assert_equal("b|a|c", f.gets.strip)
+ assert_equal("2|1|3", f.gets.strip)
+ assert_equal("5|4|6", f.gets.strip)
+ end
+
+ # test reading CSV with headers
+ CSV.open( @path, "r", :headers => true,
+ :col_sep => "|",
+ :converters => :all ) do |csv|
+ csv.each { |line| assert_equal(lines.shift, line.to_hash) }
+ end
+ end
+
def test_append # aliased add_row() and puts()
File.unlink(@path)
@@ -230,6 +299,6 @@ class TestCSVInterface < Test::Unit::TestCase
# shortcuts
assert_equal(STDOUT, CSV.instance.instance_eval { @io })
- assert_equal(STDOUT, CSV { |csv| csv.instance_eval { @io } })
+ assert_equal(STDOUT, CSV { |new_csv| new_csv.instance_eval { @io } })
end
end
diff --git a/test/csv/tc_row.rb b/test/csv/tc_row.rb
index a9b7f042b2..3fa3784bba 100644
--- a/test/csv/tc_row.rb
+++ b/test/csv/tc_row.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_row.rb
#
@@ -286,4 +287,24 @@ class TestCSVRow < Test::Unit::TestCase
assert_equal([@row.headers.size, @row.fields.size].max, @row.size)
end
+
+ def test_inspect_shows_header_field_pairs
+ str = @row.inspect
+ @row.each do |header, field|
+ assert( str.include?("#{header.inspect}:#{field.inspect}"),
+ "Header field pair not found." )
+ end
+ end
+
+ def test_inspect_is_ascii_8bit_encoded
+ assert_equal("ASCII-8BIT", @row.inspect.encoding.name)
+ end
+
+ def test_inspect_shows_symbol_headers_as_bare_attributes
+ str = CSV::Row.new(@row.headers.map { |h| h.to_sym }, @row.fields).inspect
+ @row.each do |header, field|
+ assert( str.include?("#{header}:#{field.inspect}"),
+ "Header field pair not found." )
+ end
+ end
end
diff --git a/test/csv/tc_serialization.rb b/test/csv/tc_serialization.rb
index d9c37fde21..c8273bdb3c 100644
--- a/test/csv/tc_serialization.rb
+++ b/test/csv/tc_serialization.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_serialization.rb
#
diff --git a/test/csv/tc_table.rb b/test/csv/tc_table.rb
index 028274d97f..1e572d979c 100644
--- a/test/csv/tc_table.rb
+++ b/test/csv/tc_table.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_table.rb
#
@@ -389,4 +390,17 @@ class TestCSVTable < Test::Unit::TestCase
assert_equal(@rows.size, @table.size)
end
+
+ def test_inspect_shows_current_mode
+ str = @table.inspect
+ assert(str.include?("mode:#{@table.mode}"), "Mode not shown.")
+
+ @table.by_col!
+ str = @table.inspect
+ assert(str.include?("mode:#{@table.mode}"), "Mode not shown.")
+ end
+
+ def test_inspect_is_us_ascii_encoded
+ assert_equal("US-ASCII", @table.inspect.encoding.name)
+ end
end
diff --git a/test/csv/ts_all.rb b/test/csv/ts_all.rb
index c930523757..d380ab5318 100644
--- a/test/csv/ts_all.rb
+++ b/test/csv/ts_all.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# ts_all.rb
#
@@ -17,3 +18,4 @@ require "tc_row"
require "tc_table"
require "tc_headers"
require "tc_serialization"
+require "tc_encodings"
diff --git a/test/json/fixtures/fail18.json b/test/json/fixtures/fail18.json
index d61a345465..e2d130c6eb 100644
--- a/test/json/fixtures/fail18.json
+++ b/test/json/fixtures/fail18.json
@@ -1 +1 @@
-[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] // No, we don't limit our depth: Moved to pass...
+[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
diff --git a/test/json/runner.rb b/test/json/runner.rb
index 91bc12a594..9ad04485bf 100755
--- a/test/json/runner.rb
+++ b/test/json/runner.rb
@@ -23,4 +23,3 @@ class TS_AllTests
end
end
Test::Unit::UI::Console::TestRunner.run(TS_AllTests)
- # vim: set et sw=2 ts=2:
diff --git a/test/json/test_json.rb b/test/json/test_json.rb
index 257b8e0f63..0ee993eb88 100755
--- a/test/json/test_json.rb
+++ b/test/json/test_json.rb
@@ -3,6 +3,7 @@
require 'test/unit'
require 'json'
+require 'stringio'
class TC_JSON < Test::Unit::TestCase
include JSON
@@ -61,6 +62,12 @@ class TC_JSON < Test::Unit::TestCase
assert_equal_float [3.141], parse('[3141.0E-3]')
assert_equal_float [-3.141], parse('[-3141.0e-3]')
assert_equal_float [-3.141], parse('[-3141e-3]')
+ assert_raises(ParserError) { parse('[NaN]') }
+ assert parse('[NaN]', :allow_nan => true).first.nan?
+ assert_raises(ParserError) { parse('[Infinity]') }
+ assert_equal [1.0/0], parse('[Infinity]', :allow_nan => true)
+ assert_raises(ParserError) { parse('[-Infinity]') }
+ assert_equal [-1.0/0], parse('[-Infinity]', :allow_nan => true)
assert_equal([""], parse('[""]'))
assert_equal(["foobar"], parse('["foobar"]'))
assert_equal([{}], parse('[{}]'))
@@ -238,18 +245,49 @@ EOT
end
def test_nesting
- to_deep = '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]'
- assert_raises(JSON::NestingError) { JSON.parse to_deep }
- assert_raises(JSON::NestingError) { JSON.parser.new(to_deep).parse }
- assert_raises(JSON::NestingError) { JSON.parse to_deep, :max_nesting => 19 }
- ok = JSON.parse to_deep, :max_nesting => 20
- assert_kind_of Array, ok
- ok = JSON.parse to_deep, :max_nesting => nil
- assert_kind_of Array, ok
- ok = JSON.parse to_deep, :max_nesting => false
- assert_kind_of Array, ok
- ok = JSON.parse to_deep, :max_nesting => 0
- assert_kind_of Array, ok
+ assert_raises(JSON::NestingError) { JSON.parse '[[]]', :max_nesting => 1 }
+ assert_raises(JSON::NestingError) { JSON.parser.new('[[]]', :max_nesting => 1).parse }
+ assert_equal [[]], JSON.parse('[[]]', :max_nesting => 2)
+ too_deep = '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]'
+ too_deep_ary = eval too_deep
+ assert_raises(JSON::NestingError) { JSON.parse too_deep }
+ assert_raises(JSON::NestingError) { JSON.parser.new(too_deep).parse }
+ assert_raises(JSON::NestingError) { JSON.parse too_deep, :max_nesting => 19 }
+ ok = JSON.parse too_deep, :max_nesting => 20
+ assert_equal too_deep_ary, ok
+ ok = JSON.parse too_deep, :max_nesting => nil
+ assert_equal too_deep_ary, ok
+ ok = JSON.parse too_deep, :max_nesting => false
+ assert_equal too_deep_ary, ok
+ ok = JSON.parse too_deep, :max_nesting => 0
+ assert_equal too_deep_ary, ok
+ assert_raises(JSON::NestingError) { JSON.generate [[]], :max_nesting => 1 }
+ assert_equal '[[]]', JSON.generate([[]], :max_nesting => 2)
+ assert_raises(JSON::NestingError) { JSON.generate too_deep_ary }
+ assert_raises(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 19 }
+ ok = JSON.generate too_deep_ary, :max_nesting => 20
+ assert_equal too_deep, ok
+ ok = JSON.generate too_deep_ary, :max_nesting => nil
+ assert_equal too_deep, ok
+ ok = JSON.generate too_deep_ary, :max_nesting => false
+ assert_equal too_deep, ok
+ ok = JSON.generate too_deep_ary, :max_nesting => 0
+ assert_equal too_deep, ok
+ end
+
+ def test_load_dump
+ too_deep = '[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]'
+ assert_equal too_deep, JSON.dump(eval(too_deep))
+ assert_kind_of String, Marshal.dump(eval(too_deep))
+ assert_raises(ArgumentError) { JSON.dump(eval(too_deep), 19) }
+ assert_raises(ArgumentError) { Marshal.dump(eval(too_deep), 19) }
+ assert_equal too_deep, JSON.dump(eval(too_deep), 20)
+ assert_kind_of String, Marshal.dump(eval(too_deep), 20)
+ output = StringIO.new
+ JSON.dump(eval(too_deep), output)
+ assert_equal too_deep, output.string
+ output = StringIO.new
+ JSON.dump(eval(too_deep), output, 20)
+ assert_equal too_deep, output.string
end
end
- # vim: set et sw=2 ts=2:
diff --git a/test/json/test_json_addition.rb b/test/json/test_json_addition.rb
index 04c690ce31..cf8a92ae10 100755
--- a/test/json/test_json_addition.rb
+++ b/test/json/test_json_addition.rb
@@ -31,6 +31,10 @@ class TC_JSONAddition < Test::Unit::TestCase
end
class B
+ def self.json_creatable?
+ false
+ end
+
def to_json(*args)
{
'json_class' => self.class.name,
@@ -50,9 +54,6 @@ class TC_JSONAddition < Test::Unit::TestCase
end
end
- def setup
- end
-
def test_extended_json
a = A.new(666)
assert A.json_creatable?
@@ -77,14 +78,14 @@ class TC_JSONAddition < Test::Unit::TestCase
)
end
- def test_extended_json_fail
+ def test_extended_json_fail1
b = B.new
assert !B.json_creatable?
json = generate(b)
- assert_equal({ 'json_class' => B.name }, JSON.parse(json))
+ assert_equal({ "json_class"=>"TC_JSONAddition::B" }, JSON.parse(json))
end
- def test_extended_json_fail
+ def test_extended_json_fail2
c = C.new
assert !C.json_creatable?
json = generate(c)
@@ -111,9 +112,11 @@ EOT
assert_equal raw, raw_again
end
+ MyJsonStruct = Struct.new 'MyJsonStruct', :foo, :bar
+
def test_core
- t = Time.at(1198254128, 895990)
- assert_equal t, JSON(JSON(t))
+ t = Time.now
+ assert_equal t.inspect, JSON(JSON(t)).inspect
d = Date.today
assert_equal d, JSON(JSON(d))
d = DateTime.civil(2007, 6, 14, 14, 57, 10, Rational(1, 12), 2299161)
@@ -122,8 +125,7 @@ EOT
assert_equal 1...10, JSON(JSON(1...10))
assert_equal "a".."c", JSON(JSON("a".."c"))
assert_equal "a"..."c", JSON(JSON("a"..."c"))
- struct = Struct.new 'MyJsonStruct', :foo, :bar
- s = struct.new 4711, 'foot'
+ s = MyJsonStruct.new 4711, 'foot'
assert_equal s, JSON(JSON(s))
struct = Struct.new :foo, :bar
s = struct.new 4711, 'foot'
@@ -137,7 +139,19 @@ EOT
assert_equal e.message, e_again.message
assert_equal e.backtrace, e_again.backtrace
end
- assert_equal /foo/, JSON(JSON(/foo/))
- assert_equal /foo/i, JSON(JSON(/foo/i))
+ assert_equal(/foo/, JSON(JSON(/foo/)))
+ assert_equal(/foo/i, JSON(JSON(/foo/i)))
+ end
+
+ def test_utc_datetime
+ now = Time.now
+ d = DateTime.parse(now.to_s) # usual case
+ assert d, JSON.parse(d.to_json)
+ d = DateTime.parse(now.utc.to_s) # of = 0
+ assert d, JSON.parse(d.to_json)
+ d = DateTime.civil(2008, 6, 17, 11, 48, 32, 1) # of = 1 / 12 => 1/12
+ assert d, JSON.parse(d.to_json)
+ d = DateTime.civil(2008, 6, 17, 11, 48, 32, 12) # of = 12 / 12 => 12
+ assert d, JSON.parse(d.to_json)
end
end
diff --git a/test/json/test_json_generate.rb b/test/json/test_json_generate.rb
index e720b2d862..b7e0bc22c6 100644
--- a/test/json/test_json_generate.rb
+++ b/test/json/test_json_generate.rb
@@ -70,6 +70,7 @@ EOT
#assert s.check_circular
h = { 1=>2 }
h[3] = h
+ assert_raises(JSON::CircularDatastructure) { generate(h) }
assert_raises(JSON::CircularDatastructure) { generate(h, s) }
s = JSON.state.new(:check_circular => true)
#assert s.check_circular
@@ -77,4 +78,22 @@ EOT
a << a
assert_raises(JSON::CircularDatastructure) { generate(a, s) }
end
+
+ def test_allow_nan
+ assert_raises(GeneratorError) { generate([JSON::NaN]) }
+ assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
+ assert_equal '[NaN]', fast_generate([JSON::NaN])
+ assert_raises(GeneratorError) { pretty_generate([JSON::NaN]) }
+ assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
+ assert_raises(GeneratorError) { generate([JSON::Infinity]) }
+ assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
+ assert_equal '[Infinity]', fast_generate([JSON::Infinity])
+ assert_raises(GeneratorError) { pretty_generate([JSON::Infinity]) }
+ assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
+ assert_raises(GeneratorError) { generate([JSON::MinusInfinity]) }
+ assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
+ assert_equal '[-Infinity]', fast_generate([JSON::MinusInfinity])
+ assert_raises(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
+ assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
+ end
end
diff --git a/test/json/test_json_rails.rb b/test/json/test_json_rails.rb
index e44ea606e3..c0447ddaba 100644
--- a/test/json/test_json_rails.rb
+++ b/test/json/test_json_rails.rb
@@ -31,6 +31,10 @@ class TC_JSONRails < Test::Unit::TestCase
end
class B
+ def self.json_creatable?
+ false
+ end
+
def to_json(*args)
{
'json_class' => self.class.name,
@@ -46,9 +50,6 @@ class TC_JSONRails < Test::Unit::TestCase
end
end
- def setup
- end
-
def test_extended_json
a = A.new(666)
assert A.json_creatable?
@@ -73,14 +74,14 @@ class TC_JSONRails < Test::Unit::TestCase
)
end
- def test_extended_json_fail
+ def test_extended_json_fail1
b = B.new
assert !B.json_creatable?
json = generate(b)
assert_equal({ 'json_class' => B.name }, JSON.parse(json))
end
- def test_extended_json_fail
+ def test_extended_json_fail2
c = C.new # with rails addition all objects are theoretically creatable
assert C.json_creatable?
json = generate(c)
diff --git a/test/json/test_json_unicode.rb b/test/json/test_json_unicode.rb
index cad93846b5..862c6ea1e0 100755
--- a/test/json/test_json_unicode.rb
+++ b/test/json/test_json_unicode.rb
@@ -7,9 +7,6 @@ require 'json'
class TC_JSONUnicode < Test::Unit::TestCase
include JSON
- def setup
- end
-
def test_unicode
assert_equal '""', ''.to_json
assert_equal '"\\b"', "\b".to_json
@@ -54,7 +51,7 @@ class TC_JSONUnicode < Test::Unit::TestCase
end
end
assert_raises(JSON::GeneratorError) do
- JSON.generate(["" << 0x80])
+ JSON.generate(["\x80"])
end
assert_equal "\302\200", JSON.parse('["\u0080"]').first
end
diff --git a/test/matrix/test_matrix.rb b/test/matrix/test_matrix.rb
new file mode 100644
index 0000000000..0850117b86
--- /dev/null
+++ b/test/matrix/test_matrix.rb
@@ -0,0 +1,49 @@
+require 'test/unit'
+require 'matrix'
+
+class TestMatrix < Test::Unit::TestCase
+ def setup
+ @m1 = Matrix[[1,2,3], [4,5,6]]
+ @m2 = Matrix[[1,2,3], [4,5,6]]
+ @m3 = @m1.clone
+ @m4 = Matrix[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
+ @n1 = Matrix[[2,3,4], [5,6,7]]
+ end
+
+ def test_identity
+ assert_same @m1, @m1
+ assert_not_same @m1, @m2
+ assert_not_same @m1, @m3
+ assert_not_same @m1, @m4
+ assert_not_same @m1, @n1
+ end
+
+ def test_equality
+ assert_equal @m1, @m1
+ assert_equal @m1, @m2
+ assert_equal @m1, @m3
+ assert_equal @m1, @m4
+ assert_not_equal @m1, @n1
+ end
+
+ def test_hash_equality
+ assert @m1.eql?(@m1)
+ assert @m1.eql?(@m2)
+ assert @m1.eql?(@m3)
+ assert !@m1.eql?(@m4)
+ assert !@m1.eql?(@n1)
+
+ hash = { @m1 => :value }
+ assert hash.key?(@m1)
+ assert hash.key?(@m2)
+ assert hash.key?(@m3)
+ assert !hash.key?(@m4)
+ assert !hash.key?(@n1)
+ end
+
+ def test_hash
+ assert_equal @m1.hash, @m1.hash
+ assert_equal @m1.hash, @m2.hash
+ assert_equal @m1.hash, @m3.hash
+ end
+end
diff --git a/test/matrix/test_vector.rb b/test/matrix/test_vector.rb
new file mode 100644
index 0000000000..95a39693fc
--- /dev/null
+++ b/test/matrix/test_vector.rb
@@ -0,0 +1,49 @@
+require 'test/unit'
+require 'matrix'
+
+class TestVector < Test::Unit::TestCase
+ def setup
+ @v1 = Vector[1,2,3]
+ @v2 = Vector[1,2,3]
+ @v3 = @v1.clone
+ @v4 = Vector[1.0, 2.0, 3.0]
+ @w1 = Vector[2,3,4]
+ end
+
+ def test_identity
+ assert_same @v1, @v1
+ assert_not_same @v1, @v2
+ assert_not_same @v1, @v3
+ assert_not_same @v1, @v4
+ assert_not_same @v1, @w1
+ end
+
+ def test_equality
+ assert_equal @v1, @v1
+ assert_equal @v1, @v2
+ assert_equal @v1, @v3
+ assert_equal @v1, @v4
+ assert_not_equal @v1, @w1
+ end
+
+ def test_hash_equality
+ assert @v1.eql?(@v1)
+ assert @v1.eql?(@v2)
+ assert @v1.eql?(@v3)
+ assert !@v1.eql?(@v4)
+ assert !@v1.eql?(@w1)
+
+ hash = { @v1 => :value }
+ assert hash.key?(@v1)
+ assert hash.key?(@v2)
+ assert hash.key?(@v3)
+ assert !hash.key?(@v4)
+ assert !hash.key?(@w1)
+ end
+
+ def test_hash
+ assert_equal @v1.hash, @v1.hash
+ assert_equal @v1.hash, @v2.hash
+ assert_equal @v1.hash, @v3.hash
+ end
+end
diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb
index ef612e2279..e2417fe14d 100644
--- a/test/ruby/test_complex.rb
+++ b/test/ruby/test_complex.rb
@@ -4,6 +4,14 @@ class ComplexSub < Complex; end
class Complex_Test < Test::Unit::TestCase
+ def setup
+ @rational = defined?(Rational)
+ if @rational
+ @keiju = Rational.instance_variable_get('@RCS_ID')
+ end
+ @unify = defined?(Complex::Unify)
+ end
+
def test_compsub
c = ComplexSub.__send__(:new, 1)
cc = ComplexSub.__send__(:convert, 1)
@@ -11,7 +19,7 @@ class Complex_Test < Test::Unit::TestCase
assert_kind_of(Numeric, c)
assert_kind_of(Numeric, cc)
- if defined?(ComplexSub::Unify)
+ if @unify
assert_instance_of(Fixnum, c)
assert_instance_of(Fixnum, cc)
else
@@ -42,7 +50,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(true, c.eql?(c2))
assert_equal(false, c.eql?(c3))
- if defined?(Complex::Unify)
+ if @unify
assert_equal(true, c.eql?(0))
else
assert_equal(false, c.eql?(0))
@@ -51,6 +59,7 @@ class Complex_Test < Test::Unit::TestCase
def test_hash
assert_instance_of(Fixnum, Complex(1,2).hash)
+ assert_instance_of(Fixnum, Complex(1.0,2.0).hash)
h = {}
h[Complex(0)] = 0
@@ -63,12 +72,15 @@ class Complex_Test < Test::Unit::TestCase
h[Complex(0,0)] = 9
assert_equal(4, h.size)
+
+ h[Complex(0.0,0.0)] = 9.0
+ assert_equal(5, h.size)
end
def test_freeze
c = Complex(1)
c.freeze
- unless defined?(Complex::Unify)
+ unless @unify
assert_equal(true, c.frozen?)
end
assert_instance_of(String, c.to_s)
@@ -77,45 +89,45 @@ class Complex_Test < Test::Unit::TestCase
def test_new_bang # no unify
assert_instance_of(Complex, Complex.__send__(:new!, 2,0))
assert_equal([2,0], Complex.__send__(:new!, 2,0).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([2,4], Complex.__send__(:new!, 2,4).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([-2,4], Complex.__send__(:new!, -2,4).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([2,-4], Complex.__send__(:new!, 2,-4).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([-2,-4], Complex.__send__(:new!, -2,-4).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([2,0], Complex.__send__(:new!, Complex(2)).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([2,3], Complex.__send__(:new!, Complex(2), Complex(3)).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([2,3], Complex.__send__(:new!, 2, Complex(3)).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([1.1,0], Complex.__send__(:new!, 1.1).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([-1.1,0], Complex.__send__(:new!, -1.1).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([1,0], Complex.__send__(:new!, '1').
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
assert_equal([0,0], Complex.__send__(:new!, nil).
- instance_eval{[real, image]})
+ instance_eval{[real, imag]})
end
def test_new
assert_instance_of(Complex, Complex.__send__(:new, 2,0.0))
- if defined?(Complex::Unify)
+ if @unify
assert_instance_of(Fixnum, Complex.__send__(:new, 2,0))
else
assert_instance_of(Complex, Complex.__send__(:new, 2,0))
- assert_equal([2,0], Complex.__send__(:new, 2,0). instance_eval{[real, image]})
+ assert_equal([2,0], Complex.__send__(:new, 2,0). instance_eval{[real, imag]})
end
- assert_equal([2,4], Complex.__send__(:new, 2,4).instance_eval{[real, image]})
- assert_equal([-2,4], Complex.__send__(:new, -2,4).instance_eval{[real, image]})
- assert_equal([2,-4], Complex.__send__(:new, 2,-4).instance_eval{[real, image]})
- assert_equal([-2,-4], Complex.__send__(:new, -2,-4).instance_eval{[real, image]})
+ assert_equal([2,4], Complex.__send__(:new, 2,4).instance_eval{[real, imag]})
+ assert_equal([-2,4], Complex.__send__(:new, -2,4).instance_eval{[real, imag]})
+ assert_equal([2,-4], Complex.__send__(:new, 2,-4).instance_eval{[real, imag]})
+ assert_equal([-2,-4], Complex.__send__(:new, -2,-4).instance_eval{[real, imag]})
assert_raise(ArgumentError){Complex.__send__(:new, Complex(1,2),2)}
assert_raise(ArgumentError){Complex.__send__(:new, 2,Complex(1,2))}
@@ -134,44 +146,38 @@ class Complex_Test < Test::Unit::TestCase
c = Complex(2**32, 2**32)
assert_equal(Complex.__send__(:new, 2**32,2**32), c)
- assert_equal([2**32,2**32], [c.real,c.image])
+ assert_equal([2**32,2**32], [c.real,c.imag])
c = Complex(-2**32, 2**32)
assert_equal(Complex.__send__(:new, -2**32,2**32), c)
- assert_equal([-2**32,2**32], [c.real,c.image])
+ assert_equal([-2**32,2**32], [c.real,c.imag])
c = Complex(2**32, -2**32)
assert_equal(Complex.__send__(:new, 2**32,-2**32), c)
- assert_equal([2**32,-2**32], [c.real,c.image])
+ assert_equal([2**32,-2**32], [c.real,c.imag])
c = Complex(-2**32, -2**32)
assert_equal(Complex.__send__(:new, -2**32,-2**32), c)
- assert_equal([-2**32,-2**32], [c.real,c.image])
+ assert_equal([-2**32,-2**32], [c.real,c.imag])
- c = Complex(Complex(1),0)
- assert_equal(Complex.__send__(:new, 1,0), c)
+ c = Complex(Complex(1,2),2)
+ assert_equal(Complex.__send__(:new, 1,4), c)
- c = Complex(0,Complex(1))
+ c = Complex(2,Complex(1,2))
assert_equal(Complex.__send__(:new, 0,1), c)
- c = 5.re
- assert_equal(Complex.__send__(:new, 5,0), c)
-
- c = Complex(1,2).re
- assert_equal(Complex.__send__(:new, 1,2), c)
-
- c = 5.im
- assert_equal(Complex.__send__(:new, 0,5), c)
-
- c = Complex(2,0).im
- assert_equal(Complex.__send__(:new, 0,2), c)
- assert_raise(ArgumentError){Complex(1,2).im}
+ c = Complex(Complex(1,2),Complex(1,2))
+ assert_equal(Complex.__send__(:new, -1,3), c)
c = Complex::I
assert_equal(Complex.__send__(:new, 0,1), c)
assert_equal(Complex.__send__(:new, 1),Complex(1))
assert_equal(Complex.__send__(:new, 1),Complex('1'))
+ assert_equal(Complex.__send__(:new, 3.0,3.0),Complex('3.0','3.0'))
+ if @rational && !@keiju
+ assert_equal(Complex.__send__(:new, 1,1),Complex('3/3','3/3'))
+ end
assert_raise(ArgumentError){Complex(nil)}
assert_raise(ArgumentError){Complex(Object.new)}
assert_raise(ArgumentError){Complex()}
@@ -182,64 +188,63 @@ class Complex_Test < Test::Unit::TestCase
c = Complex(4)
assert_equal(4, c.real)
- assert_equal(0, c.image)
+ assert_equal(0, c.imag)
c = Complex(4,5)
assert_equal(4, c.real)
- assert_equal(5, c.image)
+ assert_equal(5, c.imag)
if -0.0.to_s == '-0.0'
c = Complex(-0.0,-0.0)
assert_equal('-0.0', c.real.to_s)
- assert_equal('-0.0', c.image.to_s)
+ assert_equal('-0.0', c.imag.to_s)
end
c = Complex.__send__(:new, 4)
assert_equal(4, c.real)
- assert_equal(0, c.image)
- assert_equal(c.imag, c.image)
+ assert_equal(0, c.imag)
+ assert_equal(c.imag, c.imaginary)
c = Complex.__send__(:new, 4,5)
assert_equal(4, c.real)
- assert_equal(5, c.image)
- assert_equal(c.imag, c.image)
+ assert_equal(5, c.imag)
+ assert_equal(c.imag, c.imaginary)
if -0.0.to_s == '-0.0'
c = Complex.__send__(:new, -0.0,-0.0)
assert_equal('-0.0', c.real.to_s)
- assert_equal('-0.0', c.image.to_s)
- assert_equal(c.imag.to_s, c.image.to_s)
+ assert_equal('-0.0', c.imag.to_s)
+ assert_equal(c.imag.to_s, c.imaginary.to_s)
end
c = Complex.__send__(:new!, 4)
assert_equal(4, c.real)
- assert_equal(c.imag, c.image)
- assert_equal(0, c.image)
+ assert_equal(c.imag, c.imaginary)
+ assert_equal(0, c.imag)
c = Complex.__send__(:new!, 4,5)
assert_equal(4, c.real)
- assert_equal(5, c.image)
- assert_equal(c.imag, c.image)
+ assert_equal(5, c.imag)
+ assert_equal(c.imag, c.imaginary)
c = Complex.__send__(:new!, -0.0,-0.0)
assert_equal('-0.0', c.real.to_s)
- assert_equal('-0.0', c.image.to_s)
- assert_equal(c.imag.to_s, c.image.to_s)
+ assert_equal('-0.0', c.imag.to_s)
+ assert_equal(c.imag.to_s, c.imaginary.to_s)
end
def test_attr2
c = Complex(1)
- if defined?(Complex::Unify)
- assert_equal(true, c.scalar?)
+ if @unify
=begin
assert_equal(true, c.finite?)
assert_equal(false, c.infinite?)
@@ -247,13 +252,14 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(true, c.integer?)
assert_equal(false, c.float?)
assert_equal(true, c.rational?)
+=end
assert_equal(true, c.real?)
+=begin
assert_equal(false, c.complex?)
assert_equal(true, c.exact?)
assert_equal(false, c.inexact?)
=end
else
- assert_equal(false, c.scalar?)
=begin
assert_equal(true, c.finite?)
assert_equal(false, c.infinite?)
@@ -261,7 +267,9 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(false, c.integer?)
assert_equal(false, c.float?)
assert_equal(false, c.rational?)
+=end
assert_equal(false, c.real?)
+=begin
assert_equal(true, c.complex?)
assert_equal(true, c.exact?)
assert_equal(false, c.inexact?)
@@ -303,6 +311,16 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(-1,1), +Complex(-1,1))
assert_equal(Complex(1,-1), +Complex(1,-1))
assert_equal(Complex(-1,-1), +Complex(-1,-1))
+
+ if -0.0.to_s == '-0.0'
+ c = +Complex(0.0,0.0)
+ assert_equal('0.0', c.real.to_s)
+ assert_equal('0.0', c.imag.to_s)
+
+ c = +Complex(-0.0,-0.0)
+ assert_equal('-0.0', c.real.to_s)
+ assert_equal('-0.0', c.imag.to_s)
+ end
end
def test_negate
@@ -313,6 +331,16 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(-1,1), -Complex(1,-1))
assert_equal(Complex(1,1), -Complex(-1,-1))
+ if -0.0.to_s == '-0.0'
+ c = -Complex(0.0,0.0)
+ assert_equal('-0.0', c.real.to_s)
+ assert_equal('-0.0', c.imag.to_s)
+
+ c = -Complex(-0.0,-0.0)
+ assert_equal('0.0', c.real.to_s)
+ assert_equal('0.0', c.imag.to_s)
+ end
+
=begin
assert_equal(0, Complex(0).negate)
assert_equal(-2, Complex(2).negate)
@@ -329,7 +357,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(3,2), c + 2)
assert_equal(Complex(3.0,2), c + 2.0)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(3,1),Rational(2)), c + Rational(2))
assert_equal(Complex(Rational(5,3),Rational(2)), c + Rational(2,3))
end
@@ -344,7 +372,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(-1,2), c - 2)
assert_equal(Complex(-1.0,2), c - 2.0)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(-1,1),Rational(2)), c - Rational(2))
assert_equal(Complex(Rational(1,3),Rational(2)), c - Rational(2,3))
end
@@ -359,7 +387,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(2,4), c * 2)
assert_equal(Complex(2.0,4.0), c * 2.0)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(2,1),Rational(4)), c * Rational(2))
assert_equal(Complex(Rational(2,3),Rational(4,3)), c * Rational(2,3))
end
@@ -370,12 +398,12 @@ class Complex_Test < Test::Unit::TestCase
c = Complex(1,2)
c2 = Complex(2,3)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(8,13),Rational(1,13)), c / c2)
else
r = c / c2
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
end
c = Complex(1.0,2.0)
@@ -383,19 +411,19 @@ class Complex_Test < Test::Unit::TestCase
r = c / c2
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
c = Complex(1,2)
c2 = Complex(2,3)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(1,2),1), c / 2)
else
assert_equal(Complex(0.5,1.0), c / 2)
end
assert_equal(Complex(0.5,1.0), c / 2.0)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(1,2),Rational(1)), c / Rational(2))
assert_equal(Complex(Rational(3,2),Rational(3)), c / Rational(2,3))
end
@@ -405,12 +433,12 @@ class Complex_Test < Test::Unit::TestCase
c = Complex(1,2)
c2 = Complex(2,3)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(8,13),Rational(1,13)), c.quo(c2))
else
r = c.quo(c2)
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
end
c = Complex(1.0,2.0)
@@ -418,19 +446,19 @@ class Complex_Test < Test::Unit::TestCase
r = c.quo(c2)
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
c = Complex(1,2)
c2 = Complex(2,3)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(1,2),1), c.quo(2))
else
assert_equal(Complex(0.5,1.0), c.quo(2))
end
assert_equal(Complex(0.5,1.0), c.quo(2.0))
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(1,2),Rational(1)), c / Rational(2))
assert_equal(Complex(Rational(3,2),Rational(3)), c / Rational(2,3))
end
@@ -442,14 +470,14 @@ class Complex_Test < Test::Unit::TestCase
r = c.fdiv(c2)
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
c = Complex(1.0,2.0)
c2 = Complex(2.0,3.0)
r = c.fdiv(c2)
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
c = Complex(1,2)
c2 = Complex(2,3)
@@ -464,25 +492,25 @@ class Complex_Test < Test::Unit::TestCase
r = c ** c2
assert_in_delta(-0.015, r.real, 0.001)
- assert_in_delta(-0.179, r.image, 0.001)
+ assert_in_delta(-0.179, r.imag, 0.001)
assert_equal(Complex(-3,4), c ** 2)
- if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@keiju
assert_equal(Complex(Rational(-3,25),Rational(-4,25)), c ** -2)
else
r = c ** -2
assert_in_delta(-0.12, r.real, 0.001)
- assert_in_delta(-0.16, r.image, 0.001)
+ assert_in_delta(-0.16, r.imag, 0.001)
end
r = c ** 2.0
assert_in_delta(-3.0, r.real, 0.001)
- assert_in_delta(4.0, r.image, 0.001)
+ assert_in_delta(4.0, r.imag, 0.001)
r = c ** -2.0
assert_in_delta(-0.12, r.real, 0.001)
- assert_in_delta(-0.16, r.image, 0.001)
+ assert_in_delta(-0.16, r.imag, 0.001)
- if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@keiju
assert_equal(Complex(-3,4), c ** Rational(2))
#=begin
assert_equal(Complex(Rational(-3,25),Rational(-4,25)),
@@ -491,11 +519,11 @@ class Complex_Test < Test::Unit::TestCase
r = c ** Rational(2,3)
assert_in_delta(1.264, r.real, 0.001)
- assert_in_delta(1.150, r.image, 0.001)
+ assert_in_delta(1.150, r.imag, 0.001)
r = c ** Rational(-2,3)
assert_in_delta(0.432, r.real, 0.001)
- assert_in_delta(-0.393, r.image, 0.001)
+ assert_in_delta(-0.393, r.imag, 0.001)
end
end
@@ -525,7 +553,7 @@ class Complex_Test < Test::Unit::TestCase
end
def test_unify
- if defined?(Complex::Unify)
+ if @unify
assert_instance_of(Fixnum, Complex(1,2) + Complex(-1,-2))
assert_instance_of(Fixnum, Complex(1,2) - Complex(1,2))
assert_instance_of(Fixnum, Complex(1,2) * 0)
@@ -544,9 +572,9 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(5, c.abs2)
assert_equal(c.abs, Math.sqrt(c * c.conj))
- assert_equal(c.abs, Math.sqrt(c.real**2 + c.image**2))
+ assert_equal(c.abs, Math.sqrt(c.real**2 + c.imag**2))
assert_equal(c.abs2, c * c.conj)
- assert_equal(c.abs2, c.real**2 + c.image**2)
+ assert_equal(c.abs2, c.real**2 + c.imag**2)
assert_in_delta(1.107, c.arg, 0.001)
assert_in_delta(1.107, c.angle, 0.001)
@@ -586,7 +614,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal('1.0-2.0i', Complex(1.0,-2.0).to_s)
assert_equal('-1.0-2.0i', Complex(-1.0,-2.0).to_s)
- if defined?(Rational) && !defined?(Complex::Unify) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@unify && !@keiju
assert_equal('0+2/1i', Complex(0,Rational(2)).to_s)
assert_equal('0-2/1i', Complex(0,Rational(-2)).to_s)
assert_equal('1+2/1i', Complex(1,Rational(2)).to_s)
@@ -614,13 +642,15 @@ class Complex_Test < Test::Unit::TestCase
def test_marshal
c = Complex(1,2)
+ c.instance_eval{@ivar = 9}
s = Marshal.dump(c)
c2 = Marshal.load(s)
assert_equal(c, c2)
+ assert_equal(9, c2.instance_variable_get(:@ivar))
assert_instance_of(Complex, c2)
- if defined?(Rational)
+ if @rational
c = Complex(Rational(1,2),Rational(2,3))
s = Marshal.dump(c)
@@ -755,7 +785,7 @@ class Complex_Test < Test::Unit::TestCase
assert_raise(ArgumentError){ Complex('5+3i_')}
assert_raise(ArgumentError){ Complex('5+3ix')}
- if defined?(Rational) && defined?(''.to_r)
+ if @rational && defined?(''.to_r)
assert_equal(Complex(Rational(1,5)), '1/5'.to_c)
assert_equal(Complex(Rational(-1,5)), '-1/5'.to_c)
assert_equal(Complex(Rational(1,5),3), '1/5+3i'.to_c)
@@ -821,51 +851,47 @@ class Complex_Test < Test::Unit::TestCase
end
def test_to_r
- if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@keiju
assert_equal(Rational(3), Complex(3).to_r)
assert_equal(Rational(3), Rational(Complex(3)))
assert_raise(RangeError){Complex(3,2).to_r}
- assert_raise(RangeError){Rational(Complex(3,2))}
+# assert_raise(RangeError){Rational(Complex(3,2))}
end
end
def test_to_c
c = nil.to_c
- assert_equal([0,0] , [c.real, c.image])
+ assert_equal([0,0] , [c.real, c.imag])
c = 0.to_c
- assert_equal([0,0] , [c.real, c.image])
+ assert_equal([0,0] , [c.real, c.imag])
c = 1.to_c
- assert_equal([1,0] , [c.real, c.image])
+ assert_equal([1,0] , [c.real, c.imag])
c = 1.1.to_c
- assert_equal([1.1, 0], [c.real, c.image])
+ assert_equal([1.1, 0], [c.real, c.imag])
- if defined?(Rational)
+ if @rational
c = Rational(1,2).to_c
- assert_equal([Rational(1,2), 0], [c.real, c.image])
+ assert_equal([Rational(1,2), 0], [c.real, c.imag])
end
c = Complex(1,2).to_c
- assert_equal([1, 2], [c.real, c.image])
- end
-
- def test_prec
- assert_equal(nil, Complex < Precision)
+ assert_equal([1, 2], [c.real, c.imag])
end
def test_supp
- assert_equal(true, 1.scalar?)
- assert_equal(true, 1.1.scalar?)
+ assert_equal(true, 1.real?)
+ assert_equal(true, 1.1.real?)
assert_equal(1, 1.real)
- assert_equal(0, 1.image)
assert_equal(0, 1.imag)
+ assert_equal(0, 1.imaginary)
assert_equal(1.1, 1.1.real)
- assert_equal(0, 1.1.image)
assert_equal(0, 1.1.imag)
+ assert_equal(0, 1.1.imaginary)
assert_equal(1, 1.magnitude)
assert_equal(1, -1.magnitude)
@@ -919,14 +945,14 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(1.1, 1.1.conj)
assert_equal(-1.1, -1.1.conj)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(1,2),Rational(1)), Complex(1,2).quo(2))
else
assert_equal(Complex(0.5,1.0), Complex(1,2).quo(2))
end
=begin
- if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@keiju
assert_equal(Complex(Rational(1,2),Rational(1)), Complex(1,2).quo(2))
end
=end
@@ -934,7 +960,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(0.5, 1.fdiv(2))
assert_equal(5000000000.0, 10000000000.fdiv(2))
assert_equal(0.5, 1.0.fdiv(2))
- if defined?(Rational)
+ if @rational
assert_equal(0.25, Rational(1,2).fdiv(2))
end
assert_equal(Complex(0.5,1.0), Complex(1,2).quo(2))
@@ -944,7 +970,7 @@ class Complex_Test < Test::Unit::TestCase
# assert_equal(true, Math.sqrt(-4.0).inexact?)
assert_equal(Complex(0,2), Math.sqrt(-4))
# assert_equal(true, Math.sqrt(-4).exact?)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(0,2), Math.sqrt(Rational(-4)))
# assert_equal(true, Math.sqrt(Rational(-4)).exact?)
end
@@ -953,98 +979,98 @@ class Complex_Test < Test::Unit::TestCase
# assert_equal(true, Math.sqrt(-9.0).inexact?)
assert_equal(Complex(0,3), Math.sqrt(-9))
# assert_equal(true, Math.sqrt(-9).exact?)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(0,3), Math.sqrt(Rational(-9)))
# assert_equal(true, Math.sqrt(Rational(-9)).exact?)
end
c = Math.sqrt(Complex(1, 2))
assert_in_delta(1.272, c.real, 0.001)
- assert_in_delta(0.786, c.image, 0.001)
+ assert_in_delta(0.786, c.imag, 0.001)
c = Math.sqrt(-9)
assert_in_delta(0.0, c.real, 0.001)
- assert_in_delta(3.0, c.image, 0.001)
+ assert_in_delta(3.0, c.imag, 0.001)
c = Math.exp(Complex(1, 2))
assert_in_delta(-1.131, c.real, 0.001)
- assert_in_delta(2.471, c.image, 0.001)
+ assert_in_delta(2.471, c.imag, 0.001)
c = Math.sin(Complex(1, 2))
assert_in_delta(3.165, c.real, 0.001)
- assert_in_delta(1.959, c.image, 0.001)
+ assert_in_delta(1.959, c.imag, 0.001)
c = Math.cos(Complex(1, 2))
assert_in_delta(2.032, c.real, 0.001)
- assert_in_delta(-3.051, c.image, 0.001)
+ assert_in_delta(-3.051, c.imag, 0.001)
c = Math.tan(Complex(1, 2))
assert_in_delta(0.033, c.real, 0.001)
- assert_in_delta(1.014, c.image, 0.001)
+ assert_in_delta(1.014, c.imag, 0.001)
c = Math.sinh(Complex(1, 2))
assert_in_delta(-0.489, c.real, 0.001)
- assert_in_delta(1.403, c.image, 0.001)
+ assert_in_delta(1.403, c.imag, 0.001)
c = Math.cosh(Complex(1, 2))
assert_in_delta(-0.642, c.real, 0.001)
- assert_in_delta(1.068, c.image, 0.001)
+ assert_in_delta(1.068, c.imag, 0.001)
c = Math.tanh(Complex(1, 2))
assert_in_delta(1.166, c.real, 0.001)
- assert_in_delta(-0.243, c.image, 0.001)
+ assert_in_delta(-0.243, c.imag, 0.001)
c = Math.log(Complex(1, 2))
assert_in_delta(0.804, c.real, 0.001)
- assert_in_delta(1.107, c.image, 0.001)
+ assert_in_delta(1.107, c.imag, 0.001)
c = Math.log(Complex(1, 2), Math::E)
assert_in_delta(0.804, c.real, 0.001)
- assert_in_delta(1.107, c.image, 0.001)
+ assert_in_delta(1.107, c.imag, 0.001)
c = Math.log(-1)
assert_in_delta(0.0, c.real, 0.001)
- assert_in_delta(Math::PI, c.image, 0.001)
+ assert_in_delta(Math::PI, c.imag, 0.001)
c = Math.log(8, 2)
assert_in_delta(3.0, c.real, 0.001)
- assert_in_delta(0.0, c.image, 0.001)
+ assert_in_delta(0.0, c.imag, 0.001)
c = Math.log(-8, -2)
assert_in_delta(1.092, c.real, 0.001)
- assert_in_delta(-0.420, c.image, 0.001)
+ assert_in_delta(-0.420, c.imag, 0.001)
c = Math.log10(Complex(1, 2))
assert_in_delta(0.349, c.real, 0.001)
- assert_in_delta(0.480, c.image, 0.001)
+ assert_in_delta(0.480, c.imag, 0.001)
c = Math.asin(Complex(1, 2))
assert_in_delta(0.427, c.real, 0.001)
- assert_in_delta(1.528, c.image, 0.001)
+ assert_in_delta(1.528, c.imag, 0.001)
c = Math.acos(Complex(1, 2))
assert_in_delta(1.143, c.real, 0.001)
- assert_in_delta(-1.528, c.image, 0.001)
+ assert_in_delta(-1.528, c.imag, 0.001)
c = Math.atan(Complex(1, 2))
assert_in_delta(1.338, c.real, 0.001)
- assert_in_delta(0.402, c.image, 0.001)
+ assert_in_delta(0.402, c.imag, 0.001)
c = Math.atan2(Complex(1, 2), 1)
assert_in_delta(1.338, c.real, 0.001)
- assert_in_delta(0.402, c.image, 0.001)
+ assert_in_delta(0.402, c.imag, 0.001)
c = Math.asinh(Complex(1, 2))
assert_in_delta(1.469, c.real, 0.001)
- assert_in_delta(1.063, c.image, 0.001)
+ assert_in_delta(1.063, c.imag, 0.001)
c = Math.acosh(Complex(1, 2))
assert_in_delta(1.528, c.real, 0.001)
- assert_in_delta(1.143, c.image, 0.001)
+ assert_in_delta(1.143, c.imag, 0.001)
c = Math.atanh(Complex(1, 2))
assert_in_delta(0.173, c.real, 0.001)
- assert_in_delta(1.178, c.image, 0.001)
+ assert_in_delta(1.178, c.imag, 0.001)
end
end
@@ -1056,7 +1082,7 @@ class Complex_Test < Test::Unit::TestCase
end
def test_fixed_bug
- if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@keiju
assert_equal(Complex(1), 1 ** Complex(1))
end
assert_equal('-1.0-0.0i', Complex(-1.0, -0.0).to_s)
diff --git a/test/ruby/test_fixnum.rb b/test/ruby/test_fixnum.rb
index 8fa751ba98..e55e324bd1 100644
--- a/test/ruby/test_fixnum.rb
+++ b/test/ruby/test_fixnum.rb
@@ -119,15 +119,6 @@ class TestFixnum < Test::Unit::TestCase
assert_equal(0x4000000000000000, (-0x4000000000000000).abs)
end
- def test_induced_from
- assert_equal(1, Fixnum.induced_from(1))
- assert_raise(RangeError) do
- Fixnum.induced_from(2**31-1)
- Fixnum.induced_from(2**63-1)
- end
- assert_equal(1, Fixnum.induced_from((2**32).coerce(1).first))
- end
-
def test_to_s
assert_equal("1010", 10.to_s(2))
assert_equal("a", 10.to_s(36))
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index d4bbd688d2..5d7bbb178b 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -275,13 +275,6 @@ class TestFloat < Test::Unit::TestCase
assert_equal(11100.0, 11111.1.round(-2))
end
- def test_induced_from
- assert_equal(1.0, Float.induced_from(1))
- assert_equal(1.0, Float.induced_from(1.0))
- assert_raise(TypeError) { Float.induced_from(nil) }
- end
-
-
VS = [
18446744073709551617.0,
18446744073709551616.0,
diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb
index e31fb1880d..232a7fae30 100644
--- a/test/ruby/test_integer.rb
+++ b/test/ruby/test_integer.rb
@@ -122,12 +122,6 @@ class TestInteger < Test::Unit::TestCase
assert_raise(RangeError) { 0x100.chr }
end
- def test_induced_from
- assert_equal(1, Integer.induced_from(1))
- assert_equal(1, Integer.induced_from(1.0))
- assert_raise(TypeError) { Integer.induced_from(nil) }
- end
-
def test_upto
a = []
1.upto(3) {|x| a << x }
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index 35f575aa13..4d9bb51fe3 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -578,18 +578,6 @@ class TestIO < Test::Unit::TestCase
(wt.kill; wt.join) if wt
end
- def pipe2(&b)
- a = []
- a << IO.pipe while true
- rescue Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM
- yield(*a.last)
- ensure
- a.each do |r, w|
- r.close unless !r || r.closed?
- w.close unless !w || w.closed?
- end
- end
-
def ruby(*args)
args = ['-e', '$>.write($<.read)'] if args.empty?
ruby = EnvUtil.rubybin
@@ -636,14 +624,16 @@ class TestIO < Test::Unit::TestCase
assert_equal("", f2.read)
end
- proc do
- open(__FILE__) # see Bug #493 [ruby-dev:35957]
- end.call
-
- pipe2 do |r, w|
- assert_raise(Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM) do
- r2, w2 = r.dup, w.dup
- end
+ a = []
+ assert_raise(Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM) do
+ loop {a << IO.pipe}
+ end
+ assert_raise(Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM) do
+ loop {a << [a[-1][0].dup, a[-1][1].dup]}
+ end
+ a.each do |r, w|
+ r.close unless !r || r.closed?
+ w.close unless !w || w.closed?
end
end
diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb
index 237698b868..3f21ee088e 100644
--- a/test/ruby/test_io_m17n.rb
+++ b/test/ruby/test_io_m17n.rb
@@ -374,7 +374,7 @@ EOT
with_pipe("euc-jp:utf-8") {|r, w|
w << "\xa1xyz"
w.close
- err = assert_raise(Encoding::InvalidByteSequence) { r.getc }
+ err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc }
assert_equal("\xA1".force_encoding("ascii-8bit"), err.error_bytes)
assert_equal("xyz", r.read(10))
}
@@ -652,7 +652,7 @@ EOT
after = "\u{3046}\u{3048}"
w << before + invalid + after
w.close
- err = assert_raise(Encoding::InvalidByteSequence) { r.gets }
+ err = assert_raise(Encoding::InvalidByteSequenceError) { r.gets }
assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
assert_equal(after.encode("euc-jp"), r.gets)
}
@@ -669,7 +669,7 @@ EOT
w.close
assert_equal(before1.encode("euc-jp"), r.getc)
assert_equal(before2.encode("euc-jp"), r.getc)
- err = assert_raise(Encoding::InvalidByteSequence) { r.getc }
+ err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc }
assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
assert_equal(after1.encode("euc-jp"), r.getc)
assert_equal(after2.encode("euc-jp"), r.getc)
@@ -688,7 +688,7 @@ EOT
w.close
assert_equal(before1.encode("euc-jp"), r.getc)
assert_equal(before2.encode("euc-jp"), r.getc)
- err = assert_raise(Encoding::InvalidByteSequence) { r.getc }
+ err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc }
assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
assert_equal(after1.encode("euc-jp"), r.getc)
assert_equal(after2.encode("euc-jp"), r.getc)
@@ -711,7 +711,7 @@ EOT
after = "\u{3046}\u{3048}"
w << before + invalid + after
w.close
- err = assert_raise(Encoding::InvalidByteSequence) { r.read }
+ err = assert_raise(Encoding::InvalidByteSequenceError) { r.read }
assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
assert_equal(after.encode("euc-jp"), r.read)
}
@@ -809,28 +809,28 @@ EOT
def test_set_encoding_binmode
assert_raise(ArgumentError) {
- open("/dev/null", "rt") {|f|
+ open(__FILE__, "rt") {|f|
f.set_encoding("iso-2022-jp")
}
}
assert_raise(ArgumentError) {
- open("/dev/null", "r") {|f|
+ open(__FILE__, "r") {|f|
f.set_encoding("iso-2022-jp")
}
}
assert_nothing_raised {
- open("/dev/null", "rb") {|f|
+ open(__FILE__, "rb") {|f|
f.set_encoding("iso-2022-jp")
}
}
assert_nothing_raised {
- open("/dev/null", "r") {|f|
+ open(__FILE__, "r") {|f|
f.binmode
f.set_encoding("iso-2022-jp")
}
}
assert_nothing_raised {
- open("/dev/null", "rt") {|f|
+ open(__FILE__, "rt") {|f|
f.binmode
f.set_encoding("iso-2022-jp")
}
@@ -1549,11 +1549,11 @@ EOT
assert_equal("ab", f.read)
}
open("t.txt", "r:utf-8:euc-jp", :undef => :replace) {|f|
- assert_raise(Encoding::InvalidByteSequence) { f.read }
+ assert_raise(Encoding::InvalidByteSequenceError) { f.read }
assert_equal("b", f.read)
}
open("t.txt", "r:utf-8:euc-jp", :undef => :replace, :replace => "") {|f|
- assert_raise(Encoding::InvalidByteSequence) { f.read }
+ assert_raise(Encoding::InvalidByteSequenceError) { f.read }
assert_equal("b", f.read)
}
}
@@ -1569,11 +1569,11 @@ EOT
assert_equal("ab", f.read)
}
open("t.txt", "r:utf-8:euc-jp", :invalid => :replace) {|f|
- assert_raise(Encoding::ConversionUndefined) { f.read }
+ assert_raise(Encoding::ConversionUndefinedError) { f.read }
assert_equal("b", f.read)
}
open("t.txt", "r:utf-8:euc-jp", :invalid => :replace, :replace => "") {|f|
- assert_raise(Encoding::ConversionUndefined) { f.read }
+ assert_raise(Encoding::ConversionUndefinedError) { f.read }
assert_equal("b", f.read)
}
}
@@ -1593,10 +1593,10 @@ EOT
assert_equal("ab", File.read("t.txt"))
open("t.txt", "w:euc-jp", :undef => :replace) {|f|
- assert_raise(Encoding::InvalidByteSequence) { f.write invalid_utf8 }
+ assert_raise(Encoding::InvalidByteSequenceError) { f.write invalid_utf8 }
}
open("t.txt", "w:euc-jp", :undef => :replace, :replace => "") {|f|
- assert_raise(Encoding::InvalidByteSequence) { f.write invalid_utf8 }
+ assert_raise(Encoding::InvalidByteSequenceError) { f.write invalid_utf8 }
}
}
end
@@ -1613,10 +1613,10 @@ EOT
}
assert_equal("ab", File.read("t.txt"))
open("t.txt", "w:euc-jp:utf-8", :invalid => :replace) {|f|
- assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ assert_raise(Encoding::ConversionUndefinedError) { f.write "a\uFFFDb" }
}
open("t.txt", "w:euc-jp:utf-8", :invalid => :replace, :replace => "") {|f|
- assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ assert_raise(Encoding::ConversionUndefinedError) { f.write "a\uFFFDb" }
}
}
end
@@ -1633,10 +1633,10 @@ EOT
}
assert_equal("ab", File.read("t.txt"))
open("t.txt", "w:iso-2022-jp:utf-8", :invalid => :replace) {|f|
- assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ assert_raise(Encoding::ConversionUndefinedError) { f.write "a\uFFFDb" }
}
open("t.txt", "w:iso-2022-jp:utf-8", :invalid => :replace, :replace => "") {|f|
- assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ assert_raise(Encoding::ConversionUndefinedError) { f.write "a\uFFFDb" }
}
}
end
diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb
index a878227534..a1772f6408 100644
--- a/test/ruby/test_m17n.rb
+++ b/test/ruby/test_m17n.rb
@@ -146,17 +146,17 @@ class TestM17N < Test::Unit::TestCase
# tests start
def test_string_ascii_literal
- assert_encoding("US-ASCII", eval(a(%{""})).encoding)
- assert_encoding("US-ASCII", eval(a(%{"a"})).encoding)
+ assert_encoding("ASCII-8BIT", eval(a(%{""})).encoding)
+ assert_encoding("ASCII-8BIT", eval(a(%{"a"})).encoding)
end
def test_string_eucjp_literal
- assert_encoding("US-ASCII", eval(e(%{""})).encoding)
- assert_encoding("US-ASCII", eval(e(%{"a"})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{""})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{"a"})).encoding)
assert_encoding("EUC-JP", eval(e(%{"\xa1\xa1"})).encoding)
assert_encoding("EUC-JP", eval(e(%{"\\xa1\\xa1"})).encoding)
- assert_encoding("US-ASCII", eval(e(%{"\\x20"})).encoding)
- assert_encoding("US-ASCII", eval(e(%{"\\n"})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{"\\x20"})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{"\\n"})).encoding)
assert_encoding("EUC-JP", eval(e(%{"\\x80"})).encoding)
end
@@ -746,7 +746,7 @@ class TestM17N < Test::Unit::TestCase
#assert_raise(ArgumentError) { s("%c") % 0xc2a1 }
assert_strenc("\u{c2a1}", 'UTF-8', u("%c") % 0xc2a1)
assert_strenc("\u{c2}", 'UTF-8', u("%c") % 0xc2)
- assert_raise(EncodingCompatibilityError) {
+ assert_raise(Encoding::CompatibilityError) {
"%s%s" % [s("\xc2\xa1"), e("\xc2\xa1")]
}
end
@@ -866,22 +866,22 @@ class TestM17N < Test::Unit::TestCase
def test_str_aref_substr
assert_equal(a("\xa1\xc2"), a("\xc2\xa1\xc2\xa2\xc2\xa3")[a("\xa1\xc2")])
- assert_raise(EncodingCompatibilityError) { a("\xc2\xa1\xc2\xa2\xc2\xa3")[e("\xa1\xc2")] }
+ assert_raise(Encoding::CompatibilityError) { a("\xc2\xa1\xc2\xa2\xc2\xa3")[e("\xa1\xc2")] }
assert_equal(nil, e("\xc2\xa1\xc2\xa2\xc2\xa3")[e("\xa1\xc2")])
- assert_raise(EncodingCompatibilityError) { e("\xc2\xa1\xc2\xa2\xc2\xa3")[s("\xa1\xc2")] }
+ assert_raise(Encoding::CompatibilityError) { e("\xc2\xa1\xc2\xa2\xc2\xa3")[s("\xa1\xc2")] }
assert_equal(s("\xa1\xc2"), s("\xc2\xa1\xc2\xa2\xc2\xa3")[s("\xa1\xc2")])
- assert_raise(EncodingCompatibilityError) { s("\xc2\xa1\xc2\xa2\xc2\xa3")[u("\xa1\xc2")] }
+ assert_raise(Encoding::CompatibilityError) { s("\xc2\xa1\xc2\xa2\xc2\xa3")[u("\xa1\xc2")] }
assert_equal(nil, u("\xc2\xa1\xc2\xa2\xc2\xa3")[u("\xa1\xc2")])
- assert_raise(EncodingCompatibilityError) { u("\xc2\xa1\xc2\xa2\xc2\xa3")[a("\xa1\xc2")] }
+ assert_raise(Encoding::CompatibilityError) { u("\xc2\xa1\xc2\xa2\xc2\xa3")[a("\xa1\xc2")] }
assert_nil(e("\xa1\xa2\xa3\xa4")[e("\xa2\xa3")])
end
def test_aset
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s["\xb0\xa3"] = "foo"}
+ assert_raise(Encoding::CompatibilityError){s["\xb0\xa3"] = "foo"}
end
def test_str_center
@@ -917,13 +917,13 @@ class TestM17N < Test::Unit::TestCase
def test_count
assert_equal(0, e("\xa1\xa2").count("z"))
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s.count(a("\xa3\xb0"))}
+ assert_raise(Encoding::CompatibilityError){s.count(a("\xa3\xb0"))}
end
def test_delete
assert_equal(1, e("\xa1\xa2").delete("z").length)
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s.delete(a("\xa3\xb2"))}
+ assert_raise(Encoding::CompatibilityError){s.delete(a("\xa3\xb2"))}
a = "\u3042\u3044\u3046\u3042\u3044\u3046"
a.delete!("\u3042\u3044", "^\u3044")
@@ -942,7 +942,7 @@ class TestM17N < Test::Unit::TestCase
assert_nil(e("\xa1\xa2\xa3\xa4").index(e("\xa3")))
assert_nil(e("\xa1\xa2\xa3\xa4").rindex(e("\xa3")))
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s.rindex(a("\xb1\xa3"))}
+ assert_raise(Encoding::CompatibilityError){s.rindex(a("\xb1\xa3"))}
end
def test_next
@@ -985,7 +985,7 @@ class TestM17N < Test::Unit::TestCase
def test_upto
s1 = e("\xa1\xa2")
s2 = s("\xa1\xa2")
- assert_raise(EncodingCompatibilityError){s1.upto(s2) {|x| break }}
+ assert_raise(Encoding::CompatibilityError){s1.upto(s2) {|x| break }}
end
def test_casecmp
@@ -1005,12 +1005,12 @@ class TestM17N < Test::Unit::TestCase
end
def test_plus
- assert_raise(EncodingCompatibilityError){u("\xe3\x81\x82") + a("\xa1")}
+ assert_raise(Encoding::CompatibilityError){u("\xe3\x81\x82") + a("\xa1")}
end
def test_chomp
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s.chomp(s("\xa3\xb4"))}
+ assert_raise(Encoding::CompatibilityError){s.chomp(s("\xa3\xb4"))}
end
def test_gsub
@@ -1023,7 +1023,7 @@ class TestM17N < Test::Unit::TestCase
t = s.gsub(/b/, "\xa1\xa1".force_encoding("euc-jp"))
assert_equal(Encoding::ASCII_8BIT, s.encoding)
- assert_raise(EncodingCompatibilityError) {
+ assert_raise(Encoding::CompatibilityError) {
"abc".gsub(/[ac]/) {
$& == "a" ? "\xc2\xa1".force_encoding("euc-jp") :
"\xc2\xa1".force_encoding("utf-8")
@@ -1044,7 +1044,7 @@ class TestM17N < Test::Unit::TestCase
def test_each_line
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s.each_line(a("\xa3\xb1")) {|l| }}
+ assert_raise(Encoding::CompatibilityError){s.each_line(a("\xa3\xb1")) {|l| }}
s = e("\xa4\xa2\nfoo")
actual = []
@@ -1280,11 +1280,20 @@ class TestM17N < Test::Unit::TestCase
end
def test_compatible
- assert_raise(TypeError) {Encoding.compatible?("",0)}
+ assert_nil Encoding.compatible?("",0)
+ assert_equal(Encoding::UTF_8, Encoding.compatible?(Encoding::UTF_8, Encoding::UTF_8))
+ assert_equal(Encoding::UTF_8, Encoding.compatible?(Encoding::UTF_8, Encoding::US_ASCII))
+ assert_equal(Encoding::ASCII_8BIT,
+ Encoding.compatible?(Encoding::ASCII_8BIT, Encoding::US_ASCII))
+ assert_nil Encoding.compatible?(Encoding::UTF_8, Encoding::ASCII_8BIT)
end
def test_force_encoding
assert(("".center(1, "\x80".force_encoding("utf-8")); true),
"moved from btest/knownbug, [ruby-dev:33807]")
end
+
+ def test_combchar_codepoint
+ assert_equal([0x30BB, 0x309A], "\u30BB\u309A".codepoints.to_a)
+ end
end
diff --git a/test/ruby/test_m17n_comb.rb b/test/ruby/test_m17n_comb.rb
index 37b1a687a2..50fe8c2233 100644
--- a/test/ruby/test_m17n_comb.rb
+++ b/test/ruby/test_m17n_comb.rb
@@ -261,7 +261,7 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_plus
combination(STRINGS, STRINGS) {|s1, s2|
if s1.encoding != s2.encoding && !s1.ascii_only? && !s2.ascii_only?
- assert_raise(EncodingCompatibilityError) { s1 + s2 }
+ assert_raise(Encoding::CompatibilityError) { s1 + s2 }
else
t = enccall(s1, :+, s2)
assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
@@ -318,10 +318,11 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_eq
combination(STRINGS, STRINGS) {|s1, s2|
desc_eq = "#{encdump s1} == #{encdump s2}"
- if s1.ascii_only? && s2.ascii_only? && a(s1) == a(s2)
- assert(s1 == s2, desc_eq)
- assert(s1.eql?(s2), desc_eq)
- elsif s1.encoding == s2.encoding && a(s1) == a(s2)
+ if a(s1) == a(s2) and
+ (s1.ascii_only? && s2.ascii_only? or
+ s1.encoding == s2.encoding or
+ s1.encoding == (enc = Encoding.find("ASCII-8BIT")) or
+ s2.encoding == enc) then
assert(s1 == s2, desc_eq)
assert(!(s1 != s2))
assert_equal(0, s1 <=> s2)
@@ -344,7 +345,7 @@ class TestM17NComb < Test::Unit::TestCase
assert_equal(a(s), a(s1) + a(s2))
assert_str_enc_propagation(s, s1, s2)
else
- assert_raise(EncodingCompatibilityError) { s << s2 }
+ assert_raise(Encoding::CompatibilityError) { s << s2 }
end
}
end
@@ -396,7 +397,7 @@ class TestM17NComb < Test::Unit::TestCase
end
end
else
- assert_raise(EncodingCompatibilityError) { s1[s2] }
+ assert_raise(Encoding::CompatibilityError) { s1[s2] }
end
}
end
@@ -481,7 +482,7 @@ class TestM17NComb < Test::Unit::TestCase
end
end
else
- assert_raise(EncodingCompatibilityError) { t[i] = s2 }
+ assert_raise(Encoding::CompatibilityError) { t[i] = s2 }
end
}
}
@@ -513,7 +514,7 @@ class TestM17NComb < Test::Unit::TestCase
end
end
else
- assert_raise(EncodingCompatibilityError) { t[i,len] = s2 }
+ assert_raise(Encoding::CompatibilityError) { t[i,len] = s2 }
end
}
end
@@ -526,7 +527,7 @@ class TestM17NComb < Test::Unit::TestCase
!s2.ascii_only? ? s2.encoding : nil,
!s3.ascii_only? ? s3.encoding : nil].uniq.compact
if 1 < encs.length
- assert_raise(EncodingCompatibilityError, IndexError) { t[s2] = s3 }
+ assert_raise(Encoding::CompatibilityError, IndexError) { t[s2] = s3 }
else
if encs.empty?
encs = [
@@ -565,7 +566,7 @@ class TestM17NComb < Test::Unit::TestCase
end
end
else
- assert_raise(EncodingCompatibilityError, RangeError,
+ assert_raise(Encoding::CompatibilityError, RangeError,
"t=#{encdump(s1)};t[#{first}..#{last}]=#{encdump(s2)}") {
t[first..last] = s2
}
@@ -592,7 +593,7 @@ class TestM17NComb < Test::Unit::TestCase
end
end
else
- assert_raise(EncodingCompatibilityError, RangeError,
+ assert_raise(Encoding::CompatibilityError, RangeError,
"t=#{encdump(s1)};t[#{first}...#{last}]=#{encdump(s2)}") {
t[first...last] = s2
}
@@ -655,7 +656,7 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.center(width, s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.center(width, s2) }
next
end
t = enccall(s1, :center, width, s2)
@@ -676,7 +677,7 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.ljust(width, s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.ljust(width, s2) }
next
end
t = enccall(s1, :ljust, width, s2)
@@ -697,7 +698,7 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.rjust(width, s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.rjust(width, s2) }
next
end
t = enccall(s1, :rjust, width, s2)
@@ -711,7 +712,7 @@ class TestM17NComb < Test::Unit::TestCase
combination(STRINGS, STRINGS) {|s1, s2|
if !s1.ascii_only? && !s2.ascii_only? && !Encoding.compatible?(s1,s2)
if s1.bytesize > s2.bytesize
- assert_raise(EncodingCompatibilityError) { s1.chomp(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.chomp(s2) }
end
next
end
@@ -777,11 +778,11 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_count
combination(STRINGS, STRINGS) {|s1, s2|
if !s1.valid_encoding? || !s2.valid_encoding?
- assert_raise(ArgumentError, EncodingCompatibilityError) { s1.count(s2) }
+ assert_raise(ArgumentError, Encoding::CompatibilityError) { s1.count(s2) }
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.count(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.count(s2) }
next
end
n = enccall(s1, :count, s2)
@@ -809,11 +810,11 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !s1.valid_encoding? || !s2.valid_encoding?
- assert_raise(ArgumentError, EncodingCompatibilityError) { s1.delete(s2) }
+ assert_raise(ArgumentError, Encoding::CompatibilityError) { s1.delete(s2) }
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.delete(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.delete(s2) }
next
end
t = enccall(s1, :delete, s2)
@@ -855,11 +856,11 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_each_line
combination(STRINGS, STRINGS) {|s1, s2|
if !s1.valid_encoding? || !s2.valid_encoding?
- assert_raise(ArgumentError, EncodingCompatibilityError) { s1.each_line(s2) {} }
+ assert_raise(ArgumentError, Encoding::CompatibilityError) { s1.each_line(s2) {} }
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.each_line(s2) {} }
+ assert_raise(Encoding::CompatibilityError) { s1.each_line(s2) {} }
next
end
lines = []
@@ -908,9 +909,9 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_include?
combination(STRINGS, STRINGS) {|s1, s2|
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.include?(s2) }
- assert_raise(EncodingCompatibilityError) { s1.index(s2) }
- assert_raise(EncodingCompatibilityError) { s1.rindex(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.include?(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.index(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.rindex(s2) }
next
end
t = enccall(s1, :include?, s2)
@@ -941,7 +942,7 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_index
combination(STRINGS, STRINGS, -2..2) {|s1, s2, pos|
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.index(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.index(s2) }
next
end
t = enccall(s1, :index, s2, pos)
@@ -974,7 +975,7 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_rindex
combination(STRINGS, STRINGS, -2..2) {|s1, s2, pos|
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.rindex(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.rindex(s2) }
next
end
t = enccall(s1, :rindex, s2, pos)
@@ -1023,11 +1024,11 @@ class TestM17NComb < Test::Unit::TestCase
t2 = s1.dup
begin
t1[nth, 0] = s2
- rescue EncodingCompatibilityError, IndexError => e1
+ rescue Encoding::CompatibilityError, IndexError => e1
end
begin
t2.insert(nth, s2)
- rescue EncodingCompatibilityError, IndexError => e2
+ rescue Encoding::CompatibilityError, IndexError => e2
end
assert_equal(t1, t2, "t=#{encdump s1}; t.insert(#{nth},#{encdump s2}); t")
assert_equal(e1.class, e2.class, "begin #{encdump s1}.insert(#{nth},#{encdump s2}); rescue ArgumentError, IndexError => e; e end")
@@ -1041,7 +1042,7 @@ class TestM17NComb < Test::Unit::TestCase
t1.insert(nth, s2)
slen = s2.length
assert_equal(t1[nth-slen+1,slen], s2, "t=#{encdump s1}; t.insert(#{nth},#{encdump s2}); t")
- rescue EncodingCompatibilityError, IndexError => e
+ rescue Encoding::CompatibilityError, IndexError => e
end
}
end
@@ -1158,11 +1159,11 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_split
combination(STRINGS, STRINGS) {|s1, s2|
if !s2.valid_encoding?
- assert_raise(RegexpError) { s1.split(s2) }
+ assert_raise(ArgumentError, RegexpError) { s1.split(s2) }
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(ArgumentError) { s1.split(s2) }
+ assert_raise(ArgumentError, Encoding::CompatibilityError) { s1.split(s2) }
next
end
if !s1.valid_encoding?
@@ -1186,11 +1187,11 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_squeeze
combination(STRINGS, STRINGS) {|s1, s2|
if !s1.valid_encoding? || !s2.valid_encoding?
- assert_raise(ArgumentError, EncodingCompatibilityError, "#{encdump s1}.squeeze(#{encdump s2})") { s1.squeeze(s2) }
+ assert_raise(ArgumentError, Encoding::CompatibilityError, "#{encdump s1}.squeeze(#{encdump s2})") { s1.squeeze(s2) }
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.squeeze(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.squeeze(s2) }
next
end
t = enccall(s1, :squeeze, s2)
@@ -1280,7 +1281,7 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !str_enc_compatible?(s1, s2, s3)
- assert_raise(EncodingCompatibilityError, desc) { s1.tr(s2, s3) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.tr(s2, s3) }
next
end
if !s1.valid_encoding?
@@ -1309,11 +1310,11 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !s1.valid_encoding?
- assert_raise(ArgumentError, EncodingCompatibilityError, desc) { s1.tr_s(s2, s3) }
+ assert_raise(ArgumentError, Encoding::CompatibilityError, desc) { s1.tr_s(s2, s3) }
next
end
if !str_enc_compatible?(s1, s2, s3)
- assert_raise(EncodingCompatibilityError, desc) { s1.tr(s2, s3) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.tr(s2, s3) }
next
end
if s2.empty?
@@ -1423,7 +1424,7 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !str_enc_compatible?(s1.gsub(r2, ''), s3)
- assert_raise(EncodingCompatibilityError, desc) { doit.call }
+ assert_raise(Encoding::CompatibilityError, desc) { doit.call }
next
end
t = nil
@@ -1477,7 +1478,7 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !str_enc_compatible?(s1.gsub(r2, ''), s3)
- assert_raise(EncodingCompatibilityError, desc) { doit.call }
+ assert_raise(Encoding::CompatibilityError, desc) { doit.call }
next
end
t = ret = nil
@@ -1538,7 +1539,7 @@ class TestM17NComb < Test::Unit::TestCase
combination(STRINGS, STRINGS) {|s1, s2|
desc = "#{encdump s1}.end_with?(#{encdump s2})"
if !str_enc_compatible?(s1, s2)
- assert_raise(EncodingCompatibilityError, desc) { s1.end_with?(s2) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.end_with?(s2) }
next
end
if s1.length < s2.length
@@ -1557,7 +1558,7 @@ class TestM17NComb < Test::Unit::TestCase
combination(STRINGS, STRINGS) {|s1, s2|
desc = "#{encdump s1}.start_with?(#{encdump s2})"
if !str_enc_compatible?(s1, s2)
- assert_raise(EncodingCompatibilityError, desc) { s1.start_with?(s2) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.start_with?(s2) }
next
end
s1 = s1.dup.force_encoding("ASCII-8BIT")
@@ -1592,7 +1593,7 @@ class TestM17NComb < Test::Unit::TestCase
combination(STRINGS, STRINGS) {|s1, s2|
desc = "#{encdump s1}.partition(#{encdump s2})"
if !str_enc_compatible?(s1, s2)
- assert_raise(EncodingCompatibilityError, desc) { s1.partition(s2) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.partition(s2) }
next
end
i = enccall(s1, :index, s2)
@@ -1608,7 +1609,7 @@ class TestM17NComb < Test::Unit::TestCase
combination(STRINGS, STRINGS) {|s1, s2|
desc = "#{encdump s1}.rpartition(#{encdump s2})"
if !str_enc_compatible?(s1, s2)
- assert_raise(EncodingCompatibilityError, desc) { s1.rpartition(s2) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.rpartition(s2) }
next
end
i = enccall(s1, :rindex, s2)
diff --git a/test/ruby/test_math.rb b/test/ruby/test_math.rb
index 55f354664c..d4dbf9dbf0 100644
--- a/test/ruby/test_math.rb
+++ b/test/ruby/test_math.rb
@@ -113,6 +113,7 @@ class TestMath < Test::Unit::TestCase
assert_equal(1.0/0, Math.log(1.0/0))
assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log(0) }
assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log(-1) }
+ assert_raise(TypeError) { Math.log(1,nil) }
end
def test_log2
diff --git a/test/ruby/test_mixed_unicode_escapes.rb b/test/ruby/test_mixed_unicode_escapes.rb
index f274ae7090..982b57e286 100644
--- a/test/ruby/test_mixed_unicode_escapes.rb
+++ b/test/ruby/test_mixed_unicode_escapes.rb
@@ -1,4 +1,4 @@
-# -*- coding: sjis -*-
+# -*- coding: cp932 -*-
# This test is in a differnt file than TestUnicodeEscapes
# So that we can have a different coding comment above
@@ -18,8 +18,8 @@ class TestMixedUnicodeEscape < Test::Unit::TestCase
# String interpolation turns into an expression and we get
# a different kind of error, but we still can't mix these
- assert_raise(EncodingCompatibilityError) { eval %q("\u{1234}#{nil}")}
- assert_raise(EncodingCompatibilityError) { eval %q("#{nil}\u1234")}
+ assert_raise(Encoding::CompatibilityError) { eval %q("\u{1234}#{nil}")}
+ assert_raise(Encoding::CompatibilityError) { eval %q("#{nil}\u1234")}
end
end
diff --git a/test/ruby/test_numeric.rb b/test/ruby/test_numeric.rb
index 3db054fdae..0dd7b2e99c 100644
--- a/test/ruby/test_numeric.rb
+++ b/test/ruby/test_numeric.rb
@@ -72,8 +72,8 @@ class TestNumeric < Test::Unit::TestCase
end
end
- def test_scalar_p
- assert(Numeric.new.scalar?)
+ def test_real_p
+ assert(Numeric.new.real?)
end
def test_integer_p
diff --git a/test/ruby/test_prec.rb b/test/ruby/test_prec.rb
deleted file mode 100644
index d872242c11..0000000000
--- a/test/ruby/test_prec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'test/unit'
-
-class TestPrecision < Test::Unit::TestCase
- def test_prec_i
- assert_same(1, 1.0.prec(Integer))
- assert_same(1, 1.0.prec_i)
- assert_same(1, Integer.induced_from(1.0))
- end
-
- def test_prec_f
- assert_equal(1.0, 1.prec(Float))
- assert_equal(1.0, 1.prec_f)
- assert_equal(1.0, Float.induced_from(1))
- end
-
- def test_induced_from
- m = Module.new
- m.instance_eval { include(Precision) }
- assert_raise(TypeError) { m.induced_from(0) }
- end
-end
diff --git a/test/ruby/test_rational.rb b/test/ruby/test_rational.rb
index 1d280e4361..7f75584e0e 100644
--- a/test/ruby/test_rational.rb
+++ b/test/ruby/test_rational.rb
@@ -4,6 +4,14 @@ class RationalSub < Rational; end
class Rational_Test < Test::Unit::TestCase
+ def setup
+ @complex = defined?(Complex)
+ if @complex
+ @keiju = Complex.instance_variable_get('@RCS_ID')
+ end
+ @unify = defined?(Rational::Unify)
+ end
+
def test_ratsub
c = RationalSub.__send__(:new, 1)
cc = RationalSub.__send__(:convert, 1)
@@ -11,7 +19,7 @@ class Rational_Test < Test::Unit::TestCase
assert_kind_of(Numeric, c)
assert_kind_of(Numeric, cc)
- if defined?(RationalSub::Unify)
+ if @unify
assert_instance_of(Fixnum, c)
assert_instance_of(Fixnum, cc)
else
@@ -41,7 +49,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(true, c.eql?(c2))
assert_equal(false, c.eql?(c3))
- if defined?(Rational::Unify)
+ if @unify
assert_equal(true, c.eql?(0))
else
assert_equal(false, c.eql?(0))
@@ -67,7 +75,7 @@ class Rational_Test < Test::Unit::TestCase
def test_freeze
c = Rational(1)
c.freeze
- unless defined?(Rational::Unify)
+ unless @unify
assert_equal(true, c.frozen?)
end
assert_instance_of(String, c.to_s)
@@ -108,7 +116,7 @@ class Rational_Test < Test::Unit::TestCase
=begin
def test_reduce
- if defined?(Rational::Unify)
+ if @unify
assert_instance_of(Fixnum, Rational.__send__(:reduce, 2,1))
else
assert_instance_of(Rational, Rational.__send__(:reduce, 2,1))
@@ -138,7 +146,7 @@ class Rational_Test < Test::Unit::TestCase
=end
def test_new
- if defined?(Rational::Unify)
+ if @unify
assert_instance_of(Fixnum, Rational.__send__(:new, 2,1))
else
assert_instance_of(Rational, Rational.__send__(:new, 2,1))
@@ -164,7 +172,7 @@ class Rational_Test < Test::Unit::TestCase
assert_raise(ArgumentError){Rational.__send__(:new, nil)}
=begin
assert_raise(ArgumentError){Rational.__send__(:new, Rational(1))}
- if defined?(Complex)
+ if @complex
assert_raise(ArgumentError){Rational.__send__(:new, Complex(1))}
end
=end
@@ -199,6 +207,17 @@ class Rational_Test < Test::Unit::TestCase
c = Rational(Rational(1,2),Rational(1,2))
assert_equal(Rational.__send__(:new, 1), c)
+ if @complex && !@keiju
+ c = Rational(Complex(1,2),2)
+ assert_equal(Complex.__send__(:new, Rational(1,2),1), c)
+
+ c = Rational(2,Complex(1,2))
+ assert_equal(Complex.__send__(:new, Rational(2,5),Rational(-4,5)), c)
+
+ c = Rational(Complex(1,2),Complex(1,2))
+ assert_equal(Rational.__send__(:new, 1), c)
+ end
+
assert_equal(Rational.__send__(:new, 3),Rational(3))
assert_equal(Rational.__send__(:new, 1),Rational(3,3))
assert_equal(3.3.to_r,Rational(3.3))
@@ -248,8 +267,7 @@ class Rational_Test < Test::Unit::TestCase
def test_attr2
c = Rational(1)
- if defined?(Rational::Unify)
- assert_equal(true, c.scalar?)
+ if @unify
=begin
assert_equal(true, c.finite?)
assert_equal(false, c.infinite?)
@@ -257,13 +275,14 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(true, c.integer?)
assert_equal(false, c.float?)
assert_equal(true, c.rational?)
+=end
assert_equal(true, c.real?)
+=begin
assert_equal(false, c.complex?)
assert_equal(true, c.exact?)
assert_equal(false, c.inexact?)
=end
else
- assert_equal(true, c.scalar?)
=begin
assert_equal(true, c.finite?)
assert_equal(false, c.infinite?)
@@ -271,7 +290,9 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(false, c.integer?)
assert_equal(false, c.float?)
assert_equal(true, c.rational?)
+=end
assert_equal(true, c.real?)
+=begin
assert_equal(false, c.complex?)
assert_equal(true, c.exact?)
assert_equal(false, c.inexact?)
@@ -406,7 +427,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(-2, (-c).div(c2))
assert_equal(1, (-c).div(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -441,7 +462,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(Rational(99,100), (-c).modulo(c2))
assert_equal(Rational(-101,100), (-c).modulo(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -476,7 +497,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal([-2, Rational(99,100)], (-c).divmod(c2))
assert_equal([1, Rational(-101,100)], (-c).divmod(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -512,7 +533,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(-1, (-c).quot(c2))
assert_equal(1, (-c).quot(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -548,7 +569,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(Rational(-101,100), (-c).remainder(c2))
assert_equal(Rational(-101,100), (-c).remainder(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -584,7 +605,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal([-1, Rational(-101,100)], (-c).quotrem(c2))
assert_equal([1, Rational(-101,100)], (-c).quotrem(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -641,7 +662,7 @@ class Rational_Test < Test::Unit::TestCase
# p ** p
x = 2 ** Rational(2)
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -649,7 +670,7 @@ class Rational_Test < Test::Unit::TestCase
x = Rational(2) ** 2
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -657,7 +678,7 @@ class Rational_Test < Test::Unit::TestCase
x = Rational(2) ** Rational(2)
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -666,7 +687,7 @@ class Rational_Test < Test::Unit::TestCase
# -p ** p
x = (-2) ** Rational(2)
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -674,7 +695,7 @@ class Rational_Test < Test::Unit::TestCase
x = Rational(-2) ** 2
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -682,7 +703,7 @@ class Rational_Test < Test::Unit::TestCase
x = Rational(-2) ** Rational(2)
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -726,7 +747,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(1, x.numerator)
assert_equal(4, x.denominator)
- unless defined?(Rational::Unify) # maybe bug mathn
+ unless @unify # maybe bug mathn
assert_raise(ZeroDivisionError){0 ** -1}
end
end
@@ -787,7 +808,7 @@ class Rational_Test < Test::Unit::TestCase
end
def test_unify
- if defined?(Rational::Unify)
+ if @unify
assert_instance_of(Fixnum, Rational(1,2) + Rational(1,2))
assert_instance_of(Fixnum, Rational(1,2) - Rational(1,2))
assert_instance_of(Fixnum, Rational(1,2) * 2)
@@ -801,7 +822,7 @@ class Rational_Test < Test::Unit::TestCase
def test_math
assert_equal(Rational(1,2), Rational(1,2).abs)
assert_equal(Rational(1,2), Rational(-1,2).abs)
- if defined?(Complex) && !Complex.instance_variable_get('@RCS_ID')
+ if @complex && !@keiju
assert_equal(Rational(1,2), Rational(1,2).magnitude)
assert_equal(Rational(1,2), Rational(-1,2).magnitude)
end
@@ -831,7 +852,7 @@ class Rational_Test < Test::Unit::TestCase
assert_instance_of(String, c.to_s)
assert_equal('1/2', c.to_s)
- if defined?(Rational::Unify)
+ if @unify
assert_equal('0', Rational(0,2).to_s)
assert_equal('0', Rational(0,-2).to_s)
else
@@ -854,10 +875,12 @@ class Rational_Test < Test::Unit::TestCase
def test_marshal
c = Rational(1,2)
+ c.instance_eval{@ivar = 9}
s = Marshal.dump(c)
c2 = Marshal.load(s)
assert_equal(c, c2)
+ assert_equal(9, c2.instance_variable_get(:@ivar))
assert_instance_of(Rational, c2)
assert_raise(ZeroDivisionError){
@@ -987,8 +1010,8 @@ class Rational_Test < Test::Unit::TestCase
end
def test_to_c
- if defined?(Complex) && !Complex.instance_variable_get('@RCS_ID')
- if defined?(Rational::Unify)
+ if @complex && !@keiju
+ if @unify
assert_equal(Rational(3,2), Rational(3,2).to_c)
assert_equal(Rational(3,2), Complex(Rational(3,2)))
else
@@ -1015,8 +1038,8 @@ class Rational_Test < Test::Unit::TestCase
c = Rational(1,2).to_r
assert_equal([1,2] , [c.numerator, c.denominator])
- if defined?(Complex)
- if Complex.instance_variable_get('@RCS_ID')
+ if @complex
+ if @keiju
assert_raise(NoMethodError){Complex(1,2).to_r}
else
assert_raise(RangeError){Complex(1,2).to_r}
@@ -1024,16 +1047,6 @@ class Rational_Test < Test::Unit::TestCase
end
end
- def test_prec
- assert_equal(true, Rational < Precision)
-
- c = Rational(3,2)
-
- assert_eql(1, c.prec(Integer))
- assert_eql(1.5, c.prec(Float))
- assert_eql(c, c.prec(Rational))
- end
-
def test_gcdlcm
assert_equal(7, 91.gcd(-49))
assert_equal(5, 5.gcd(0))
@@ -1052,8 +1065,8 @@ class Rational_Test < Test::Unit::TestCase
end
def test_supp
- assert_equal(true, 1.scalar?)
- assert_equal(true, 1.1.scalar?)
+ assert_equal(true, 1.real?)
+ assert_equal(true, 1.1.real?)
assert_equal(1, 1.numerator)
assert_equal(9, 9.numerator)
@@ -1089,7 +1102,7 @@ class Rational_Test < Test::Unit::TestCase
end
def test_fixed_bug
- if defined?(Rational::Unify)
+ if @unify
assert_instance_of(Fixnum, Rational(1,2) ** 0) # mathn's bug
end
diff --git a/test/ruby/test_transcode.rb b/test/ruby/test_transcode.rb
index 5abeed88ee..389deb48b1 100644
--- a/test/ruby/test_transcode.rb
+++ b/test/ruby/test_transcode.rb
@@ -21,13 +21,13 @@ class TestTranscode < Test::Unit::TestCase
def test_errors
assert_raise(ArgumentError) { 'abc'.encode }
assert_raise(ArgumentError) { 'abc'.encode! }
- assert_raise(Encoding::NoConverter) { 'abc'.encode('foo', 'bar') }
- assert_raise(Encoding::NoConverter) { 'abc'.encode!('foo', 'bar') }
- assert_raise(Encoding::NoConverter) { 'abc'.force_encoding('utf-8').encode('foo') }
- assert_raise(Encoding::NoConverter) { 'abc'.force_encoding('utf-8').encode!('foo') }
- assert_raise(Encoding::ConversionUndefined) { "\x80".encode('utf-8','ASCII-8BIT') }
- assert_raise(Encoding::InvalidByteSequence) { "\x80".encode('utf-8','US-ASCII') }
- assert_raise(Encoding::ConversionUndefined) { "\xA5".encode('utf-8','iso-8859-3') }
+ assert_raise(Encoding::NoConverterError) { 'abc'.encode('foo', 'bar') }
+ assert_raise(Encoding::NoConverterError) { 'abc'.encode!('foo', 'bar') }
+ assert_raise(Encoding::NoConverterError) { 'abc'.force_encoding('utf-8').encode('foo') }
+ assert_raise(Encoding::NoConverterError) { 'abc'.force_encoding('utf-8').encode!('foo') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\x80".encode('utf-8','ASCII-8BIT') }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x80".encode('utf-8','US-ASCII') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA5".encode('utf-8','iso-8859-3') }
end
def test_arguments
@@ -355,24 +355,24 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u71FC", "\xE0\x9E", 'shift_jis') # 燼
check_both_ways("\u71F9", "\xE0\x9F", 'shift_jis') # 燹
check_both_ways("\u73F1", "\xE0\xFC", 'shift_jis') # 珱
- assert_raise(Encoding::ConversionUndefined) { "\xEF\x40".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xEF\x7E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xEF\x80".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xEF\x9E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xEF\x9F".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xEF\xFC".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\x40".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\x7E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\x80".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\x9E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\x9F".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\xFC".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xEF\x40".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xEF\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xEF\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xEF\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xEF\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xEF\xFC".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xF0\x40".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xF0\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xF0\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xF0\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xF0\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xF0\xFC".encode("utf-8", 'shift_jis') }
#check_both_ways("\u9ADC", "\xFC\x40", 'shift_jis') # 髜 (IBM extended)
- assert_raise(Encoding::ConversionUndefined) { "\xFC\x7E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xFC\x80".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xFC\x9E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xFC\x9F".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xFC\xFC".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xFC\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xFC\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xFC\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xFC\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xFC\xFC".encode("utf-8", 'shift_jis') }
check_both_ways("\u677E\u672C\u884C\u5F18", "\x8f\xbc\x96\x7b\x8d\x73\x8d\x4f", 'shift_jis') # 松本行弘
check_both_ways("\u9752\u5C71\u5B66\u9662\u5927\u5B66", "\x90\xC2\x8E\x52\x8A\x77\x89\x40\x91\xE5\x8A\x77", 'shift_jis') # 青山学院大学
check_both_ways("\u795E\u6797\u7FA9\u535A", "\x90\x5F\x97\xD1\x8B\x60\x94\x8E", 'shift_jis') # 神林義博
@@ -392,34 +392,34 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u00F7", "\xA1\xE0", 'euc-jp') # ÷
check_both_ways("\u25C7", "\xA1\xFE", 'euc-jp') # ◇
check_both_ways("\u25C6", "\xA2\xA1", 'euc-jp') # ◆
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xAF".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xB9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xC2".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xC9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xD1".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xDB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xEB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xF1".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xFA".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xFD".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA2\xAF".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA2\xB9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA2\xC2".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA2\xC9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA2\xD1".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA2\xDB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA2\xEB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA2\xF1".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA2\xFA".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA2\xFD".encode("utf-8", 'euc-jp') }
check_both_ways("\u25EF", "\xA2\xFE", 'euc-jp') # ◯
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xAF".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xBA".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xC0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xDB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xE0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xFB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA4\xF4".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA5\xF7".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA6\xB9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA6\xC0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA6\xD9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA7\xC2".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA7\xD0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA7\xF2".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA8\xC1".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xCF\xD4".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xCF\xFE".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA3\xAF".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA3\xBA".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA3\xC0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA3\xDB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA3\xE0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA3\xFB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA4\xF4".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA5\xF7".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA6\xB9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA6\xC0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA6\xD9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA7\xC2".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA7\xD0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA7\xF2".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xA8\xC1".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xCF\xD4".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xCF\xFE".encode("utf-8", 'euc-jp') }
check_both_ways("\u6A97", "\xDD\xA1", 'euc-jp') # 檗
check_both_ways("\u6BEF", "\xDD\xDF", 'euc-jp') # 毯
check_both_ways("\u9EBE", "\xDD\xE0", 'euc-jp') # 麾
@@ -432,7 +432,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u71FC", "\xDF\xFE", 'euc-jp') # 燼
check_both_ways("\u71F9", "\xE0\xA1", 'euc-jp') # 燹
check_both_ways("\u73F1", "\xE0\xFE", 'euc-jp') # 珱
- assert_raise(Encoding::ConversionUndefined) { "\xF4\xA7".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xF4\xA7".encode("utf-8", 'euc-jp') }
#check_both_ways("\u9ADC", "\xFC\xE3", 'euc-jp') # 髜 (IBM extended)
check_both_ways("\u677E\u672C\u884C\u5F18", "\xBE\xBE\xCB\xDC\xB9\xD4\xB9\xB0", 'euc-jp') # 松本行弘
@@ -491,33 +491,33 @@ class TestTranscode < Test::Unit::TestCase
end
def test_eucjp_sjis_undef
- assert_raise(Encoding::ConversionUndefined) { "\x8e\xe0".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\x8e\xfe".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\x8f\xa1\xa1".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\x8f\xa1\xfe".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\x8f\xfe\xa1".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\x8f\xfe\xfe".encode("Shift_JIS", "EUC-JP") }
-
- assert_raise(Encoding::ConversionUndefined) { "\xf0\x40".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xf0\x7e".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xf0\x80".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xf0\xfc".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xfc\x40".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xfc\x7e".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xfc\x80".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xfc\xfc".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\x8e\xe0".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\x8e\xfe".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\x8f\xa1\xa1".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\x8f\xa1\xfe".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\x8f\xfe\xa1".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\x8f\xfe\xfe".encode("Shift_JIS", "EUC-JP") }
+
+ assert_raise(Encoding::ConversionUndefinedError) { "\xf0\x40".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xf0\x7e".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xf0\x80".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xf0\xfc".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xfc\x40".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xfc\x7e".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xfc\x80".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\xfc\xfc".encode("EUC-JP", "Shift_JIS") }
end
def test_iso_2022_jp
- assert_raise(Encoding::InvalidByteSequence) { "\x1b(A".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x1b$(A".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x1b$C".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x0e".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x80".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x1b$(Dd!\x1b(B".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::ConversionUndefined) { "\u9299".encode("iso-2022-jp") }
- assert_raise(Encoding::ConversionUndefined) { "\uff71\uff72\uff73\uff74\uff75".encode("iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x1b(I12345\x1b(B".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b(A".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$(A".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$C".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x0e".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x80".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$(Dd!\x1b(B".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u9299".encode("iso-2022-jp") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\uff71\uff72\uff73\uff74\uff75".encode("iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b(I12345\x1b(B".encode("utf-8", "iso-2022-jp") }
assert_equal("\xA1\xA1".force_encoding("euc-jp"),
"\e$B!!\e(B".encode("EUC-JP", "ISO-2022-JP"))
assert_equal("\e$B!!\e(B".force_encoding("ISO-2022-JP"),
@@ -550,11 +550,11 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("\u005C", "\e(J\x5C\e(B".encode("UTF-8", "ISO-2022-JP"))
assert_equal("\u005C", "\x5C".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
assert_equal("\u005C", "\e(J\x5C\e(B".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
- assert_raise(Encoding::ConversionUndefined) { "\u00A5".encode("Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\u00A5".encode("Windows-31J") }
- assert_raise(Encoding::ConversionUndefined) { "\u00A5".encode("EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\u00A5".encode("eucJP-ms") }
- assert_raise(Encoding::ConversionUndefined) { "\u00A5".encode("CP51932") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u00A5".encode("Shift_JIS") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u00A5".encode("Windows-31J") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u00A5".encode("EUC-JP") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u00A5".encode("eucJP-ms") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u00A5".encode("CP51932") }
# FULLWIDTH REVERSE SOLIDUS
check_both_ways("\uFF3C", "\x81\x5F", "Shift_JIS")
@@ -575,11 +575,17 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("\u007E", "\e(J\x7E\e(B".encode("UTF-8", "ISO-2022-JP"))
assert_equal("\u007E", "\x7E".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
assert_equal("\u007E", "\e(J\x7E\e(B".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
- assert_raise(Encoding::ConversionUndefined) { "\u203E".encode("Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\u203E".encode("Windows-31J") }
- assert_raise(Encoding::ConversionUndefined) { "\u203E".encode("EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\u203E".encode("eucJP-ms") }
- assert_raise(Encoding::ConversionUndefined) { "\u203E".encode("CP51932") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u203E".encode("Shift_JIS") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u203E".encode("Windows-31J") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u203E".encode("EUC-JP") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u203E".encode("eucJP-ms") }
+ assert_raise(Encoding::ConversionUndefinedError) { "\u203E".encode("CP51932") }
end
+ def test_nothing_changed
+ a = "James".force_encoding("US-ASCII")
+ b = a.encode("Shift_JIS")
+ assert_equal(Encoding::US_ASCII, a.encoding)
+ assert_equal(Encoding::Shift_JIS, b.encoding)
+ end
end
diff --git a/transcode.c b/transcode.c
index 4d1107ddc4..b82729cb5b 100644
--- a/transcode.c
+++ b/transcode.c
@@ -14,9 +14,9 @@
#include "transcode_data.h"
#include <ctype.h>
-VALUE rb_eConversionUndefined;
-VALUE rb_eInvalidByteSequence;
-VALUE rb_eNoConverter;
+VALUE rb_eConversionUndefinedError;
+VALUE rb_eInvalidByteSequenceError;
+VALUE rb_eNoConverterError;
VALUE rb_cEncodingConverter;
@@ -52,6 +52,7 @@ typedef struct rb_transcoding {
unsigned int next_table;
VALUE next_info;
unsigned char next_byte;
+ unsigned int output_index;
int recognized_len; /* already interpreted */
int readagain_len; /* not yet interpreted */
@@ -80,6 +81,10 @@ typedef struct rb_transcoding {
((tc)->transcoder->max_output <= sizeof((tc)->writebuf.ary) ? \
(tc)->writebuf.ary : \
(tc)->writebuf.ptr)
+#define TRANSCODING_WRITEBUF_SIZE(tc) \
+ ((tc)->transcoder->max_output <= sizeof((tc)->writebuf.ary) ? \
+ sizeof((tc)->writebuf.ary) : \
+ (tc)->transcoder->max_output)
#define TRANSCODING_STATE_EMBED_MAX sizeof(union rb_transcoding_state_t)
#define TRANSCODING_STATE(tc) \
((tc)->transcoder->state_size <= sizeof((tc)->state) ? \
@@ -580,10 +585,10 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
SUSPEND_OBUF(19); *out_p++ = getBT3(next_info);
continue;
case STR1:
- next_byte = 0; /* index */
- while (next_byte < BYTE_ADDR(STR1_BYTEINDEX(next_info))[0]) {
- SUSPEND_OBUF(28); *out_p++ = BYTE_ADDR(STR1_BYTEINDEX(next_info))[1+next_byte];
- next_byte++;
+ tc->output_index = 0;
+ while (tc->output_index < STR1_LENGTH(BYTE_ADDR(STR1_BYTEINDEX(next_info)))) {
+ SUSPEND_OBUF(28); *out_p++ = BYTE_ADDR(STR1_BYTEINDEX(next_info))[1+tc->output_index];
+ tc->output_index++;
}
continue;
case FUNii:
@@ -600,9 +605,12 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
case FUNio:
SUSPEND_OBUF(13);
if (tr->max_output <= out_stop - out_p)
- out_p += (VALUE)(*tr->func_io)(TRANSCODING_STATE(tc), next_info, out_p);
+ out_p += tr->func_io(TRANSCODING_STATE(tc),
+ next_info, out_p, out_stop - out_p);
else {
- writebuf_len = (VALUE)(*tr->func_io)(TRANSCODING_STATE(tc), next_info, TRANSCODING_WRITEBUF(tc));
+ writebuf_len = tr->func_io(TRANSCODING_STATE(tc),
+ next_info,
+ TRANSCODING_WRITEBUF(tc), TRANSCODING_WRITEBUF_SIZE(tc));
writebuf_off = 0;
while (writebuf_off < writebuf_len) {
SUSPEND_OBUF(20);
@@ -617,11 +625,15 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
SUSPEND_OBUF(14);
if (tr->max_output <= out_stop - out_p) {
char_start = transcode_char_start(tc, *in_pos, inchar_start, in_p, &char_len);
- out_p += (VALUE)(*tr->func_so)(TRANSCODING_STATE(tc), char_start, (size_t)char_len, out_p);
+ out_p += tr->func_so(TRANSCODING_STATE(tc),
+ char_start, (size_t)char_len,
+ out_p, out_stop - out_p);
}
else {
char_start = transcode_char_start(tc, *in_pos, inchar_start, in_p, &char_len);
- writebuf_len = (VALUE)(*tr->func_so)(TRANSCODING_STATE(tc), char_start, (size_t)char_len, TRANSCODING_WRITEBUF(tc));
+ writebuf_len = tr->func_so(TRANSCODING_STATE(tc),
+ char_start, (size_t)char_len,
+ TRANSCODING_WRITEBUF(tc), TRANSCODING_WRITEBUF_SIZE(tc));
writebuf_off = 0;
while (writebuf_off < writebuf_len) {
SUSPEND_OBUF(22);
@@ -675,10 +687,12 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
if (tr->finish_func) {
SUSPEND_OBUF(4);
if (tr->max_output <= out_stop - out_p) {
- out_p += tr->finish_func(TRANSCODING_STATE(tc), out_p);
+ out_p += tr->finish_func(TRANSCODING_STATE(tc),
+ out_p, out_stop - out_p);
}
else {
- writebuf_len = tr->finish_func(TRANSCODING_STATE(tc), TRANSCODING_WRITEBUF(tc));
+ writebuf_len = tr->finish_func(TRANSCODING_STATE(tc),
+ TRANSCODING_WRITEBUF(tc), TRANSCODING_WRITEBUF_SIZE(tc));
writebuf_off = 0;
while (writebuf_off < writebuf_len) {
SUSPEND_OBUF(23);
@@ -1946,7 +1960,7 @@ rb_econv_open_exc(const char *sname, const char *dname, int ecflags)
mesg = rb_str_new_cstr("code converter not found (");
econv_description(sname, dname, ecflags, mesg);
rb_str_cat2(mesg, ")");
- exc = rb_exc_new3(rb_eNoConverter, mesg);
+ exc = rb_exc_new3(rb_eNoConverterError, mesg);
return exc;
}
@@ -1983,7 +1997,7 @@ make_econv_exception(rb_econv_t *ec)
ec->last_error.source_encoding);
}
- exc = rb_exc_new3(rb_eInvalidByteSequence, mesg);
+ exc = rb_exc_new3(rb_eInvalidByteSequenceError, mesg);
rb_ivar_set(exc, rb_intern("error_bytes"), bytes);
rb_ivar_set(exc, rb_intern("readagain_bytes"), bytes2);
rb_ivar_set(exc, rb_intern("incomplete_input"), ec->last_error.result == econv_incomplete_input ? Qtrue : Qfalse);
@@ -2009,7 +2023,7 @@ make_econv_exception(rb_econv_t *ec)
StringValueCStr(dumped),
ec->last_error.source_encoding,
ec->last_error.destination_encoding);
- exc = rb_exc_new3(rb_eConversionUndefined, mesg);
+ exc = rb_exc_new3(rb_eConversionUndefinedError, mesg);
idx = rb_enc_find_index(ec->last_error.source_encoding);
if (0 <= idx)
rb_enc_associate_index(bytes, idx);
@@ -2274,16 +2288,18 @@ econv_opts(VALUE opt)
v = rb_hash_aref(opt, sym_xml);
if (!NIL_P(v)) {
- v = rb_convert_type(v, T_SYMBOL, "Symbol", "to_sym");
if (v==sym_text) {
ecflags |= ECONV_XML_TEXT_DECORATOR|ECONV_UNDEF_HEX_CHARREF;
}
else if (v==sym_attr) {
ecflags |= ECONV_XML_ATTR_CONTENT_DECORATOR|ECONV_XML_ATTR_QUOTE_DECORATOR|ECONV_UNDEF_HEX_CHARREF;
}
- else {
+ else if (TYPE(v) == T_SYMBOL) {
rb_raise(rb_eArgError, "unexpected value for xml option: %s", rb_id2name(SYM2ID(v)));
}
+ else {
+ rb_raise(rb_eArgError, "unexpected value for xml option");
+ }
}
v = rb_hash_aref(opt, sym_universal_newline);
@@ -2570,7 +2586,12 @@ str_encode(int argc, VALUE *argv, VALUE str)
int encidx = str_transcode(argc, argv, &newstr);
if (encidx < 0) return rb_str_dup(str);
- RBASIC(newstr)->klass = rb_obj_class(str);
+ if (newstr == str) {
+ newstr = rb_str_dup(str);
+ }
+ else {
+ RBASIC(newstr)->klass = rb_obj_class(str);
+ }
return str_encode_associate(newstr, encidx);
}
@@ -3361,8 +3382,8 @@ econv_primitive_convert(int argc, VALUE *argv, VALUE self)
* puts ec.finish.dump #=> "\e(B".force_encoding("ISO-2022-JP")
*
* If a conversion error occur,
- * Encoding::ConversionUndefined or
- * Encoding::InvalidByteSequence is raised.
+ * Encoding::ConversionUndefinedError or
+ * Encoding::InvalidByteSequenceError is raised.
*
*/
static VALUE
@@ -3614,7 +3635,7 @@ econv_insert_output(VALUE self, VALUE string)
* some bytes are buffered to be converted later.
* The latter bytes can be put back.
* It can be observed by
- * Encoding::InvalidByteSequence#readagain_bytes and
+ * Encoding::InvalidByteSequenceError#readagain_bytes and
* Encoding::Converter#primitive_errinfo.
*
* ec = Encoding::Converter.new("utf-16le", "iso-8859-1")
@@ -3663,14 +3684,14 @@ econv_putback(int argc, VALUE *argv, VALUE self)
* It returns nil if the last conversion is not an error.
*
* "error" means that
- * Encoding::InvalidByteSequence and Encoding::ConversionUndefined for
+ * Encoding::InvalidByteSequenceError and Encoding::ConversionUndefinedError for
* Encoding::Converter#convert and
* :invalid_byte_sequence, :incomplete_input and :undefined_conversion for
* Encoding::Converter#primitive_convert.
*
* ec = Encoding::Converter.new("utf-8", "iso-8859-1")
* p ec.primitive_convert(src="\xf1abcd", dst="") #=> :invalid_byte_sequence
- * p ec.last_error #=> #<Encoding::InvalidByteSequence: "\xF1" followed by "a" on UTF-8>
+ * p ec.last_error #=> #<Encoding::InvalidByteSequenceError: "\xF1" followed by "a" on UTF-8>
* p ec.primitive_convert(src, dst, nil, 1) #=> :destination_buffer_full
* p ec.last_error #=> nil
*
@@ -3708,7 +3729,7 @@ econv_get_replacement(VALUE self)
ret = make_replacement(ec);
if (ret == -1) {
- rb_raise(rb_eConversionUndefined, "replacement character setup failed");
+ rb_raise(rb_eConversionUndefinedError, "replacement character setup failed");
}
enc = rb_enc_find(ec->replacement_enc);
@@ -3742,8 +3763,8 @@ econv_set_replacement(VALUE self, VALUE arg)
rb_enc_name(enc));
if (ret == -1) {
- /* xxx: rb_eInvalidByteSequence? */
- rb_raise(rb_eConversionUndefined, "replacement character setup failed");
+ /* xxx: rb_eInvalidByteSequenceError? */
+ rb_raise(rb_eConversionUndefinedError, "replacement character setup failed");
}
return arg;
@@ -3784,7 +3805,7 @@ ecerr_source_encoding_name(VALUE self)
* ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") # ISO-8859-1 -> UTF-8 -> EUC-JP
* begin
* ec.convert("\xa0") # NO-BREAK SPACE, which is available in UTF-8 but not in EUC-JP.
- * rescue Encoding::ConversionUndefined
+ * rescue Encoding::ConversionUndefinedError
* p $!.source_encoding #=> #<Encoding:UTF-8>
* p $!.destination_encoding #=> #<Encoding:EUC-JP>
* p $!.source_encoding_name #=> "UTF-8"
@@ -3826,12 +3847,12 @@ ecerr_destination_encoding(VALUE self)
* call-seq:
* ecerr.error_char -> string
*
- * returns the one-character string which cause Encoding::ConversionUndefined.
+ * returns the one-character string which cause Encoding::ConversionUndefinedError.
*
* ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
* begin
* ec.convert("\xa0")
- * rescue Encoding::ConversionUndefined
+ * rescue Encoding::ConversionUndefinedError
* puts $!.error_char.dump #=> "\xC2\xA0"
* p $!.error_char.encoding #=> #<Encoding:UTF-8>
* end
@@ -3847,13 +3868,13 @@ ecerr_error_char(VALUE self)
* call-seq:
* ecerr.error_bytes -> string
*
- * returns the discarded bytes when Encoding::InvalidByteSequence occur.
+ * returns the discarded bytes when Encoding::InvalidByteSequenceError occur.
*
* ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
* begin
* ec.convert("abc\xA1\xFFdef")
- * rescue Encoding::InvalidByteSequence
- * p $! #=> #<Encoding::InvalidByteSequence: "\xA1" followed by "\xFF" on EUC-JP>
+ * rescue Encoding::InvalidByteSequenceError
+ * p $! #=> #<Encoding::InvalidByteSequenceError: "\xA1" followed by "\xFF" on EUC-JP>
* puts $!.error_bytes.dump #=> "\xA1"
* puts $!.readagain_bytes.dump #=> "\xFF"
* end
@@ -3868,7 +3889,7 @@ ecerr_error_bytes(VALUE self)
* call-seq:
* ecerr.readagain_bytes -> string
*
- * returns the bytes to be read again when Encoding::InvalidByteSequence occur.
+ * returns the bytes to be read again when Encoding::InvalidByteSequenceError occur.
*/
static VALUE
ecerr_readagain_bytes(VALUE self)
@@ -3887,16 +3908,16 @@ ecerr_readagain_bytes(VALUE self)
*
* begin
* ec.convert("abc\xA1z")
- * rescue Encoding::InvalidByteSequence
- * p $! #=> #<Encoding::InvalidByteSequence: "\xA1" followed by "z" on EUC-JP>
+ * rescue Encoding::InvalidByteSequenceError
+ * p $! #=> #<Encoding::InvalidByteSequenceError: "\xA1" followed by "z" on EUC-JP>
* p $!.incomplete_input? #=> false
* end
*
* begin
* ec.convert("abc\xA1")
* ec.finish
- * rescue Encoding::InvalidByteSequence
- * p $! #=> #<Encoding::InvalidByteSequence: incomplete "\xA1" on EUC-JP>
+ * rescue Encoding::InvalidByteSequenceError
+ * p $! #=> #<Encoding::InvalidByteSequenceError: incomplete "\xA1" on EUC-JP>
* p $!.incomplete_input? #=> true
* end
*/
@@ -3911,9 +3932,9 @@ extern void Init_newline(void);
void
Init_transcode(void)
{
- rb_eConversionUndefined = rb_define_class_under(rb_cEncoding, "ConversionUndefined", rb_eStandardError);
- rb_eInvalidByteSequence = rb_define_class_under(rb_cEncoding, "InvalidByteSequence", rb_eStandardError);
- rb_eNoConverter = rb_define_class_under(rb_cEncoding, "NoConverter", rb_eStandardError);
+ rb_eConversionUndefinedError = rb_define_class_under(rb_cEncoding, "ConversionUndefinedError", rb_eStandardError);
+ rb_eInvalidByteSequenceError = rb_define_class_under(rb_cEncoding, "InvalidByteSequenceError", rb_eStandardError);
+ rb_eNoConverterError = rb_define_class_under(rb_cEncoding, "NoConverterError", rb_eStandardError);
transcoder_table = st_init_strcasetable();
@@ -3973,19 +3994,19 @@ Init_transcode(void)
rb_define_const(rb_cEncodingConverter, "XML_ATTR_CONTENT_DECORATOR", INT2FIX(ECONV_XML_ATTR_CONTENT_DECORATOR));
rb_define_const(rb_cEncodingConverter, "XML_ATTR_QUOTE_DECORATOR", INT2FIX(ECONV_XML_ATTR_QUOTE_DECORATOR));
- rb_define_method(rb_eConversionUndefined, "source_encoding_name", ecerr_source_encoding_name, 0);
- rb_define_method(rb_eConversionUndefined, "destination_encoding_name", ecerr_destination_encoding_name, 0);
- rb_define_method(rb_eConversionUndefined, "source_encoding", ecerr_source_encoding, 0);
- rb_define_method(rb_eConversionUndefined, "destination_encoding", ecerr_destination_encoding, 0);
- rb_define_method(rb_eConversionUndefined, "error_char", ecerr_error_char, 0);
-
- rb_define_method(rb_eInvalidByteSequence, "source_encoding_name", ecerr_source_encoding_name, 0);
- rb_define_method(rb_eInvalidByteSequence, "destination_encoding_name", ecerr_destination_encoding_name, 0);
- rb_define_method(rb_eInvalidByteSequence, "source_encoding", ecerr_source_encoding, 0);
- rb_define_method(rb_eInvalidByteSequence, "destination_encoding", ecerr_destination_encoding, 0);
- rb_define_method(rb_eInvalidByteSequence, "error_bytes", ecerr_error_bytes, 0);
- rb_define_method(rb_eInvalidByteSequence, "readagain_bytes", ecerr_readagain_bytes, 0);
- rb_define_method(rb_eInvalidByteSequence, "incomplete_input?", ecerr_incomplete_input, 0);
+ rb_define_method(rb_eConversionUndefinedError, "source_encoding_name", ecerr_source_encoding_name, 0);
+ rb_define_method(rb_eConversionUndefinedError, "destination_encoding_name", ecerr_destination_encoding_name, 0);
+ rb_define_method(rb_eConversionUndefinedError, "source_encoding", ecerr_source_encoding, 0);
+ rb_define_method(rb_eConversionUndefinedError, "destination_encoding", ecerr_destination_encoding, 0);
+ rb_define_method(rb_eConversionUndefinedError, "error_char", ecerr_error_char, 0);
+
+ rb_define_method(rb_eInvalidByteSequenceError, "source_encoding_name", ecerr_source_encoding_name, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "destination_encoding_name", ecerr_destination_encoding_name, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "source_encoding", ecerr_source_encoding, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "destination_encoding", ecerr_destination_encoding, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "error_bytes", ecerr_error_bytes, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "readagain_bytes", ecerr_readagain_bytes, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "incomplete_input?", ecerr_incomplete_input, 0);
Init_newline();
}
diff --git a/transcode_data.h b/transcode_data.h
index 98f48a4de9..497eb3c51b 100644
--- a/transcode_data.h
+++ b/transcode_data.h
@@ -34,10 +34,12 @@
#define FUNsi (PType 0x0D) /* function from start to info */
#define FUNio (PType 0x0E) /* function from info to output */
#define FUNso (PType 0x0F) /* function from start to output */
-#define STR1 (PType 0x11) /* string up to 255 bytes: 1byte length + content */
+#define STR1 (PType 0x11) /* string 4 <= len <= 259 bytes: 1byte length + content */
+#define STR1_LENGTH(byte_addr) (*(byte_addr) + 4)
#define STR1_BYTEINDEX(w) ((w) >> 6)
#define makeSTR1(bi) (((bi) << 6) | STR1)
+#define makeSTR1LEN(len) ((len)-4)
#define o1(b1) (PType((((unsigned char)(b1))<<8)|ONEbt))
#define o2(b1,b2) (PType((((unsigned char)(b1))<<8)|(((unsigned char)(b2))<<16)|TWObt))
@@ -84,11 +86,11 @@ struct rb_transcoder {
int (*state_fini_func)(void*); /* ret==0:success ret!=0:failure(errno) */
VALUE (*func_ii)(void*, VALUE); /* info -> info */
VALUE (*func_si)(void*, const unsigned char*, size_t); /* start -> info */
- int (*func_io)(void*, VALUE, const unsigned char*); /* info -> output */
- int (*func_so)(void*, const unsigned char*, size_t, unsigned char*); /* start -> output */
- int (*finish_func)(void*, unsigned char*); /* -> output */
- int (*resetsize_func)(void*); /* -> len */
- int (*resetstate_func)(void*, unsigned char*); /* -> output */
+ ssize_t (*func_io)(void*, VALUE, const unsigned char*, size_t); /* info -> output */
+ ssize_t (*func_so)(void*, const unsigned char*, size_t, unsigned char*, size_t); /* start -> output */
+ ssize_t (*finish_func)(void*, unsigned char*, size_t); /* -> output */
+ ssize_t (*resetsize_func)(void*); /* -> len */
+ ssize_t (*resetstate_func)(void*, unsigned char*, size_t); /* -> output */
};
void rb_declare_transcoder(const char *enc1, const char *enc2, const char *lib);
diff --git a/version.h b/version.h
index 42c19fcf52..cc88cf8780 100644
--- a/version.h
+++ b/version.h
@@ -1,7 +1,7 @@
#define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2008-09-14"
+#define RUBY_RELEASE_DATE "2008-09-21"
#define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20080914
+#define RUBY_RELEASE_CODE 20080921
#define RUBY_PATCHLEVEL 0
#define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
#define RUBY_VERSION_TEENY 0
#define RUBY_RELEASE_YEAR 2008
#define RUBY_RELEASE_MONTH 9
-#define RUBY_RELEASE_DAY 14
+#define RUBY_RELEASE_DAY 21
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];
diff --git a/vm.c b/vm.c
index 71658195b1..7841b43396 100644
--- a/vm.c
+++ b/vm.c
@@ -1820,7 +1820,7 @@ Init_VM(void)
rb_define_method_id(klass, id_core_define_singleton_method, m_core_define_singleton_method, 3);
rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 1);
rb_obj_freeze(fcore);
- rb_global_variable(&rb_mRubyVMFrozenCore);
+ rb_gc_register_mark_object(fcore);
rb_mRubyVMFrozenCore = fcore;
/* ::VM::Env */
@@ -1901,7 +1901,7 @@ Init_VM(void)
vm->living_threads = st_init_numtable();
st_insert(vm->living_threads, th_self, (st_data_t) th->thread_id);
- rb_register_mark_object(iseqval);
+ rb_gc_register_mark_object(iseqval);
GetISeqPtr(iseqval, iseq);
th->cfp->iseq = iseq;
th->cfp->pc = iseq->iseq_encoded;
@@ -1960,6 +1960,9 @@ Init_top_self(void)
vm->top_self = rb_obj_alloc(rb_cObject);
rb_define_singleton_method(rb_vm_top_self(), "to_s", main_to_s, 0);
+
+ /* initialize mark object array */
+ vm->mark_object_ary = rb_ary_new();
}
VALUE *