/*
 Escape Quotes written by Mike Olson
 Copyright (c) 2001 Fourthought, Inc. USA.   All Rights Reserved.
 See  http://4suite.org/COPYRIGHT  for license and copyright information
*/

#include <Python.h>
#include <string.h>

static char escape__doc__[] = 
"escape(string) -> string\n\
\n\
Replace all ' with \\' and \\ with \\\\.";


/*
  We need to split the string into a list of strings.  Each of the strings should be ~6000 chars long
  , be UTF-8 encoded, and escaped.  For escaping we use:
  ' --> \\047
  \\ --> \\134
  0x00 --> \\00 
*/


static PyObject *escape(PyObject *self, PyObject *args) {
  char *orig;
  int ctr, newSize, origSize, newCtr;

  PyStringObject *rt;


  if (!PyArg_ParseTuple(args, "s#:escape", &orig,&origSize)) {
    return NULL;
  }

  /*Convert it into a new string, do one pass through to see how long it will be
   */
  newSize = 0;
  for (ctr = 0;ctr < origSize;ctr ++) {
    switch (orig[ctr]) {
    case '\'':
      newSize += 2;
      break;
    case '\\':
      newSize += 4;
      break;
    case '\0':
      newSize += 5;
      break;
    default:
      newSize ++;
    }
  }

  /*Create our results memory*/
  rt = (PyStringObject *)PyString_FromStringAndSize(NULL,newSize);
  if (!rt) {
    return NULL;
  }

  /*Walk again and translate*/
  newCtr = 0;
  for (ctr = 0;ctr < origSize;ctr ++) {
    if (orig[ctr] == '\'') {
      rt->ob_sval[newCtr++] = '\\';
      rt->ob_sval[newCtr++] = '\'';
      /*rt->ob_sval[newCtr++] = '0';
      rt->ob_sval[newCtr++] = '4';
      rt->ob_sval[newCtr++] = '7';*/
    }else if (orig[ctr] == '\\') {
      rt->ob_sval[newCtr++] = '\\';
      rt->ob_sval[newCtr++] = '\\';
      rt->ob_sval[newCtr++] = '\\';
      rt->ob_sval[newCtr++] = '\\';
      /*rt->ob_sval[newCtr++] = '1';
      rt->ob_sval[newCtr++] = '3';
      rt->ob_sval[newCtr++] = '4';*/
    } else if (orig[ctr] == '\0') {
      rt->ob_sval[newCtr++] = '\\';
      rt->ob_sval[newCtr++] = '\\';
      rt->ob_sval[newCtr++] = '0';
      rt->ob_sval[newCtr++] = '0';
      rt->ob_sval[newCtr++] = '0';
    }else{
      rt->ob_sval[newCtr++] = orig[ctr];
    }
  }
  return (PyObject *)rt;
}


static char unescape__doc__[] = 
"unescape(string) -> string\n\
\n\
Convert PostgreSQL escape sequences into normal characters.";



static PyObject *unescape(PyObject *self, PyObject *args) {

  /*Same concept as before except backwards*/
  int ctr,newSize,value,newCtr;
  PyObject *orig,*rt;
  char numBuffer[4];
  
  if (!PyArg_ParseTuple(args, "S:unescape", &orig)) {
    return NULL;
  }


  /* Caluculate the size of the new string */
  newSize = 0;
  for (ctr = 0;ctr < PyString_GET_SIZE(orig); ctr ++) {
    if (PyString_AS_STRING(orig)[ctr] == '\\'){
      if (PyString_AS_STRING(orig)[ctr + 1] == '\\') {
	ctr ++;
      } else {
	/*The next three are an octet*/
	ctr += 3;
      }
    }
    newSize ++;
  }

  /* Shortcut: no escape sequences exist */
  if (newSize == PyString_GET_SIZE(orig)) {
    Py_INCREF(orig);
    return orig;
  }

  /* Allocate the new string */
  rt = PyString_FromStringAndSize(NULL, newSize);
  if (!rt) {
    return NULL;
  }

  numBuffer[3] ='\0';
  newCtr = 0;
  for (ctr = 0; ctr < PyString_GET_SIZE(orig); ctr++) {
    if (PyString_AS_STRING(orig)[ctr] == '\\'){
      /* See what to replace */
      if (PyString_AS_STRING(orig)[ctr + 1] == '\\') {
	PyString_AS_STRING(rt)[newCtr++] = '\\';
	ctr ++;
      } else {
	/*The next three are an octet*/
	strncpy(numBuffer,&(PyString_AS_STRING(orig)[ctr+1]),3);
	value = strtol(numBuffer,NULL,8);
	PyString_AS_STRING(rt)[newCtr++] = (char)value;
	ctr += 3;
      }
    } else {
      PyString_AS_STRING(rt)[newCtr++] = PyString_AS_STRING(orig)[ctr];
    }
  }

  return rt;
}



static PyMethodDef escapeMethods[] = {
     { "escape",  escape,  METH_VARARGS, escape__doc__ },
     { "unescape",  unescape,  METH_VARARGS, unescape__doc__ },
     { NULL, NULL }
};

DL_EXPORT(void) initEscapec(void) {
  PyObject *module, *dict;
  module = Py_InitModule("Escapec", escapeMethods);
  dict = PyModule_GetDict(module);
}
