*** empty log message ***
[bpt/guile.git] / libguile / strports.c
index 70d8e66..f7b4013 100644 (file)
  */
 
 /* NOTES:
+
+   We break the rules set forth by strings.h about accessing the
+   internals of strings here.  We can do this since we can guarantee
+   that the string used as pt->stream is not in use by anyone else.
+   Thus, it's representation will not change asynchronously.
+
+   (Ports aren't thread-safe yet anyway...)
+
    write_buf/write_end point to the ends of the allocated string.
    read_buf/read_end in principle point to the part of the string which
    has been written to, but this is only updated after a flush.
@@ -79,8 +87,10 @@ static void
 st_resize_port (scm_t_port *pt, off_t new_size)
 {
   SCM old_stream = SCM_PACK (pt->stream);
-  SCM new_stream = scm_allocate_string (new_size);
-  unsigned long int old_size = SCM_STRING_LENGTH (old_stream);
+  const char *src = scm_i_string_chars (old_stream);
+  char *dst;
+  SCM new_stream = scm_i_make_string (new_size, &dst);
+  unsigned long int old_size = scm_i_string_length (old_stream);
   unsigned long int min_size = min (old_size, new_size);
   unsigned long int i;
 
@@ -89,12 +99,14 @@ st_resize_port (scm_t_port *pt, off_t new_size)
   pt->write_buf_size = new_size;
 
   for (i = 0; i != min_size; ++i)
-    SCM_STRING_CHARS (new_stream) [i] = SCM_STRING_CHARS (old_stream) [i];
+    dst[i] = src[i];
+
+  scm_remember_upto_here_1 (old_stream);
 
   /* reset buffer. */
   {
     pt->stream = SCM_UNPACK (new_stream);
-    pt->read_buf = pt->write_buf = SCM_STRING_UCHARS (new_stream);
+    pt->read_buf = pt->write_buf = dst;
     pt->read_pos = pt->write_pos = pt->write_buf + index;
     pt->write_end = pt->write_buf + pt->write_buf_size;
     pt->read_end = pt->read_buf + pt->read_buf_size;
@@ -252,19 +264,37 @@ scm_mkstrport (SCM pos, SCM str, long modes, const char *caller)
   scm_t_port *pt;
   size_t str_len, c_pos;
 
-  SCM_ASSERT (SCM_I_STRINGP (str), str, SCM_ARG1, caller);
-  str_len = SCM_I_STRING_LENGTH (str);
+  SCM_ASSERT (scm_is_string (str), str, SCM_ARG1, caller);
+
+  str_len = scm_i_string_length (str);
   c_pos = scm_to_unsigned_integer (pos, 0, str_len);
 
   if (!((modes & SCM_WRTNG) || (modes & SCM_RDNG)))
     scm_misc_error ("scm_mkstrport", "port must read or write", SCM_EOL);
 
+  /* XXX
+     Make a new string to isolate us from changes to the original.
+     This is done so that we can rely on scm_i_string_chars to stay in
+     place even across SCM_TICKs.
+
+     Additionally, when we are going to write to the string, we make a
+     copy so that we can write to it without having to use
+     scm_i_string_writable_chars.
+  */
+
+  if (modes & SCM_WRTNG)
+    str = scm_c_substring_copy (str, 0, str_len);
+  else
+    str = scm_c_substring (str, 0, str_len);
+
   scm_mutex_lock (&scm_i_port_table_mutex);
   z = scm_new_port_table_entry (scm_tc16_strport);
   pt = SCM_PTAB_ENTRY(z);
   SCM_SETSTREAM (z, SCM_UNPACK (str));
   SCM_SET_CELL_TYPE(z, scm_tc16_strport|modes);
-  pt->write_buf = pt->read_buf = SCM_I_STRING_UCHARS (str);
+  /* see above why we can use scm_i_string_chars here. */
+  pt->write_buf = pt->read_buf = (char *)scm_i_string_chars (str);
   pt->read_pos = pt->write_pos = pt->read_buf + c_pos;
   pt->write_buf_size = pt->read_buf_size = str_len;
   pt->write_end = pt->read_end = pt->read_buf + pt->read_buf_size;
@@ -284,11 +314,13 @@ SCM scm_strport_to_string (SCM port)
 {
   scm_t_port *pt = SCM_PTAB_ENTRY (port);
   SCM str;
-
+  char *dst;
+  
   if (pt->rw_active == SCM_PORT_WRITE)
     st_flush (port);
 
-  str = scm_mem2string ((char *) pt->read_buf, pt->read_buf_size);
+  str = scm_i_make_string (pt->read_buf_size, &dst);
+  memcpy (dst, (char *) pt->read_buf, pt->read_buf_size);
   scm_remember_upto_here_1 (port);
   return str;
 }
@@ -305,7 +337,7 @@ SCM_DEFINE (scm_object_to_string, "object->string", 1, 1, 0,
   if (!SCM_UNBNDP (printer))
     SCM_VALIDATE_PROC (2, printer);
 
-  str = scm_allocate_string (0);
+  str = scm_c_make_string (0, SCM_UNDEFINED);
   port = scm_mkstrport (SCM_INUM0, str, SCM_OPN | SCM_WRTNG, FUNC_NAME);
 
   if (SCM_UNBNDP (printer))
@@ -399,7 +431,7 @@ SCM
 scm_c_read_string (const char *expr)
 {
   SCM port = scm_mkstrport (SCM_INUM0,
-                           scm_makfrom0str (expr),
+                           scm_from_locale_string (expr),
                            SCM_OPN | SCM_RDNG,
                            "scm_c_read_string");
   SCM form;
@@ -416,13 +448,13 @@ scm_c_read_string (const char *expr)
 SCM
 scm_c_eval_string (const char *expr)
 {
-  return scm_eval_string (scm_makfrom0str (expr));
+  return scm_eval_string (scm_from_locale_string (expr));
 }
 
 SCM
 scm_c_eval_string_in_module (const char *expr, SCM module)
 {
-  return scm_eval_string_in_module (scm_makfrom0str (expr), module);
+  return scm_eval_string_in_module (scm_from_locale_string (expr), module);
 }