~drizzle-trunk/drizzle/development

1300.4.3 by Stewart Smith
move HEX() and UNHEX() to hex_functions plugin.
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
1300.4.3 by Stewart Smith
move HEX() and UNHEX() to hex_functions plugin.
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
20
#include "config.h"
21
#include <drizzled/util/convert.h>
22
#include "drizzled/internal/m_string.h"
23
24
#include <drizzled/plugin/function.h>
25
#include <drizzled/function/str/strfunc.h>
26
27
using namespace drizzled;
28
29
class HexFunction :public Item_str_func
30
{
31
  String tmp_value;
32
public:
33
  HexFunction() :Item_str_func() {}
34
  const char *func_name() const { return "hex"; }
35
  String *val_str(String *);
36
  void fix_length_and_dec()
37
  {
38
    collation.set(default_charset());
39
    decimals=0;
40
    max_length=args[0]->max_length*2*collation.collation->mbmaxlen;
41
  }
42
43
  bool check_argument_count(int n) { return n == 1; }
44
};
45
46
class UnHexFunction :public Item_str_func
47
{
48
  String tmp_value;
49
public:
50
  UnHexFunction() :Item_str_func()
51
  {
52
    /* there can be bad hex strings */
53
    maybe_null= 1;
54
  }
55
  const char *func_name() const { return "unhex"; }
56
  String *val_str(String *);
57
  void fix_length_and_dec()
58
  {
59
    collation.set(&my_charset_bin);
60
    decimals=0;
61
    max_length=(1+args[0]->max_length)/2;
62
  }
63
  bool check_argument_count(int n) { return n == 1; }
64
};
65
66
/**
67
  convert a hex digit into number.
68
*/
69
static int hexchar_to_int(char c)
70
{
71
  if (c <= '9' && c >= '0')
72
    return c-'0';
73
  c|=32;
74
  if (c <= 'f' && c >= 'a')
75
    return c-'a'+10;
76
  return -1;
77
}
78
79
String *HexFunction::val_str(String *str)
80
{
81
  String *res;
82
  assert(fixed == 1);
83
  if (args[0]->result_type() != STRING_RESULT)
84
  {
85
    uint64_t dec;
86
    char ans[65],*ptr;
87
    /* Return hex of unsigned int64_t value */
88
    if (args[0]->result_type() == REAL_RESULT ||
89
        args[0]->result_type() == DECIMAL_RESULT)
90
    {
91
      double val= args[0]->val_real();
92
      if ((val <= (double) INT64_MIN) ||
93
          (val >= (double) (uint64_t) UINT64_MAX))
94
        dec=  ~(int64_t) 0;
95
      else
96
        dec= (uint64_t) (val + (val > 0 ? 0.5 : -0.5));
97
    }
98
    else
99
      dec= (uint64_t) args[0]->val_int();
100
101
    if ((null_value= args[0]->null_value))
102
      return 0;
103
    ptr= internal::int64_t2str(dec,ans,16);
104
    if (str->copy(ans,(uint32_t) (ptr-ans),default_charset()))
105
      return &my_empty_string;			// End of memory
106
    return str;
107
  }
108
109
  /* Convert given string to a hex string, character by character */
110
  res= args[0]->val_str(str);
111
  if (!res || tmp_value.alloc(res->length()*2+1))
112
  {
113
    null_value=1;
114
    return 0;
115
  }
116
  null_value=0;
117
  tmp_value.length(res->length()*2);
118
119
  (void) drizzled_string_to_hex((char*) tmp_value.ptr(), res->ptr(),
120
                                res->length());
121
  return &tmp_value;
122
}
123
124
  /** Convert given hex string to a binary string. */
125
126
String *UnHexFunction::val_str(String *str)
127
{
128
  const char *from, *end;
129
  char *to;
130
  String *res;
131
  uint32_t length;
132
  assert(fixed == 1);
133
134
  res= args[0]->val_str(str);
135
  if (!res || tmp_value.alloc(length= (1+res->length())/2))
136
  {
137
    null_value=1;
138
    return 0;
139
  }
140
141
  from= res->ptr();
142
  null_value= 0;
143
  tmp_value.length(length);
144
  to= (char*) tmp_value.ptr();
145
  if (res->length() % 2)
146
  {
147
    int hex_char;
148
    *to++= hex_char= hexchar_to_int(*from++);
149
    if ((null_value= (hex_char == -1)))
150
      return 0;
151
  }
152
  for (end=res->ptr()+res->length(); from < end ; from+=2, to++)
153
  {
154
    int hex_char;
155
    *to= (hex_char= hexchar_to_int(from[0])) << 4;
156
    if ((null_value= (hex_char == -1)))
157
      return 0;
158
    *to|= hex_char= hexchar_to_int(from[1]);
159
    if ((null_value= (hex_char == -1)))
160
      return 0;
161
  }
162
  return &tmp_value;
163
}
164
165
plugin::Create_function<HexFunction> *hex_function= NULL;
166
plugin::Create_function<UnHexFunction> *unhex_function= NULL;
167
1530.2.6 by Monty Taylor
Moved plugin::Context to module::Context.
168
static int initialize(drizzled::module::Context &context)
1300.4.3 by Stewart Smith
move HEX() and UNHEX() to hex_functions plugin.
169
{
170
  hex_function= new plugin::Create_function<HexFunction>("hex");
171
  unhex_function= new plugin::Create_function<UnHexFunction>("unhex");
1324.2.2 by Monty Taylor
Use the plugin::Context everywhere.
172
  context.add(hex_function);
173
  context.add(unhex_function);
1300.4.3 by Stewart Smith
move HEX() and UNHEX() to hex_functions plugin.
174
  return 0;
175
}
176
177
DRIZZLE_DECLARE_PLUGIN
178
{
179
  DRIZZLE_VERSION_ID,
180
  "hex_functions",
181
  "1.0",
182
  "Stewart Smith",
183
  "Convert a string to HEX() or from UNHEX()",
184
  PLUGIN_LICENSE_GPL,
185
  initialize, /* Plugin Init */
186
  NULL,   /* system variables */
187
  NULL    /* config options */
188
}
189
DRIZZLE_DECLARE_PLUGIN_END;