c_str.c
author viric@llimona
Wed, 04 Jul 2007 21:45:05 +0200
changeset 12 f81dd70a9b0b
parent 8 4ecd557ebebf
permissions -rw-r--r--
Merged stupid changes.

#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]);
}