changeset 30833:2db6e42a6ba3

(MINIMUM_CONVERSION_BUFFER_SIZE): Macro deleted. (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.
author Kenichi Handa <handa@m17n.org>
date Wed, 16 Aug 2000 01:37:20 +0000
parents b0b1acff966b
children 34cac3323036
files src/coding.c
diffstat 1 files changed, 156 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/src/coding.c	Wed Aug 16 01:36:53 2000 +0000
+++ b/src/coding.c	Wed Aug 16 01:37:20 2000 +0000
@@ -3870,33 +3870,60 @@
   return (src_bytes * magnification + CONVERSION_BUFFER_EXTRA_ROOM);
 }
 
-#ifndef MINIMUM_CONVERSION_BUFFER_SIZE
-#define MINIMUM_CONVERSION_BUFFER_SIZE 1024
-#endif
-
-char *conversion_buffer;
-int conversion_buffer_size;
-
-/* 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.  */
-
-char *
-get_conversion_buffer (size)
-     int size;
+/* Working buffer for code conversion.  */
+struct conversion_buffer
 {
-  if (size > conversion_buffer_size)
+  int size;			/* size of data.  */
+  int on_stack;			/* 1 if allocated by alloca.  */
+  unsigned char *data;
+};
+
+/* Don't use alloca for allocating memory space larger than this, lest
+   we overflow their stack.  */
+#define MAX_ALLOCA 16*1024
+
+/* 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)
+
+/* Double the allocated memory for *BUF.  */
+static void
+extend_conversion_buffer (buf)
+     struct conversion_buffer *buf;
+{
+  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;
+    }
+  else
+    {
+      buf->data = (unsigned char *) xrealloc (buf->data, buf->size * 2);
     }
-  return conversion_buffer;
+  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 @@
   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 @@
 	}
       coding->consumed = coding->consumed_char = src - source;
       coding->produced = dst - destination;
+      coding->result = CODING_FINISH_NORMAL;
     }
 
   if (!coding->dst_multibyte)
@@ -4231,7 +4259,8 @@
       && 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 @@
 	  coding->consumed = src_bytes;
 	}
       coding->produced = coding->produced_char = dst - destination;
+      coding->result = CODING_FINISH_NORMAL;
     }
 
   return coding->result;
@@ -5197,12 +5227,15 @@
      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 @@
   /* 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 @@
 
   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;
-
-  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)
+  allocate_conversion_buffer (buf, len);
+
+  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);
-
-  return str;
+    newstr = run_pre_post_conversion_on_str (newstr, coding, 0);
+
+  return newstr;
 }
 
 Lisp_Object
@@ -5320,11 +5383,14 @@
      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 @@
   /* 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;
 }
 
 
@@ -6208,12 +6286,6 @@
 /*** 9. Post-amble ***/
 
 void
-init_coding ()
-{
-  conversion_buffer = (char *) xmalloc (MINIMUM_CONVERSION_BUFFER_SIZE);
-}
-
-void
 init_coding_once ()
 {
   int i;
@@ -6253,8 +6325,6 @@
   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);