00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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++);
00054 while (ptr != end)
00055 {
00056 *ptr++= (char) (char_val(str[0])*16+char_val(str[1]));
00057 str+=2;
00058 }
00059 *ptr=0;
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
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
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);
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 }