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.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 str->copy(ans,(uint32_t) (ptr-ans),default_charset());
00106 return str;
00107 }
00108
00109
00110 res= args[0]->val_str(str);
00111 if (!res)
00112 {
00113 null_value=1;
00114 return 0;
00115 }
00116 null_value=0;
00117 tmp_value.alloc(res->length()*2+1);
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)
00137 {
00138 null_value=1;
00139 return 0;
00140 }
00141 tmp_value.alloc(length= (1+res->length())/2);
00142
00143 from= res->ptr();
00144 null_value= 0;
00145 tmp_value.length(length);
00146 to= (char*) tmp_value.ptr();
00147 if (res->length() % 2)
00148 {
00149 int hex_char;
00150 *to++= hex_char= hexchar_to_int(*from++);
00151 if ((null_value= (hex_char == -1)))
00152 return 0;
00153 }
00154 for (end=res->ptr()+res->length(); from < end ; from+=2, to++)
00155 {
00156 int hex_char;
00157 *to= (hex_char= hexchar_to_int(from[0])) << 4;
00158 if ((null_value= (hex_char == -1)))
00159 return 0;
00160 *to|= hex_char= hexchar_to_int(from[1]);
00161 if ((null_value= (hex_char == -1)))
00162 return 0;
00163 }
00164 return &tmp_value;
00165 }
00166
00167 plugin::Create_function<HexFunction> *hex_function= NULL;
00168 plugin::Create_function<UnHexFunction> *unhex_function= NULL;
00169
00170 static int initialize(drizzled::module::Context &context)
00171 {
00172 hex_function= new plugin::Create_function<HexFunction>("hex");
00173 unhex_function= new plugin::Create_function<UnHexFunction>("unhex");
00174 context.add(hex_function);
00175 context.add(unhex_function);
00176 return 0;
00177 }
00178
00179 DRIZZLE_DECLARE_PLUGIN
00180 {
00181 DRIZZLE_VERSION_ID,
00182 "hex_functions",
00183 "1.0",
00184 "Stewart Smith",
00185 "Convert a string to HEX() or from UNHEX()",
00186 PLUGIN_LICENSE_GPL,
00187 initialize,
00188 NULL,
00189 NULL
00190 }
00191 DRIZZLE_DECLARE_PLUGIN_END;