Kakasiをrubyでつかう(その後)

ruby-kakasiを導入してみたのですが、どうも動きがおかしいことに気づきました

どういう時におかしいかというと連続で違う引数で呼び出す際にどうやら2回めの呼び出し時の引数が聞いていないような感じです。しかもローマ字に変換する際にヘボン式か訓令式か変更した場合のみです

こんなコード

#!ruby
#coding:utf-8

require "kakasi"
require "nkf"
keyword="し ち つ ふ じ ぢ しゃ しゅ しょ ちゃ ちゅ ちょ じゃ じゅ じょ ぢゃ ぢゅ ぢょ"
p Kakasi.kakasi("-Ea -Ja -Ka -Ha ",NKF.nkf("-e",keyword))
p Kakasi.kakasi("-Ea -Ja -Ka -Ha -rk",NKF.nkf("-e",keyword))

結果がこれ

$ ruby test.rb
"shi chi tsu fu ji di sha shu sho cha chu cho ja ju jo dya dyu dyo"
"shi chi tsu fu ji di sha shu sho cha chu cho ja ju jo dya dyu dyo"

最初kakasi-rubyがおかしいのかと思いソースコードをいじってみていたのですがどうやらそうではなく、本体側がおかしいことがわかりました。

このぶぶん

--- kakasi-2.3.4/src/hh2.c			2001-05-30 14:46:55.000000000 +0900
+++ kakasi-2.3.4_mod/src/hh2.c	2013-04-23 18:23:04.000000000 +0900
@@ -192,7 +192,7 @@
		 int max_match, match_more;
		 char *max_romaji;

