c_str.c
changeset 7 fcde17ef6af6
child 8 4ecd557ebebf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/c_str.c	Thu May 31 00:17:52 2007 +0200
@@ -0,0 +1,150 @@
+#include <stdio.h>
+
+#include "sreplace.h"
+
+/* Complete set of backslash sequences:
+
+ From K&R, The C Programming Language, Chapter 2, Constants.
+
+ \b backspace
+ \?  question mark
+ \f formfeed
+  \' single quote
+ \n newline
+ \" double quote
+ \r carriage return
+ \ooo octal number
+ \t horizontal tab
+ \xhh hexadecimal number 
+ \v vertical tab
+
+ (\\ backslash)
+*/
+
+/* Returns length */
+int parse_backslashes(unsigned char *str)
+{
+  int was_backslash = 0;
+  int was_octal = 0; /* 0 to 3 */
+  int was_hex = 0; /* 0 to 2 */
+  unsigned char *write_str = str;
+  unsigned char *start = str;
+  unsigned char newchar;
+
+  while (*str != 0)
+  {
+    if (*str == '\\' && !was_backslash)
+      was_backslash = 1;
+    else
+    {
+      if (was_octal)
+      {
+        if (was_octal < 3 && *str >= '0' && *str <= '7')
+        {
+          newchar = (newchar * 8) + (*str - '0');
+          was_octal += 1;
+          if (was_octal == 3)
+          {
+            *(write_str++) = newchar;
+            was_octal = 0;
+          }
+        } else /* Didn't come octal char. End of oct string. */
+        {
+          *(write_str++) = newchar;
+          *(write_str++) = *str;
+          was_octal = 0;
+        }
+      }
+      else if (was_hex)
+      {
+        unsigned char base = 0;
+
+        if (*str >= '0' && *str <= '9')
+          base = '0';
+        else if (*str >= 'a' && *str <= 'f')
+          base = 'a' - 10;
+        else if (*str >= 'A' && *str <= 'F')
+          base = 'A' - 10;
+
+        if (base != 0) /* Came hex char */
+        {
+          newchar = (newchar * 16) + (*str - base);
+          was_hex += 1;
+
+          if (was_hex == 3) /* End of hex string */
+          {
+            *(write_str++) = newchar;
+            was_hex = 0;
+          }
+        }
+        else /* Non-hex char came. End of hex string */
+        {
+          *(write_str++) = newchar;
+          *(write_str++) = *str;
+          was_hex = 0;
+        }
+      }
+      else if (was_backslash)
+      { switch(*str)
+        {
+          case '\\':
+            *(write_str++) = '\\';
+            break;
+          case 'n':
+            *(write_str++) = '\n';
+            break;
+          case 't':
+            *(write_str++) = '\t';
+            break;
+          case 'r':
+            *(write_str++) = '\r';
+            break;
+          case 'v':
+            *(write_str++) = '\v';
+            break;
+          case 'f':
+            *(write_str++) = '\f';
+            break;
+          case 'b':
+            *(write_str++) = '\b';
+            break;
+          case '0':
+          case '1':
+          case '2':
+          case '3':
+          case '4':
+          case '5':
+          case '6':
+          case '7':
+            was_octal = 1;
+            newchar = 0;
+            break;
+          case 'x':
+            was_hex = 1;
+            newchar = 0;
+            break;
+          default:
+            *(write_str++) = *str;
+        }
+        was_backslash = 0;
+      }
+      else
+        *(write_str++) = *str;
+    }
+    ++str;
+  }
+  *(write_str) = '\0';
+
+  /* We calculate length with distance between the last
+   * written char and the start of the string */
+  return write_str - start;
+}
+
+void print_hex(FILE *out, const struct String *str)
+{
+    int i;
+
+    fprintf(out, "Length: %i\n", str->length);
+    for (i = 0; i < str->length; ++i)
+        fprintf(out, "%02hhx", str->ptr[i]);
+}