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/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
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
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;
00107 return str;
00108 }
00109
00110
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,
00187 NULL,
00188 NULL
00189 }
00190 DRIZZLE_DECLARE_PLUGIN_END;