OSDN Git Service

* Fix: nkc for UTF8-MAC.
authorNARUSE, Yui <naruse@users.sourceforge.jp>
Mon, 10 Nov 2008 03:28:52 +0000 (03:28 +0000)
committerNARUSE, Yui <naruse@users.sourceforge.jp>
Mon, 10 Nov 2008 03:28:52 +0000 (03:28 +0000)
nkf.c

diff --git a/nkf.c b/nkf.c
index 7797245..ce68917 100644 (file)
--- a/nkf.c
+++ b/nkf.c
@@ -31,9 +31,9 @@
  * \e$B8=:_!"\e(Bnkf \e$B$O\e(B SorceForge \e$B$K$F%a%s%F%J%s%9$,B3$1$i$l$F$$$^$9!#\e(B
  * http://sourceforge.jp/projects/nkf/
  ***********************************************************************/
-#define NKF_IDENT "$Id: nkf.c,v 1.188 2008/11/07 02:43:43 naruse Exp $"
+#define NKF_IDENT "$Id: nkf.c,v 1.189 2008/11/09 18:28:52 naruse Exp $"
 #define NKF_VERSION "2.0.8"
-#define NKF_RELEASE_DATE "2008-11-07"
+#define NKF_RELEASE_DATE "2008-11-10"
 #define COPY_RIGHT \
     "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),2000 S. Kono, COW\n" \
     "Copyright (C) 2002-2008 Kono, Furukawa, Naruse, mastodon"
@@ -50,6 +50,7 @@
 # define INCL_DOSERRORS
 # include <os2.h>
 #endif
+#include <assert.h>
 
 /* state of output_mode and input_mode
 
@@ -4198,42 +4199,102 @@ numchar_ungetc(nkf_char c, FILE *f)
 
 #ifdef UNICODE_NORMALIZATION
 
+typedef struct {
+    unsigned char *buf;
+    int max_length;
+    int count;
+} nkf_buffer;
+
+static nkf_buffer *
+nkf_buf_new(int length)
+{
+    nkf_buffer *buf = malloc(sizeof(nkf_buffer));
+    buf->buf = malloc(length);
+    buf->max_length = length;
+    buf->count = 0;
+    return buf;
+} 
+
+#define nkf_buf_count(buf) ((buf)->count)
+#define nkf_buf_empty_p(buf) ((buf)->count == 0)
+
+static unsigned char
+nkf_buf_push(nkf_buffer *buf, nkf_char c)
+{
+    assert(buf->max_length > buf->count);
+    buf->buf[buf->count++] = c;
+    return buf->count;
+}
+
+static unsigned char
+nkf_buf_pop(nkf_buffer *buf)
+{
+    assert(0 < buf->count);
+    return buf->buf[--buf->count];
+}
+
+static unsigned char
+nkf_buf_at(nkf_buffer *buf, int index)
+{
+    assert(index <= buf->count);
+    return buf->buf[index];
+}
+
+static void
+nkf_buf_clear(nkf_buffer *buf)
+{
+    buf->count = 0;
+}
+
 /* Normalization Form C */
 static nkf_char
 nfc_getc(FILE *f)
 {
     nkf_char (*g)(FILE *f) = i_nfc_getc;
     nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc;
-    int i=0, j, k=1, lower, upper;
-    nkf_char buf[9];
+    nkf_buffer *buf = nkf_buf_new(9);
     const unsigned char *array;
+    int lower=0, upper=NORMALIZATION_TABLE_LENGTH-1;
+    int c = (*g)(f);
 
-    buf[i] = (*g)(f);
-    while (k > 0 && ((buf[i] & 0xc0) != 0x80)){
-       lower=0, upper=NORMALIZATION_TABLE_LENGTH-1;
-       while (upper >= lower) {
-           j = (lower+upper) / 2;
-           array = normalization_table[j].nfd;
-           for (k=0; k < NORMALIZATION_TABLE_NFD_LENGTH && array[k]; k++){
-               if (array[k] != buf[k]){
-                   array[k] < buf[k] ? (lower = j + 1) : (upper = j - 1);
-                   k = 0;
+    if (c == EOF || c > 0xFF || (c & 0xc0) != 0x80) return c;
+
+    nkf_buf_push(buf, (unsigned char)c);
+    do {
+       while (lower <= upper) {
+           int mid = (lower+upper) / 2;
+           int len;
+           array = normalization_table[mid].nfd;
+           for (len=0; len < NORMALIZATION_TABLE_NFD_LENGTH && array[len]; len++) {
+               if (array[len] != nkf_buf_at(buf, len)) {
+                   if (array[len] < nkf_buf_at(buf, len)) lower = mid + 1;
+                   else  upper = mid - 1;
+                   len = 0;
                    break;
-               } else if (k >= i)
-                   buf[++i] = (*g)(f);
+               } else if (len >= nkf_buf_count(buf)) {
+                   c = (*g)(f);
+                   if (c == EOF) {
+                       len = 0;
+                       lower = 1, upper = 0;
+                       break;
+                   }
+                   nkf_buf_push(buf, c);
+               }
            }
-           if (k > 0){
-               array = normalization_table[j].nfc;
+           if (len > 0) {
+               int i;
+               array = normalization_table[mid].nfc;
+               nkf_buf_clear(buf);
                for (i=0; i < NORMALIZATION_TABLE_NFC_LENGTH && array[i]; i++)
-                   buf[i] = (nkf_char)(array[i]);
-               i--;
+                   nkf_buf_push(buf, array[i]);
                break;
            }
        }
-       while (i > 0)
-           (*u)(buf[i--], f);
-    }
-    return buf[0];
+    } while (lower <= upper);
+
+    while (nkf_buf_count(buf) > 1) (*u)(nkf_buf_pop(buf), f);
+
+    return nkf_buf_pop(buf);
 }
 
 static nkf_char