c_str.c
author viric@llimona
Wed, 04 Jul 2007 21:45:12 +0200
changeset 13 fd73b72d5752
parent 8 4ecd557ebebf
permissions -rw-r--r--
Added tag v0.1 for changeset f81dd70a9b0b

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