(MINIMUM_CONVERSION_BUFFER_SIZE): Macro deleted.
authorKenichi Handa <handa@m17n.org>
Wed, 16 Aug 2000 01:37:20 +0000 (01:37 +0000)
committerKenichi Handa <handa@m17n.org>
Wed, 16 Aug 2000 01:37:20 +0000 (01:37 +0000)
(conversion_buffer, conversion_buffer_size): Variables deleted.
(get_conversion_buffer): Function deleted.
(struct conversion_buffer): New structure.
(MAX_ALLOCA): New macro.
(allocate_conversion_buffer): New macro.
(extend_conversion_buffer, free_conversion_buffer): New functions.
(ccl_coding_driver): Set coding->result.
(decode_coding): Set coding->result to CODING_FINISH_NORMAL if
this is the last block of source.
(encode_coding): Likewise.  Handle the source block as the last
one only when the whole source text is consumed.
(decode_coding_string): Handle the case that the output buffer is
too small to decode the whole source text.  Use
allocate_conversion_buffer, extend_conversion_buffer and
free_conversion_buffer, not get_conversion_buffer.
(encode_coding_string): Likewise.
(init_coding): Function deleted.
(init_coding_once): Delete code to initialize
conversion_buffer_size.

src/coding.c

index ba83767..a9704c0 100644 (file)
@@ -3870,33 +3870,60 @@ encoding_buffer_size (coding, src_bytes)
   return (src_bytes * magnification + CONVERSION_BUFFER_EXTRA_ROOM);
 }
 
-#ifndef MINIMUM_CONVERSION_BUFFER_SIZE
-#define MINIMUM_CONVERSION_BUFFER_SIZE 1024
-#endif
+/* Working buffer for code conversion.  */
+struct conversion_buffer
+{
+  int size;                    /* size of data.  */
+  int on_stack;                        /* 1 if allocated by alloca.  */
+  unsigned char *data;
+};
 
-char *conversion_buffer;
-int conversion_buffer_size;
+/* Don't use alloca for allocating memory space larger than this, lest
+   we overflow their stack.  */
+#define MAX_ALLOCA 16*1024
 
-/* Return a pointer to a SIZE bytes of buffer to be used for encoding
-   or decoding.  Sufficient memory is allocated automatically.  If we
-   run out of memory, return NULL.  */
+/* Allocate LEN bytes of memory for BUF (struct conversion_buffer).  */
+#define allocate_conversion_buffer(buf, len)           \
+  do {                                                 \
+    if (len < MAX_ALLOCA)                              \
+      {                                                        \
+       buf.data = (unsigned char *) alloca (len);      \
+       buf.on_stack = 1;                               \
+      }                                                        \
+    else                                               \
+      {                                                        \
+       buf.data = (unsigned char *) xmalloc (len);     \
+       buf.on_stack = 0;                               \
+      }                                                        \
+    buf.size = len;                                    \
+  } while (0)
 
-char *
-get_conversion_buffer (size)
-     int size;
+/* Double the allocated memory for *BUF.  */
+static void
+extend_conversion_buffer (buf)
+     struct conversion_buffer *buf;
 {
-  if (size > conversion_buffer_size)
+  if (buf->on_stack)
     {
-      char *buf;
-      int real_size = conversion_buffer_size * 2;
-
-      while (real_size < size) real_size *= 2;
-      buf = (char *) xmalloc (real_size);
-      xfree (conversion_buffer);
-      conversion_buffer = buf;
-      conversion_buffer_size = real_size;
+      unsigned char *save = buf->data;
+      buf->data = (unsigned char *) xmalloc (buf->size * 2);
+      bcopy (save, buf->data, buf->size);
+      buf->on_stack = 0;
     }
-  return conversion_buffer;
+  else
+    {
+      buf->data = (unsigned char *) xrealloc (buf->data, buf->size * 2);
+    }
+  buf->size *= 2;
+}
+
+/* Free the allocated memory for BUF if it is not on stack.  */
+static void
+free_conversion_buffer (buf)
+     struct conversion_buffer *buf;
+{
+  if (!buf->on_stack)
+    xfree (buf->data);
 }
 
 int
