Drizzled Public API Documentation

quote.cc

00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include "quote.h"
00023 
00024 #include <drizzled/lex_string.h>
00025 
00026 namespace drizzled
00027 {
00028 
00029 inline
00030 static uint32_t get_esc_bit(unsigned char *mask, unsigned char num)
00031 {
00032   return (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7));
00033 }
00034 
00052 String *Item_func_quote::val_str(String *str)
00053 {
00054   assert(fixed == 1);
00055   /*
00056     Bit mask that has 1 for set for the position of the following characters:
00057     0, \, ' and ^Z
00058   */
00059 
00060   static unsigned char escmask[32]=
00061   {
00062     0x01, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00,
00063     0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
00064     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00065     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00066   };
00067 
00068   char *from, *to, *end, *start;
00069   String *arg= args[0]->val_str(str);
00070   uint32_t arg_length, new_length;
00071   if (!arg)         // Null argument
00072   {
00073     /* Return the string 'NULL' */
00074     str->copy(STRING_WITH_LEN("NULL"), collation.collation);
00075     null_value= 0;
00076     return str;
00077   }
00078 
00079   arg_length= arg->length();
00080   new_length= arg_length+2; /* for beginning and ending ' signs */
00081 
00082   for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++)
00083     new_length+= get_esc_bit(escmask, (unsigned char) *from);
00084 
00085   if (tmp_value.alloc(new_length))
00086     goto null;
00087 
00088   /*
00089     We replace characters from the end to the beginning
00090   */
00091   to= (char*) tmp_value.ptr() + new_length - 1;
00092   *to--= '\'';
00093   for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--)
00094   {
00095     /*
00096       We can't use the bitmask here as we want to replace \O and ^Z with 0
00097       and Z
00098     */
00099     switch (*end)  {
00100     case 0:
00101       *to--= '0';
00102       *to=   '\\';
00103       break;
00104     case '\032':
00105       *to--= 'Z';
00106       *to=   '\\';
00107       break;
00108     case '\'':
00109     case '\\':
00110       *to--= *end;
00111       *to=   '\\';
00112       break;
00113     default:
00114       *to= *end;
00115       break;
00116     }
00117   }
00118   *to= '\'';
00119   tmp_value.length(new_length);
00120   tmp_value.set_charset(collation.collation);
00121   null_value= 0;
00122   return &tmp_value;
00123 
00124 null:
00125   null_value= 1;
00126   return 0;
00127 }
00128 
00129 } /* namespace drizzled */