c_str.c
changeset 7 fcde17ef6af6
child 8 4ecd557ebebf
equal deleted inserted replaced
6:7dd3bdec0ad2 7:fcde17ef6af6
       
     1 #include <stdio.h>
       
     2 
       
     3 #include "sreplace.h"
       
     4 
       
     5 /* Complete set of backslash sequences:
       
     6 
       
     7  From K&R, The C Programming Language, Chapter 2, Constants.
       
     8 
       
     9  \b backspace
       
    10  \?  question mark
       
    11  \f formfeed
       
    12   \' single quote
       
    13  \n newline
       
    14  \" double quote
       
    15  \r carriage return
       
    16  \ooo octal number
       
    17  \t horizontal tab
       
    18  \xhh hexadecimal number 
       
    19  \v vertical tab
       
    20 
       
    21  (\\ backslash)
       
    22 */
       
    23 
       
    24 /* Returns length */
       
    25 int parse_backslashes(unsigned char *str)
       
    26 {
       
    27   int was_backslash = 0;
       
    28   int was_octal = 0; /* 0 to 3 */
       
    29   int was_hex = 0; /* 0 to 2 */
       
    30   unsigned char *write_str = str;
       
    31   unsigned char *start = str;
       
    32   unsigned char newchar;
       
    33 
       
    34   while (*str != 0)
       
    35   {
       
    36     if (*str == '\\' && !was_backslash)
       
    37       was_backslash = 1;
       
    38     else
       
    39     {
       
    40       if (was_octal)
       
    41       {
       
    42         if (was_octal < 3 && *str >= '0' && *str <= '7')
       
    43         {
       
    44           newchar = (newchar * 8) + (*str - '0');
       
    45           was_octal += 1;
       
    46           if (was_octal == 3)
       
    47           {
       
    48             *(write_str++) = newchar;
       
    49             was_octal = 0;
       
    50           }
       
    51         } else /* Didn't come octal char. End of oct string. */
       
    52         {
       
    53           *(write_str++) = newchar;
       
    54           *(write_str++) = *str;
       
    55           was_octal = 0;
       
    56         }
       
    57       }
       
    58       else if (was_hex)
       
    59       {
       
    60         unsigned char base = 0;
       
    61 
       
    62         if (*str >= '0' && *str <= '9')
       
    63           base = '0';
       
    64         else if (*str >= 'a' && *str <= 'f')
       
    65           base = 'a' - 10;
       
    66         else if (*str >= 'A' && *str <= 'F')
       
    67           base = 'A' - 10;
       
    68 
       
    69         if (base != 0) /* Came hex char */
       
    70         {
       
    71           newchar = (newchar * 16) + (*str - base);
       
    72           was_hex += 1;
       
    73 
       
    74           if (was_hex == 3) /* End of hex string */
       
    75           {
       
    76             *(write_str++) = newchar;
       
    77             was_hex = 0;
       
    78           }
       
    79         }
       
    80         else /* Non-hex char came. End of hex string */
       
    81         {
       
    82           *(write_str++) = newchar;
       
    83           *(write_str++) = *str;
       
    84           was_hex = 0;
       
    85         }
       
    86       }
       
    87       else if (was_backslash)
       
    88       { switch(*str)
       
    89         {
       
    90           case '\\':
       
    91             *(write_str++) = '\\';
       
    92             break;
       
    93           case 'n':
       
    94             *(write_str++) = '\n';
       
    95             break;
       
    96           case 't':
       
    97             *(write_str++) = '\t';
       
    98             break;
       
    99           case 'r':
       
   100             *(write_str++) = '\r';
       
   101             break;
       
   102           case 'v':
       
   103             *(write_str++) = '\v';
       
   104             break;
       
   105           case 'f':
       
   106             *(write_str++) = '\f';
       
   107             break;
       
   108           case 'b':
       
   109             *(write_str++) = '\b';
       
   110             break;
       
   111           case '0':
       
   112           case '1':
       
   113           case '2':
       
   114           case '3':
       
   115           case '4':
       
   116           case '5':
       
   117           case '6':
       
   118           case '7':
       
   119             was_octal = 1;
       
   120             newchar = 0;
       
   121             break;
       
   122           case 'x':
       
   123             was_hex = 1;
       
   124             newchar = 0;
       
   125             break;
       
   126           default:
       
   127             *(write_str++) = *str;
       
   128         }
       
   129         was_backslash = 0;
       
   130       }
       
   131       else
       
   132         *(write_str++) = *str;
       
   133     }
       
   134     ++str;
       
   135   }
       
   136   *(write_str) = '\0';
       
   137 
       
   138   /* We calculate length with distance between the last
       
   139    * written char and the start of the string */
       
   140   return write_str - start;
       
   141 }
       
   142 
       
   143 void print_hex(FILE *out, const struct String *str)
       
   144 {
       
   145     int i;
       
   146 
       
   147     fprintf(out, "Length: %i\n", str->length);
       
   148     for (i = 0; i < str->length; ++i)
       
   149         fprintf(out, "%02hhx", str->ptr[i]);
       
   150 }