@@ -3929,20 +3956,20 @@ ccl_coding_driver (coding, source, destination, src_bytes, dst_bytes, encodep)
   switch (ccl->status)
     {
     case CCL_STAT_SUSPEND_BY_SRC:
-      result = CODING_FINISH_INSUFFICIENT_SRC;
+      coding->result = CODING_FINISH_INSUFFICIENT_SRC;
       break;
     case CCL_STAT_SUSPEND_BY_DST:
-      result = CODING_FINISH_INSUFFICIENT_DST;
+      coding->result = CODING_FINISH_INSUFFICIENT_DST;
       break;
     case CCL_STAT_QUIT:
     case CCL_STAT_INVALID_CMD:
-      result = CODING_FINISH_INTERRUPT;
+      coding->result = CODING_FINISH_INTERRUPT;
       break;
     default:
-      result = CODING_FINISH_NORMAL;
+      coding->result = CODING_FINISH_NORMAL;
       break;
     }
-  return result;
+  return coding->result;
 }
 
 /* Decode EOL format of the text at PTR of BYTES length destructively
@@ -4170,6 +4197,7 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes)
        }
       coding->consumed = coding->consumed_char = src - source;
       coding->produced = dst - destination;
+      coding->result = CODING_FINISH_NORMAL;
     }
 
   if (!coding->dst_multibyte)
@@ -4231,7 +4259,8 @@ encode_coding (coding, source, destination, src_bytes, dst_bytes)
       && coding->consumed == src_bytes)
     coding->result = CODING_FINISH_NORMAL;
 
-  if (coding->mode & CODING_MODE_LAST_BLOCK)
+  if (coding->mode & CODING_MODE_LAST_BLOCK
+      && coding->result == CODING_FINISH_INSUFFICIENT_SRC)
     {
       unsigned char *src = source + coding->consumed;
       unsigned char *src_end = src + src_bytes;
@@ -4252,6 +4281,7 @@ encode_coding (coding, source, destination, src_bytes, dst_bytes)
          coding->consumed = src_bytes;
        }
       coding->produced = coding->produced_char = dst - destination;
+      coding->result = CODING_FINISH_NORMAL;
     }
 
   return coding->result;
@@ -5197,12 +5227,15 @@ decode_coding_string (str, coding, nocopy)
      int nocopy;
 {
   int len;
-  char *buf;
+  struct conversion_buffer buf;
   int from, to, to_byte;
   struct gcpro gcpro1;
   Lisp_Object saved_coding_symbol;
   int result;
   int require_decoding;
+  int shrinked_bytes = 0;
+  Lisp_Object newstr;
+  int consumed, produced, produced_char;
 
   from = 0;
   to = XSTRING (str)->size;
@@ -5247,12 +5280,11 @@ decode_coding_string (str, coding, nocopy)
   /* Try to skip the heading and tailing ASCIIs.  */
   if (require_decoding && coding->type != coding_type_ccl)
     {
-      int from_orig = from;
-
       SHRINK_CONVERSION_REGION (&from, &to_byte, coding, XSTRING (str)->data,
                                0);
       if (from == to_byte)
        require_decoding = 0;
+      shrinked_bytes = from + (STRING_BYTES (XSTRING (str)) - to_byte);
     }
 
   if (!require_decoding)
@@ -5271,46 +5303,77 @@ decode_coding_string (str, coding, nocopy)
 
   if (coding->composing != COMPOSITION_DISABLED)
     coding_allocate_composition_data (coding, from);
-
   len = decoding_buffer_size (coding, to_byte - from);
-  len += from + STRING_BYTES (XSTRING (str)) - to_byte;
-  GCPRO1 (str);
-  buf = get_conversion_buffer (len);
-  UNGCPRO;
+  allocate_conversion_buffer (buf, len);
 
