Drizzled Public API Documentation

hex_string.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/error.h>
00023 #include <drizzled/field.h>
00024 #include <drizzled/item/hex_string.h>
00025 #include <drizzled/item/string.h>
00026 #include <drizzled/type/decimal.h>
00027 
00028 #include <algorithm>
00029 
00030 using namespace std;
00031 
00032 namespace drizzled
00033 {
00034 
00035 static char _dig_vec_lower[] =
00036   "0123456789abcdefghijklmnopqrstuvwxyz";
00037 
00038 inline uint32_t char_val(char X)
00039 {
00040   return (uint32_t) (X >= '0' && X <= '9' ? X-'0' :
00041                  X >= 'A' && X <= 'Z' ? X-'A'+10 :
00042                  X-'a'+10);
00043 }
00044 
00045 Item_hex_string::Item_hex_string(const char *str, uint32_t str_length)
00046 {
00047   max_length=(str_length+1)/2;
00048   char *ptr=(char*) memory::sql_alloc(max_length+1);
00049   if (!ptr)
00050     return;
00051   str_value.set(ptr,max_length,&my_charset_bin);
00052   char *end=ptr+max_length;
00053   if (max_length*2 != str_length)
00054     *ptr++=char_val(*str++);                    // Not even, assume 0 prefix
00055   while (ptr != end)
00056   {
00057     *ptr++= (char) (char_val(str[0])*16+char_val(str[1]));
00058     str+=2;
00059   }
00060   *ptr=0;                                       // Keep purify happy
00061   collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
00062   fixed= 1;
00063   unsigned_flag= 1;
00064 }
00065 
00066 int64_t Item_hex_string::val_int()
00067 {
00068   // following assert is redundant, because fixed=1 assigned in constructor
00069   assert(fixed == 1);
00070   char *end= (char*) str_value.ptr()+str_value.length(),
00071        *ptr= end - min(str_value.length(), sizeof(int64_t));
00072 
00073   uint64_t value=0;
00074   for (; ptr != end ; ptr++)
00075     value=(value << 8)+ (uint64_t) (unsigned char) *ptr;
00076   return (int64_t) value;
00077 }
00078 
00079 
00080 type::Decimal *Item_hex_string::val_decimal(type::Decimal *decimal_value)
00081 {
00082   // following assert is redundant, because fixed=1 assigned in constructor
00083   assert(fixed == 1);
00084   uint64_t value= (uint64_t)val_int();
00085   int2_class_decimal(E_DEC_FATAL_ERROR, value, true, decimal_value);
00086   return (decimal_value);
00087 }
00088 
00089 int Item_hex_string::save_in_field(Field *field, bool)
00090 {
00091   field->set_notnull();
00092   if (field->result_type() == STRING_RESULT)
00093     return field->store(str_value.ptr(), str_value.length(),
00094                         collation.collation);
00095 
00096   uint64_t nr;
00097   uint32_t length= str_value.length();
00098   if (length > 8)
00099   {
00100     nr= field->flags & UNSIGNED_FLAG ? UINT64_MAX : INT64_MAX;
00101     goto warn;
00102   }
00103   nr= (uint64_t) val_int();
00104   if ((length == 8) && !(field->flags & UNSIGNED_FLAG) && (nr > INT64_MAX))
00105   {
00106     nr= INT64_MAX;
00107     goto warn;
00108   }
00109   return field->store((int64_t) nr, true);  // Assume hex numbers are unsigned
00110 
00111 warn:
00112   if (!field->store((int64_t) nr, true))
00113     field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE,
00114                        1);
00115   return 1;
00116 }
00117 
00118 void Item_hex_string::print(String *str)
00119 {
00120   char *end= (char*) str_value.ptr() + str_value.length(),
00121        *ptr= end - min(str_value.length(), sizeof(int64_t));
00122   str->append("0x");
00123   for (; ptr != end ; ptr++)
00124   {
00125     str->append(_dig_vec_lower[((unsigned char) *ptr) >> 4]);
00126     str->append(_dig_vec_lower[((unsigned char) *ptr) & 0x0F]);
00127   }
00128 }
00129 
00130 
00131 bool Item_hex_string::eq(const Item *arg, bool binary_cmp) const
00132 {
00133   if (arg->basic_const_item() && arg->type() == type())
00134   {
00135     if (binary_cmp)
00136       return !stringcmp(&str_value, &arg->str_value);
00137     return !sortcmp(&str_value, &arg->str_value, collation.collation);
00138   }
00139   return false;
00140 }
00141 
00142 Item *Item_hex_string::safe_charset_converter(const CHARSET_INFO * const tocs)
00143 {
00144   Item_string *conv;
00145   String tmp, *str= val_str(&tmp);
00146 
00147   if (!(conv= new Item_string(str->ptr(), str->length(), tocs)))
00148     return NULL;
00149   conv->str_value.copy();
00150   conv->str_value.mark_as_const();
00151   return conv;
00152 }
00153 
00154 
00155 } /* namespace drizzled */