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