-  if (from > 0)
-    bcopy (XSTRING (str)->data, buf, from);
-  result = decode_coding (coding, XSTRING (str)->data + from,
-                        buf + from, to_byte - from, len);
-  if (result == CODING_FINISH_INCONSISTENT_EOL)
+  consumed = produced = produced_char = 0;
+  while (1)
     {
-      /* We simply try to decode the whole string again but without
-         eol-conversion this time.  */
-      coding->eol_type = CODING_EOL_LF;
-      coding->symbol = saved_coding_symbol;
-      coding_free_composition_data (coding);
-      return decode_coding_string (str, coding, nocopy);
+      result = decode_coding (coding, XSTRING (str)->data + from + consumed,
+                             buf.data + produced, to_byte - from - consumed,
+                             buf.size - produced);
+      consumed += coding->consumed;
+      produced += coding->produced;
+      produced_char += coding->produced_char;
+      if (result == CODING_FINISH_NORMAL)
+       break;
+      if (result == CODING_FINISH_INSUFFICIENT_CMP)
+       coding_allocate_composition_data (coding, from + produced_char);
+      else if (result == CODING_FINISH_INSUFFICIENT_DST)
+       extend_conversion_buffer (&buf);
+      else if (result == CODING_FINISH_INCONSISTENT_EOL)
+       {
+         /* Recover the original EOL format.  */
+         if (coding->eol_type == CODING_EOL_CR)
+           {
+             unsigned char *p;
+             for (p = buf.data; p < buf.data + produced; p++)
+               if (*p == '\n') *p = '\r';
+           }
+         else if (coding->eol_type == CODING_EOL_CRLF)
+           {
+             int num_eol = 0;
+             unsigned char *p0, *p1;
+             for (p0 = buf.data, p1 = p0 + produced; p0 < p1; p0++)
+               if (*p0 == '\n') num_eol++;
+             if (produced + num_eol >= buf.size)
+               extend_conversion_buffer (&buf);
+             for (p0 = buf.data + produced, p1 = p0 + num_eol; p0 > buf.data;)
+               {
+                 *--p1 = *--p0;
+                 if (*p0 == '\n') *--p1 = '\r';
+               }
+             produced += num_eol;
+             produced_char += num_eol;
+           } 
+         coding->eol_type = CODING_EOL_LF;
+         coding->symbol = saved_coding_symbol;
+       }
     }
 
-  bcopy (XSTRING (str)->data + to_byte, buf + from + coding->produced,
-        STRING_BYTES (XSTRING (str)) - to_byte);
-
-  len = from + STRING_BYTES (XSTRING (str)) - to_byte;
   if (coding->dst_multibyte)
-    str = make_multibyte_string (buf, len + coding->produced_char,
-                                len + coding->produced);
+    newstr = make_uninit_multibyte_string (produced_char + shrinked_bytes,
+                                          produced + shrinked_bytes);
   else
-    str = make_unibyte_string (buf, len + coding->produced);
+    newstr = make_uninit_string (produced + shrinked_bytes);
+  if (from > 0)
+    bcopy (XSTRING (str)->data, XSTRING (newstr)->data, from);
+  bcopy (buf.data, XSTRING (newstr)->data + from, produced);
+  if (shrinked_bytes > from)
+    bcopy (XSTRING (str)->data + to_byte,
+          XSTRING (newstr)->data + from + produced,
+          shrinked_bytes - from);
+  free_conversion_buffer (&buf);
 
   if (coding->cmp_data && coding->cmp_data->used)
-    coding_restore_composition (coding, str);
+    coding_restore_composition (coding, newstr);
   coding_free_composition_data (coding);
 
   if (SYMBOLP (coding->post_read_conversion)
       && !NILP (Ffboundp (coding->post_read_conversion)))
-    str = run_pre_post_conversion_on_str (str, coding, 0);
+    newstr = run_pre_post_conversion_on_str (newstr, coding, 0);
 
