#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/**
 * Exercise 3-2.  Write a function escape(s,t) that converts 
 * characters like newline and tab into visible escape sequences 
 * like \n and \t as it copies the string t to s.  Write a 
 * function for the other direction as well, converting escape 
 * sequences into the real characters.
 */

char* encode(char*,char*);
char* decode(char*,char*);

/* build: build a random string of size sz */
char* build(int sz)
{
   int i;

   srand(time(NULL));

   char* s = (char*)malloc(sz+1);
   for(i=0; i<sz; i++) {
      char c = (char) (rand() % 128);
      s[i] = (c == 0) ? 'a' : c;
   }
   s[i] = '\0';
   return s;
}

int main(void)
{
   char* s = build(5);
   char* t = build(10);

   printf("Regular: %s\n", s);
   printf("Encoded: %s\n", encode(s,t));
   printf("Decoded: %s\n", decode(s,t));

   free(s);
   free(t);

   return 0;
}

char* encode(char* source, char* sink)
{
   int i,j;

   for(i=j=0; source[i]!='\0'; i++) {
      switch(source[i]) {
         case '\n':
            sink[j++] = '\\';
            sink[j++] = 'n';
         case '\t':
            sink[j++] = '\\';
            sink[j++] = 't';
            break;
         case '\v':
            sink[j++] = '\\';
            sink[j++] = 'v';
            break;
         case '\b':
            sink[j++] = '\\';
            sink[j++] = 'b';
            break;
         case '\r':
            sink[j++] = '\\';
            sink[j++] = 'r';
            break;
         case '\f':
            sink[j++] = '\\';
            sink[j++] = 'f';
            break;
         case '\\':
            sink[j++] = '\\';
            sink[j++] = '\\';
            break;
         case '\?':
            sink[j++] = '\\';
            sink[j++] = '\?';
            break;
         case '\'':
            sink[j++] = '\\';
            sink[j++] = '\'';
            break;
         case '\"':
            sink[j++] = '\\';
            sink[j++] = '\"';
            break;
         default:
            sink[j++] = source[i];
      }
   }
   sink[j] = '\0';
   return sink;
}

char* decode(char* sink, char* source)
{
   int i,j;

   for(i=j=0; source[j]!='\0'; j++) {
      if(source[j] == '\\') {
         switch(source[++j]) {
            case 'n':
               sink[i++] = '\n';
               break;
            case 't':
               sink[i++] = '\t';
               break;
            case 'v':
               sink[i++] = '\v';
               break;
            case 'b':
               sink[i++] = '\b';
               break;
            case 'r':
               sink[i++] = '\r';
               break;
            case 'f':
               sink[i++] = '\f';
               break;
            case '\\':
               sink[i++] = '\\';
               break;
            case '\?':
               sink[i++] = '\?';
               break;
            case '\'':
               sink[i++] = '\'';
               break;
            case '\"':
               sink[i++] = '\\';
               break;
         }
      } else {
         sink[i++] = source[j];
      }
   }
   sink[i] = '\0';
   return sink;
}
