/*
$Id: quote.c 10871 2008-03-03 16:50:04Z turnstep $
Copyright (c) 2003-2008 Greg Sabino Mullane and others: see the Changes file
You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the Perl README file.
*/
#include "Pg.h"
char * null_quote(const char *string, STRLEN len, STRLEN *retlen)
{
dTHX;
char *result;
New(0, result, len+1, char);
strncpy(result,string,len);
result[len]='\0';
*retlen = len;
return result;
}
char * quote_string(const char *string, STRLEN len, STRLEN *retlen)
{
dTHX;
char * result;
STRLEN oldlen = len;
const char * const tmp = string;
(*retlen) = 2;
while (len > 0 && *string != '\0') {
if (*string == '\'' || *string == '\\') {
(*retlen)++;
}
(*retlen)++;
string++;
len--;
}
string = tmp;
New(0, result, 1+(*retlen), char);
*result++ = '\'';
len = oldlen;
while (len > 0 && *string != '\0') {
if (*string == '\'' || *string == '\\') {
*result++ = *string;
}
*result++ = *string++;
len--;
}
*result++ = '\'';
*result = '\0';
return result - (*retlen);
}
char * quote_geom(const char *string, STRLEN len, STRLEN *retlen)
{
dTHX;
char * result;
const char *tmp;
len = 0; /* stops compiler warnings. Remove entirely someday */
tmp = string;
(*retlen) = 2;
while (*string != '\0') {
if (*string !=9 && *string != 32 && *string != '(' && *string != ')'
&& *string != ',' && (*string < '0' || *string > '9'))
croak("Invalid input for geometric type");
(*retlen)++;
string++;
}
string = tmp;
New(0, result, 1+(*retlen), char);
*result++ = '\'';
while (*string != '\0') {
*result++ = *string++;
}
*result++ = '\'';
*result = '\0';
return result - (*retlen);
}
char * quote_path(const char *string, STRLEN len, STRLEN *retlen)
{
dTHX;
char * result;
const char * const tmp = string;
len = 0; /* stops compiler warnings. Remove entirely someday */
(*retlen) = 2;
while (*string != '\0') {
if (*string !=9 && *string != 32 && *string != '(' && *string != ')'
&& *string != ',' && *string != '[' && *string != ']'
&& (*string < '0' || *string > '9'))
croak("Invalid input for geometric path type");
(*retlen)++;
string++;
}
string = tmp;
New(0, result, 1+(*retlen), char);
*result++ = '\'';
while (*string != '\0') {
*result++ = *string++;
}
*result++ = '\'';
*result = '\0';
return result - (*retlen);
}
char * quote_circle(const char *string, STRLEN len, STRLEN *retlen)
{
dTHX;
char * result;
const char * const tmp = string;
len = 0; /* stops compiler warnings. Remove entirely someday */
(*retlen) = 2;
while (*string != '\0') {
if (*string !=9 && *string != 32 && *string != '(' && *string != ')'
&& *string != ',' && *string != '<' && *string != '>'
&& (*string < '0' || *string > '9'))
croak("Invalid input for geometric circle type");
(*retlen)++;
string++;
}
string = tmp;
New(0, result, 1+(*retlen), char);
*result++ = '\'';
while (*string != '\0') {
*result++ = *string++;
}
*result++ = '\'';
*result = '\0';
return result - (*retlen);
}
char * quote_bytea(char *string, STRLEN len, STRLEN *retlen)
{
dTHX;
char * result;
STRLEN oldlen = len;
result = string;
(*retlen) = 2;
while (len > 0) {
if (*string == '\'') {
(*retlen) += 2;
}
else if (*string == '\\') {
(*retlen) += 4;
}
else if (*string < 0x20 || *string > 0x7e) {
(*retlen) += 5;
}
else {
(*retlen)++;
}
string++;
len--;
}
string = result;
New(0, result, 1+(*retlen), char);
*result++ = '\'';
len = oldlen;
while (len > 0) {
if (*string == '\'') { /* Single quote becomes double quotes */
*result++ = *string;
*result++ = *string++;
}
else if (*string == '\\') { /* Backslash becomes 4 backslashes */
*result++ = *string;
*result++ = *string++;
*result++ = '\\';
*result++ = '\\';
}
else if (*string < 0x20 || *string > 0x7e) {
(void) snprintf((char *)result, 6, "\\\\%03o", *string++);
result += 5;
}
else {
*result++ = *string++;
}
len--;
}
*result++ = '\'';
*result = '\0';
return (char *)result - (*retlen);
}
char * quote_sql_binary(char *string, STRLEN len, STRLEN *retlen)
{
dTHX;
/* We are going to return a quote_bytea() for backwards compat but
we warn first */
warn("Use of SQL_BINARY invalid in quote()");
return quote_bytea(string, len, retlen);
}
char * quote_bool(const char *value, STRLEN len, STRLEN *retlen)
{
dTHX;
char *result;
long int int_value;
STRLEN max_len=6;
len = 0;
if (isDIGIT(*(const char*)value)) {
/* For now -- will go away when quote* take SVs */
int_value = atoi(value);
} else {
int_value = 42; /* Not true, not false. Just is */
}
New(0, result, max_len, char);
if (0 == int_value)
strncpy(result,"FALSE\0",6);
else if (1 == int_value)
strncpy(result,"TRUE\0",5);
else
croak("Error: Bool must be either 1 or 0");
*retlen = strlen(result);
assert(*retlen+1 <= max_len);
return result;
}
char * quote_integer(const char *value, STRLEN len, STRLEN *retlen)
{
dTHX;
char *result;
STRLEN max_len=6;
const int intval = *((const int*)value);
len = 0;
New(0, result, max_len, char);
if (0 == intval)
strncpy(result,"FALSE\0",6);
else if (1 == intval)
strncpy(result,"TRUE\0",5);
*retlen = strlen(result);
assert(*retlen+1 <= max_len);
return result;
}
void dequote_char(const char *string, STRLEN *retlen)
{
dTHX;
/* TODO: chop_blanks if requested */
*retlen = strlen(string);
}
void dequote_string(const char *string, STRLEN *retlen)
{
dTHX;
*retlen = strlen(string);
}
void dequote_bytea(char *string, STRLEN *retlen)
{
dTHX;
char *result;
(*retlen) = 0;
if (NULL == string)
return;
result = string;
while (*string != '\0') {
(*retlen)++;
if ('\\' == *string) {
if ('\\' == *(string+1)) {
*result++ = '\\';
string +=2;
}
else if (
(*(string+1) >= '0' && *(string+1) <= '3') &&
(*(string+2) >= '0' && *(string+2) <= '7') &&
(*(string+3) >= '0' && *(string+3) <= '7'))
{
*result++ = (*(string+1)-'0')*64 + (*(string+2)-'0')*8 + (*(string+3)-'0');
string += 4;
}
else { /* Invalid escape sequence - ignore the backslash */
(*retlen)--;
string++;
}
}
else {
*result++ = *string++;
}
}
*result = '\0';
return;
}
/*
This one is not used in PG, but since we have a quote_sql_binary,
it might be nice to let people go the other way too. Say when talking
to something that uses SQL_BINARY
*/
void dequote_sql_binary(char *string, STRLEN *retlen)
{
dTHX;
/* We are going to retun a dequote_bytea(), JIC */
warn("Use of SQL_BINARY invalid in dequote()");
dequote_bytea(string, retlen);
return;
/* Put dequote_sql_binary function here at some point */
}
void dequote_bool(char *string, STRLEN *retlen)
{
dTHX;
switch(*string){
case 'f': *string = '0'; break;
case 't': *string = '1'; break;
default:
croak("I do not know how to deal with %c as a bool", *string);
}
*retlen = 1;
}
void null_dequote(const char *string, STRLEN *retlen)
{
dTHX;
*retlen = strlen(string);
}
/* end of quote.c */