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
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++);
00055 while (ptr != end)
00056 {
00057 *ptr++= (char) (char_val(str[0])*16+char_val(str[1]));
00058 str+=2;
00059 }
00060 *ptr=0;
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
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
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);
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 }