| 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-1301 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 | |
| 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 | |
| 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 | |