1 /* Copyright (c) 2005, 2011, Oracle and/or its affiliates.
2    Copyright (c) 2009-2011, Monty Program Ab
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
16 
17 #include "strings_def.h"
18 #include <m_ctype.h>
19 
20 #define NEQ(A, B) ((A) != (B))
21 #define EQU(A, B) ((A) == (B))
22 
23 /**
24   Macro for the body of the string scanning.
25 
26   @param CS  The character set of the string
27   @param STR Pointer to beginning of string
28   @param END Pointer to one-after-end of string
29   @param ACC Pointer to beginning of accept (or reject) string
30   @param LEN Length of accept (or reject) string
31   @param CMP is a function-like for doing the comparison of two characters.
32  */
33 
34 #define SCAN_STRING(CS, STR, END, ACC, LEN, CMP)                        \
35   do {                                                                  \
36     uint mbl;                                                           \
37     const char *ptr_str, *ptr_acc;                                      \
38     const char *acc_end= (ACC) + (LEN);                                 \
39     for (ptr_str= (STR) ; ptr_str < (END) ; ptr_str+= mbl)              \
40     {                                                                   \
41       mbl= my_charlen_fix((CS), ptr_str, (END));                        \
42       if (mbl < 2)                                                      \
43       {                                                                 \
44         DBUG_ASSERT(mbl == 1);                                          \
45         for (ptr_acc= (ACC) ; ptr_acc < acc_end ; ++ptr_acc)            \
46           if (CMP(*ptr_acc, *ptr_str))                                  \
47             goto end;                                                   \
48       }                                                                 \
49     }                                                                   \
50 end:                                                                    \
51     return (size_t) (ptr_str - (STR));                                  \
52   } while (0)
53 
54 
55 /*
56   my_strchr(cs, str, end, c) returns a pointer to the first place in
57   str where c (1-byte character) occurs, or NULL if c does not occur
58   in str. This function is multi-byte safe.
59   TODO: should be moved to CHARSET_INFO if it's going to be called
60   frequently.
61 */
62 
my_strchr(CHARSET_INFO * cs,const char * str,const char * end,pchar c)63 char *my_strchr(CHARSET_INFO *cs, const char *str, const char *end,
64                 pchar c)
65 {
66   while (str < end)
67   {
68     uint mbl= my_ismbchar(cs, str, end);
69     if (mbl < 2)
70     {
71       if (*str == c)
72         return((char *)str);
73       str++;
74     }
75     else
76       str+= mbl;
77   }
78   return(0);
79 }
80 
81 /**
82   Calculate the length of the initial segment of 'str' which consists
83   entirely of characters not in 'reject'.
84 
85   @note The reject string points to single-byte characters so it is
86   only possible to find the first occurrence of a single-byte
87   character.  Multi-byte characters in 'str' are treated as not
88   matching any character in the reject string.
89 
90   @todo should be moved to CHARSET_INFO if it's going to be called
91   frequently.
92 
93   @internal The implementation builds on the assumption that 'str' is long,
94   while 'reject' is short. So it compares each character in string
95   with the characters in 'reject' in a tight loop over the characters
96   in 'reject'.
97 */
98 
my_strcspn(CHARSET_INFO * cs,const char * str,const char * str_end,const char * reject)99 size_t my_strcspn(CHARSET_INFO *cs, const char *str, const char *str_end,
100                   const char *reject)
101 {
102   SCAN_STRING(cs, str, str_end, reject, strlen(reject), EQU);
103 }
104