Drizzled Public API Documentation

hex_functions.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 <drizzled/charset_info.h>
00023 #include <drizzled/function/str/strfunc.h>
00024 #include <drizzled/internal/m_string.h>
00025 #include <drizzled/plugin/function.h>
00026 #include <drizzled/util/convert.h>
00027 
00028 using namespace drizzled;
00029 
00030 class HexFunction :public Item_str_func
00031 {
00032   String tmp_value;
00033 public:
00034   HexFunction() :Item_str_func() {}
00035   const char *func_name() const { return "hex"; }
00036   String *val_str(String *);
00037   void fix_length_and_dec()
00038   {
00039     collation.set(default_charset());
00040     decimals=0;
00041     max_length=args[0]->max_length*2*collation.collation->mbmaxlen;
00042   }
00043 
00044   bool check_argument_count(int n) { return n == 1; }
00045 };
00046 
00047 class UnHexFunction :public Item_str_func
00048 {
00049   String tmp_value;
00050 public:
00051   UnHexFunction() :Item_str_func()
00052   {
00053     /* there can be bad hex strings */
00054     maybe_null= 1;
00055   }
00056   const char *func_name() const { return "unhex"; }
00057   String *val_str(String *);
00058   void fix_length_and_dec()
00059   {
00060     collation.set(&my_charset_bin);
00061     decimals=0;
00062     max_length=(1+args[0]->max_length)/2;
00063   }
00064   bool check_argument_count(int n) { return n == 1; }
00065 };
00066 
00070 static int hexchar_to_int(char c)
00071 {
00072   if (c <= '9' && c >= '0')
00073     return c-'0';
00074   c|=32;
00075   if (c <= 'f' && c >= 'a')
00076     return c-'a'+10;
00077   return -1;
00078 }
00079 
00080 String *HexFunction::val_str(String *str)
00081 {
00082   String *res;
00083   assert(fixed == 1);
00084   if (args[0]->result_type() != STRING_RESULT)
00085   {
00086     uint64_t dec;
00087     char ans[65],*ptr;
00088     /* Return hex of unsigned int64_t value */
00089     if (args[0]->result_type() == REAL_RESULT ||
00090         args[0]->result_type() == DECIMAL_RESULT)
00091     {
00092       double val= args[0]->val_real();
00093       if ((val <= (double) INT64_MIN) ||
00094           (val >= (double) (uint64_t) UINT64_MAX))
00095         dec=  ~(int64_t) 0;
00096       else
00097         dec= (uint64_t) (val + (val > 0 ? 0.5 : -0.5));
00098     }
00099     else
00100       dec= (uint64_t) args[0]->val_int();
00101 
00102     if ((null_value= args[0]->null_value))
00103       return 0;
00104     ptr= internal::int64_t2str(dec,ans,16);
00105     if (str->copy(ans,(uint32_t) (ptr-ans),default_charset()))
00106       return &my_empty_string;      // End of memory
00107     return str;
00108   }
00109 
00110   /* Convert given string to a hex string, character by character */
00111   res= args[0]->val_str(str);
00112   if (!res || tmp_value.alloc(res->length()*2+1))
00113   {
00114     null_value=1;
00115     return 0;
00116   }
00117   null_value=0;
00118   tmp_value.length(res->length()*2);
00119 
00120   (void) drizzled_string_to_hex((char*) tmp_value.ptr(), res->ptr(),
00121                                 res->length());
00122   return &tmp_value;
00123 }
00124 
00127 String *UnHexFunction::val_str(String *str)
00128 {
00129   const char *from, *end;
00130   char *to;
00131   String *res;
00132   uint32_t length;
00133   assert(fixed == 1);
00134 
00135   res= args[0]->val_str(str);
00136   if (!res || tmp_value.alloc(length= (1+res->length())/2))
00137   {
00138     null_value=1;
00139     return 0;
00140   }
00141 
00142   from= res->ptr();
00143   null_value= 0;
00144   tmp_value.length(length);
00145   to= (char*) tmp_value.ptr();
00146   if (res->length() % 2)
00147   {
00148     int hex_char;
00149     *to++= hex_char= hexchar_to_int(*from++);
00150     if ((null_value= (hex_char == -1)))
00151       return 0;
00152   }
00153   for (end=res->ptr()+res->length(); from < end ; from+=2, to++)
00154   {
00155     int hex_char;
00156     *to= (hex_char= hexchar_to_int(from[0])) << 4;
00157     if ((null_value= (hex_char == -1)))
00158       return 0;
00159     *to|= hex_char= hexchar_to_int(from[1]);
00160     if ((null_value= (hex_char == -1)))
00161       return 0;
00162   }
00163   return &tmp_value;
00164 }
00165 
00166 plugin::Create_function<HexFunction> *hex_function= NULL;
00167 plugin::Create_function<UnHexFunction> *unhex_function= NULL;
00168 
00169 static int initialize(drizzled::module::Context &context)
00170 {
00171   hex_function= new plugin::Create_function<HexFunction>("hex");
00172   unhex_function= new plugin::Create_function<UnHexFunction>("unhex");
00173   context.add(hex_function);
00174   context.add(unhex_function);
00175   return 0;
00176 }
00177 
00178 DRIZZLE_DECLARE_PLUGIN
00179 {
00180   DRIZZLE_VERSION_ID,
00181   "hex_functions",
00182   "1.0",
00183   "Stewart Smith",
00184   "Convert a string to HEX() or from UNHEX()",
00185   PLUGIN_LICENSE_GPL,
00186   initialize, /* Plugin Init */
00187   NULL,   /* depends */
00188   NULL    /* config options */
00189 }
00190 DRIZZLE_DECLARE_PLUGIN_END;