-  return str;
+  return newstr;
 }
 
 Lisp_Object
@@ -5320,11 +5383,14 @@ encode_coding_string (str, coding, nocopy)
      int nocopy;
 {
   int len;
-  char *buf;
+  struct conversion_buffer buf;
   int from, to, to_byte;
   struct gcpro gcpro1;
   Lisp_Object saved_coding_symbol;
   int result;
+  int shrinked_bytes = 0;
+  Lisp_Object newstr;
+  int consumed, consumed_char, produced;
 
   if (SYMBOLP (coding->pre_write_conversion)
       && !NILP (Ffboundp (coding->pre_write_conversion)))
@@ -5356,32 +5422,44 @@ encode_coding_string (str, coding, nocopy)
   /* Try to skip the heading and tailing ASCIIs.  */
   if (coding->type != coding_type_ccl)
     {
-      int from_orig = from;
-
       SHRINK_CONVERSION_REGION (&from, &to_byte, coding, XSTRING (str)->data,
                                1);
       if (from == to_byte)
        return (nocopy ? str : Fcopy_sequence (str));
+      shrinked_bytes = from + (STRING_BYTES (XSTRING (str)) - to_byte);
     }
 
   len = encoding_buffer_size (coding, to_byte - from);
-  len += from + STRING_BYTES (XSTRING (str)) - to_byte;
-  GCPRO1 (str);
-  buf = get_conversion_buffer (len);
-  UNGCPRO;
+  allocate_conversion_buffer (buf, len);
+
+  consumed = consumed_char = produced = 0;
+
+  while (1)
+    {
+      result = encode_coding (coding, XSTRING (str)->data + from + consumed,
+                             buf.data + produced, to_byte - from - consumed,
+                             buf.size - produced);
+      consumed += coding->consumed;
+      produced += coding->produced;
+      if (result == CODING_FINISH_NORMAL)
+       break;
+      /* Now result should be CODING_FINISH_INSUFFICIENT_DST.  */
+      extend_conversion_buffer (&buf);
+    }
 
+  newstr = make_uninit_string (produced + shrinked_bytes);
   if (from > 0)
-    bcopy (XSTRING (str)->data, buf, from);
-  result = encode_coding (coding, XSTRING (str)->data + from,
-                         buf + from, to_byte - from, len);
-  bcopy (XSTRING (str)->data + to_byte, buf + from + coding->produced,
-        STRING_BYTES (XSTRING (str)) - to_byte);
-
-  len = from + STRING_BYTES (XSTRING (str)) - to_byte;
-  str = make_unibyte_string (buf, len + coding->produced);
+    bcopy (XSTRING (str)->data, XSTRING (newstr)->data, from);
+  bcopy (buf.data, XSTRING (newstr)->data + from, produced);
+  if (shrinked_bytes > from)
+    bcopy (XSTRING (str)->data + to_byte,
+          XSTRING (newstr)->data + from + produced,
+          shrinked_bytes - from);
+
+  free_conversion_buffer (&buf);
   coding_free_composition_data (coding);
 
-  return str;
+  return newstr;
 }
 
 \f
@@ -6207,12 +6285,6 @@ This function is internal use only.")
 \f
 /*** 9. Post-amble ***/
 
-void
-init_coding ()
-{
-  conversion_buffer = (char *) xmalloc (MINIMUM_CONVERSION_BUFFER_SIZE);
-}
-
 void
 init_coding_once ()
 {
@@ -6253,8 +6325,6 @@ init_coding_once ()
   iso_code_class[ISO_CODE_SS3] = ISO_single_shift_3;
   iso_code_class[ISO_CODE_CSI] = ISO_control_sequence_introducer;
 
-  conversion_buffer_size = MINIMUM_CONVERSION_BUFFER_SIZE;
-
   setup_coding_system (Qnil, &keyboard_coding);
   setup_coding_system (Qnil, &terminal_coding);
   setup_coding_system (Qnil, &safe_terminal_coding);