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 } \
50end: \
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
63char *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
99size_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