-		if (index_made == 0) {
+//		if (index_made == 0) {
				int last;

				for (i = 0; i < 0x81; ++ i) {
@@ -211,7 +211,7 @@
								last = index_table[i];
				}
				index_made = 1;
-		}
+//		}

		 buffer[H2rom_buflen-1] = '\0'; clen = H2rom_buflen-1;
		 for (i = 0; i < (H2rom_buflen-1)/2; i ++) {

どうも訓令式とヘボン式のテーブルを切り替えて使っているようなのですが、高速化のためか一文字目の際にテーブルを作成し、それ以降はキャッシュを見るような感じになっています。しかしstatic変数で管理しているため、Library使用時にはこれがクリアされず、2回めのライブラリ呼び出し時には前回のキャッシュをそのまま使っていたようです

とりあえずキャッシュ部分を削除してみました。

本来ならばきちんと治すべきなのですが、、、、、

本体修正後rubyを実行

ruby test.rb
"shi chi tsu fu ji di sha shu sho cha chu cho ja ju jo dya dyu dyo"
"si ti tu hu zi di sya syu syo tya tyu tyo zya zyu zyo dya dyu dyo"

期待通りとなりました

kakasi-rubyをruby1.9で動かす

https://github.com/hogelog/kakasi-ruby

ruby用のkakasiモジュールはそのままではruby1.9ではコンパイルが通りません

そこで↓を参考に修正

http://www.metareal.org/2007/06/14/ruby-extension-struct-rstring-macros/

パッチ

diff -u kakasi-ruby-master/kakasi.c kakasi-ruby-master-1.9/kakasi.c
--- kakasi-ruby-master/kakasi.c 2013-04-19 10:14:17.000000000 +0900
+++ kakasi-ruby-master-1.9/kakasi.c		 2013-04-19 10:08:46.000000000 +0900
@@ -3,24 +3,28 @@
	*	Copyright (c) 1999-2002 GOTO Kentaro
	*/

-
 #include 
 #include "ruby.h"
 #include "libkakasi.h"

-
 #define OPTMAX 1024
 #define min(x,y) ((x)<(y) ? (x) : (y))


+// 130419 for 1.9
+#ifndef RSTRING_PTR
+#define RSTRING_PTR(s) (RSTRING(s)->ptr)
+#endif
+#ifndef RSTRING_LEN
+#define RSTRING_LEN(s) (RSTRING(s)->len)
+#endif
+
 static char const rcsid[] =
	 "$kNotwork: kakasi.c,v 1.3 2002/09/28 05:21:37 gotoken Exp $";

-
 static int dic_closed = 1, len = 0;
 static char prev_opt_ptr[OPTMAX];

-
 static VALUE
 rb_kakasi_kakasi(obj, opt, src)
		 VALUE obj, opt, src;
@@ -30,45 +34,36 @@
		 char *buf, *opt_ptr, *t;
		 VALUE dst;

-
		 Check_Type(src, T_STRING);

-
		 /* return "" immediately if source str is empty */
-		if (RSTRING(src)->len == 0)
+		if(RSTRING_LEN(src)==0)
				return rb_str_new2("");

-
		 Check_Type(opt, T_STRING);

-
			/* initialize kakasi iff opt != previous opt */
-		if (0 == len || 0 != strncmp(RSTRING(opt)->ptr, prev_opt_ptr,
-																min(RSTRING(opt)->len, len))) {
-			 strncpy(prev_opt_ptr, RSTRING(opt)->ptr, RSTRING(opt)->len);
-			 len = RSTRING(opt)->len;
-
+		if (0 == len || 0 != strncmp(RSTRING_PTR(opt), prev_opt_ptr,
+																min(RSTRING_LEN(opt), len))) {
+			 strncpy(prev_opt_ptr, RSTRING_PTR(opt), RSTRING_LEN(opt));
+			 len = RSTRING_LEN(opt);

				if (len + 1 > OPTMAX) {
						rb_raise(rb_eArgError, "too long 1st arg (should be < 1023)");
				}

-
				if (!dic_closed) {
						kakasi_close_kanwadict();
						dic_closed = 1;
				}

-
-			 argv = opts = ALLOCA_N(char*, RSTRING(opt)->len);
+			 argv = opts = ALLOCA_N(char*, RSTRING_LEN(opt));
				*opts++ = "kakasi";
				argc++;

-
-			 opt_ptr = ALLOCA_N(char, 1 + RSTRING(opt)->len);
-			 strncpy(opt_ptr, RSTRING(opt)->ptr, RSTRING(opt)->len);
-			 opt_ptr[RSTRING(opt)->len] = '\0';
-
+			 opt_ptr = ALLOCA_N(char, 1 + RSTRING_LEN(opt));
+			 strncpy(opt_ptr, RSTRING_PTR(opt), RSTRING_LEN(opt));
+			 opt_ptr[RSTRING_LEN(opt)] = '\0';

				if (*opts++ = strtok(opt_ptr, " \t")) {
						argc++;
@@ -77,42 +72,37 @@
								argc++;
						}
				}
-
-
+
				if (0 != kakasi_getopt_argv(argc, argv))
						rb_raise(rb_eRuntimeError, "failed to initialize kakasi");
				dic_closed = 0;
		 }

-
		 dst = rb_str_new2("");
-		while (i < RSTRING(src)->len) {
-			if (*(RSTRING(src)->ptr + i) != '\0') {
-			 buf = kakasi_do((RSTRING(src)->ptr + i));
+		while (i < RSTRING_LEN(src)) {
+			if (*(RSTRING_PTR(src) + i) != '\0') {
+			 buf = kakasi_do((RSTRING_PTR(src) + i));
				rb_str_concat(dst, rb_str_new2(buf));
				if (*buf) free(buf);
-			 while (*(RSTRING(src)->ptr + i) != '\0') {
+			 while (*(RSTRING_PTR(src) + i) != '\0') {
					i++;
				}
			 }
-			if (i == RSTRING(src)->len) {
+			if (i == RSTRING_LEN(src)) {
				break;
			 }
			 rb_str_concat(dst, rb_str_new("\0", 1));
			 i++;
		 }

-
		 return dst;
 }

-
 void
 Init_kakasi()
 {
		 VALUE mKakasi = rb_define_module("Kakasi");

-
		 rb_define_module_function(mKakasi, "kakasi", rb_kakasi_kakasi, 2);
		 rb_define_const(mKakasi, "KAKASI_VERSION", rb_str_new2("2002-09-28"));
 }

と思って作成していたらすでに修正している人がいました。_| ̄|○

https://github.com/hogelog/kakasi-ruby/tree/1.9

Tomcat+DBCP+SQLite

  • server.xml
			
								
			
  • WEB-INF/web.xml


	test	
	
		jdbc/sqlite
		javax.sql.DataSource
		Container
	

  • jsp
<%@ page language="java" contentType="text/html; charset=Shift_JIS" pageEncoding="Shift_JIS"%><%@ page import="java.sql.*,javax.naming.*,javax.sql.*,java.util.*,java.text.*,java.net.*" %>
<%
	InitialContext ic = new InitialContext();
	DataSource ds=(DataSource)ic.lookup("java:comp/env/jdbc/sqlite");
	Connection conn=ds.getConnection();
	PreparedStatement ps=conn.prepareStatement("select datetime('now','localtime')");
	ps.execute();
	ResultSet rs=ps.getResultSet();
	while(rs.next()){
		 out.println(rs.getString(1));
	}
 %>
  • 結果
2013-04-18 17:01:20