~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/strfunc.cc

  • Committer: Lee
  • Date: 2009-01-07 22:45:50 UTC
  • mfrom: (772 drizzle)
  • mto: This revision was merged to the branch mainline in revision 777.
  • Revision ID: lbieber@lbieber-desktop-20090107224550-tzjtc8klmv84ppyg
finish enabling tests, remove timezone2, timezone3

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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/* Some useful string utility functions used by the MySQL server */
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
 
{
 
17
#include <drizzled/server_includes.h>
26
18
 
27
19
/*
28
20
  Return bitmap for strings used in a set
62
54
      uint32_t var_len;
63
55
      int mblen= 1;
64
56
 
65
 
      for (; pos != end && *pos != field_separator; pos++) 
66
 
      {}
67
 
      var_len= (uint32_t) (pos - start);
 
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);
68
72
      uint32_t find= cs ? find_type2(lib, start, var_len, cs) :
69
73
                      find_type(lib, start, var_len, (bool) 0);
70
74
      if (!find)
161
165
  return(0);
162
166
} /* find_type */
163
167
 
164
 
} /* namespace drizzled */
 
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
}