Const casts.
[pspp] / src / libpspp / str.c
index afe32de9f2049bfcc5a80ac7a95b36b348be4cb7..bde4de4be5bb4ee13edf877e217537336debfc0a 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009, 2010 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -23,6 +23,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 
+#include <libpspp/cast.h>
 #include <libpspp/message.h>
 #include <libpspp/pool.h>
 
@@ -1214,13 +1215,24 @@ ds_capacity (const struct string *st)
 char *
 ds_cstr (const struct string *st_)
 {
-  struct string *st = (struct string *) st_;
+  struct string *st = CONST_CAST (struct string *, st_);
   if (st->ss.string == NULL)
     ds_extend (st, 1);
   st->ss.string[st->ss.length] = '\0';
   return st->ss.string;
 }
 
+/* Returns the value of ST as a null-terminated string and then
+   reinitialized ST as an empty string.  The caller must free the
+   returned string with free(). */
+char *
+ds_steal_cstr (struct string *st)
+{
+  char *s = ds_cstr (st);
+  ds_init_empty (st);
+  return s;
+}
+
 /* Reads characters from STREAM and appends them to ST, stopping
    after MAX_LENGTH characters, after appending a newline, or
    after an I/O error or end of file was encountered, whichever
@@ -1228,9 +1240,9 @@ ds_cstr (const struct string *st_)
    to ST, false if no characters were read before an I/O error or
    end of file (or if MAX_LENGTH was 0).
 
-   This function accepts LF, CR LF, and CR sequences as new-line,
-   and translates each of them to a single '\n' new-line
-   character in ST. */
+   This function treats LF and CR LF sequences as new-line,
+   translating each of them to a single '\n' new-line character
+   in ST. */
 bool
 ds_read_line (struct string *st, FILE *stream, size_t max_length)
 {
@@ -1239,21 +1251,36 @@ ds_read_line (struct string *st, FILE *stream, size_t max_length)
   for (length = 0; length < max_length; length++)
     {
       int c = getc (stream);
-      if (c == EOF)
-        break;
-
-      if (c == '\r')
+      switch (c)
         {
+        case EOF:
+          return length > 0;
+
+        case '\n':
+          ds_put_char (st, c);
+          return true;
+
+        case '\r':
           c = getc (stream);
-          if (c != '\n')
+          if (c == '\n')
             {
+              /* CR followed by LF is special: translate to \n. */
+              ds_put_char (st, '\n');
+              return true;
+            }
+          else
+            {
+              /* CR followed by anything else is just CR. */
+              ds_put_char (st, '\r');
+              if (c == EOF)
+                return true;
               ungetc (c, stream);
-              c = '\n';
             }
+          break;
+
+        default:
+          ds_put_char (st, c);
         }
-      ds_put_char (st, c);
-      if (c == '\n')
-        return true;
     }
 
   return length > 0;
@@ -1438,7 +1465,9 @@ ds_relocate (struct string *st)
     {
       ds_clear (st);
       ds_put_cstr (st, rel);
-      free ((char *) rel);
+      /* The documentation for relocate says that casting away const
+       and then freeing is appropriate ... */
+      free (CONST_CAST (char *, rel));
     }
 }