~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/strfunc.cc

  • Committer: Brian Aker
  • Date: 2010-12-08 22:35:56 UTC
  • mfrom: (1819.9.158 update-innobase)
  • Revision ID: brian@tangent.org-20101208223556-37mi4omqg7lkjzf3
Merge in Stewart's changes, 1.3 changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
15
 
16
16
/* Some useful string utility functions used by the MySQL server */
17
 
#include <drizzled/server_includes.h>
 
17
#include "config.h"
 
18
 
 
19
#include "drizzled/strfunc.h"
 
20
#include "drizzled/typelib.h"
 
21
#include "drizzled/charset_info.h"
 
22
#include "drizzled/global_charset_info.h"
 
23
 
 
24
namespace drizzled
 
25
{
18
26
 
19
27
/*
20
28
  Return bitmap for strings used in a set
47
55
  *err_pos= 0;                  // No error yet
48
56
  if (str != end)
49
57
  {
50
 
    const char *start= str;    
 
58
    const char *start= str;
51
59
    for (;;)
52
60
    {
53
61
      const char *pos= start;
54
62
      uint32_t var_len;
55
63
      int mblen= 1;
56
64
 
57
 
      if (cs && cs->mbminlen > 1)
58
 
      {
59
 
        for ( ; pos < end; pos+= mblen)
60
 
        {
61
 
          my_wc_t wc;
62
 
          if ((mblen= cs->cset->mb_wc(cs, &wc, (const unsigned char *) pos, 
63
 
                                               (const unsigned char *) end)) < 1)
64
 
            mblen= 1; // Not to hang on a wrong multibyte sequence
65
 
          if (wc == (my_wc_t) field_separator)
66
 
            break;
67
 
        }
68
 
      }
69
 
      else
70
 
        for (; pos != end && *pos != field_separator; pos++) ;
71
 
      var_len= (uint) (pos - start);
 
65
      for (; pos != end && *pos != field_separator; pos++) 
 
66
      {}
 
67
      var_len= (uint32_t) (pos - start);
72
68
      uint32_t find= cs ? find_type2(lib, start, var_len, cs) :
73
69
                      find_type(lib, start, var_len, (bool) 0);
74
70
      if (!find)
113
109
  const char *j;
114
110
  for (uint32_t pos=0 ; (j=lib->type_names[pos++]) ; )
115
111
  {
116
 
    for (i=find ; i != end && 
117
 
           my_toupper(system_charset_info,*i) == 
 
112
    for (i=find ; i != end &&
 
113
           my_toupper(system_charset_info,*i) ==
118
114
           my_toupper(system_charset_info,*j) ; i++, j++) ;
119
115
    if (i == end)
120
116
    {
165
161
  return(0);
166
162
} /* find_type */
167
163
 
168
 
 
169
 
/*
170
 
  Un-hex all elements in a typelib
171
 
 
172
 
  SYNOPSIS
173
 
   unhex_type2()
174
 
   interval       TYPELIB (struct of pointer to values + lengths + count)
175
 
 
176
 
  NOTES
177
 
 
178
 
  RETURN
179
 
    N/A
180
 
*/
181
 
 
182
 
void unhex_type2(TYPELIB *interval)
183
 
{
184
 
  for (uint32_t pos= 0; pos < interval->count; pos++)
185
 
  {
186
 
    char *from, *to;
187
 
    for (from= to= (char*) interval->type_names[pos]; *from; )
188
 
    {
189
 
      /*
190
 
        Note, hexchar_to_int(*from++) doesn't work
191
 
        one some compilers, e.g. IRIX. Looks like a compiler
192
 
        bug in inline functions in combination with arguments
193
 
        that have a side effect. So, let's use from[0] and from[1]
194
 
        and increment 'from' by two later.
195
 
      */
196
 
 
197
 
      *to++= (char) (hexchar_to_int(from[0]) << 4) +
198
 
                     hexchar_to_int(from[1]);
199
 
      from+= 2;
200
 
    }
201
 
    interval->type_lengths[pos] /= 2;
202
 
  }
203
 
}
204
 
 
205
 
 
206
 
/*
207
 
  Check if the first word in a string is one of the ones in TYPELIB
208
 
 
209
 
  SYNOPSIS
210
 
    check_word()
211
 
    lib         TYPELIB
212
 
    val         String to check
213
 
    end         End of input
214
 
    end_of_word Store value of last used byte here if we found word
215
 
 
216
 
  RETURN
217
 
    0    No matching value
218
 
    > 1  lib->type_names[#-1] matched
219
 
         end_of_word will point to separator character/end in 'val'
220
 
*/
221
 
 
222
 
uint32_t check_word(TYPELIB *lib, const char *val, const char *end,
223
 
                const char **end_of_word)
224
 
{
225
 
  int res;
226
 
  const char *ptr;
227
 
 
228
 
  /* Fiend end of word */
229
 
  for (ptr= val ; ptr < end && my_isalpha(&my_charset_utf8_general_ci, *ptr) ; ptr++)
230
 
    ;
231
 
  if ((res=find_type(lib, val, (uint) (ptr - val), 1)) > 0)
232
 
    *end_of_word= ptr;
233
 
  return res;
234
 
}
235
 
 
236
 
 
237
 
/*
238
 
  Converts a string between character sets
239
 
 
240
 
  SYNOPSIS
241
 
    strconvert()
242
 
    from_cs       source character set
243
 
    from          source, a null terminated string
244
 
    to            destination buffer
245
 
    to_length     destination buffer length
246
 
 
247
 
  NOTES
248
 
    'to' is always terminated with a '\0' character.
249
 
    If there is no enough space to convert whole string,
250
 
    only prefix is converted, and terminated with '\0'.
251
 
 
252
 
  RETURN VALUES
253
 
    result string length
254
 
*/
255
 
 
256
 
 
257
 
uint32_t strconvert(const CHARSET_INFO * const from_cs, const char *from,
258
 
                const CHARSET_INFO * const to_cs, char *to, uint32_t to_length, uint32_t *errors)
259
 
{
260
 
  int cnvres;
261
 
  my_wc_t wc;
262
 
  char *to_start= to;
263
 
  unsigned char *to_end= (unsigned char*) to + to_length - 1;
264
 
  my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
265
 
  my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
266
 
  uint32_t error_count= 0;
267
 
 
268
 
  while (1)
269
 
  {
270
 
    /*
271
 
      Using 'from + 10' is safe:
272
 
      - it is enough to scan a single character in any character set.
273
 
      - if remaining string is shorter than 10, then mb_wc will return
274
 
        with error because of unexpected '\0' character.
275
 
    */
276
 
    if ((cnvres= (*mb_wc)(from_cs, &wc,
277
 
                          (unsigned char*) from, (unsigned char*) from + 10)) > 0)
278
 
    {
279
 
      if (!wc)
280
 
        break;
281
 
      from+= cnvres;
282
 
    }
283
 
    else if (cnvres == MY_CS_ILSEQ)
284
 
    {
285
 
      error_count++;
286
 
      from++;
287
 
      wc= '?';
288
 
    }
289
 
    else
290
 
      break; // Impossible char.
291
 
 
292
 
outp:
293
 
 
294
 
    if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
295
 
      to+= cnvres;
296
 
    else if (cnvres == MY_CS_ILUNI && wc != '?')
297
 
    {
298
 
      error_count++;
299
 
      wc= '?';
300
 
      goto outp;
301
 
    }
302
 
    else
303
 
      break;
304
 
  }
305
 
  *to= '\0';
306
 
  *errors= error_count;
307
 
  return (uint32_t) (to - to_start);
308
 
 
309
 
}
310
 
 
311
 
 
312
 
/*
313
 
  Searches for a LEX_STRING in an LEX_STRING array.
314
 
 
315
 
  SYNOPSIS
316
 
    find_string_in_array()
317
 
      heap    The array
318
 
      needle  The string to search for
319
 
 
320
 
  NOTE
321
 
    The last LEX_STRING in the array should have str member set to NULL
322
 
 
323
 
  RETURN VALUES
324
 
    -1   Not found
325
 
    >=0  Ordinal position
326
 
*/
327
 
 
328
 
int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle,
329
 
                         const CHARSET_INFO * const cs)
330
 
{
331
 
  const LEX_STRING *pos;
332
 
  for (pos= haystack; pos->str; pos++)
333
 
    if (!cs->coll->strnncollsp(cs, (unsigned char *) pos->str, pos->length,
334
 
                               (unsigned char *) needle->str, needle->length, 0))
335
 
    {
336
 
      return (pos - haystack);
337
 
    }
338
 
  return -1;
339
 
}
 
164
} /* namespace drizzled */