1 /*
2 * This file is part of the Advance project.
3 *
4 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Andrea Mazzoleni
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * In addition, as a special exception, Andrea Mazzoleni
21 * gives permission to link the code of this program with
22 * the MAME library (or with modified versions of MAME that use the
23 * same license as MAME), and distribute linked combinations including
24 * the two. You must obey the GNU General Public License in all
25 * respects for all of the code used other than MAME. If you modify
26 * this file, you may extend this exception to your version of the
27 * file, but you are not obligated to do so. If you do not wish to
28 * do so, delete this exception statement from your version.
29 */
30
31 #include "portable.h"
32
33 #include "snstring.h"
34
35 /**
36 * Copy a string with a size limit.
37 * The destination string always has the terminating 0.
38 */
sncpy(char * dst,size_t len,const char * src)39 void sncpy(char* dst, size_t len, const char* src)
40 {
41 if (len) {
42 --len;
43 while (len && *src) {
44 *dst++ = *src++;
45 --len;
46 }
47 *dst = 0;
48 #ifndef NDEBUG
49 ++dst;
50 while (len) {
51 *dst++ = 0x5A;
52 --len;
53 }
54 #endif
55 }
56 }
57
58 /**
59 * Copy a string with a size limit.
60 * The destination string always has the terminating 0.
61 */
sncpyc(char * dst,size_t len,char src)62 void sncpyc(char* dst, size_t len, char src)
63 {
64 sncpyn(dst, len, &src, 1);
65 }
66
67 /**
68 * Copy a string with a size limit and no more than the specified number of chars.
69 * The destination string always has the terminating 0.
70 */
sncpyn(char * dst,size_t len,const char * src,size_t src_len)71 void sncpyn(char* dst, size_t len, const char* src, size_t src_len)
72 {
73 if (len < src_len + 1)
74 sncpy(dst, len, src);
75 else
76 sncpy(dst, src_len + 1, src);
77 }
78
79 /**
80 * Cat a string with a size limit.
81 * The destination string always has the terminating 0.
82 */
sncat(char * dst,size_t len,const char * src)83 void sncat(char* dst, size_t len, const char* src)
84 {
85 while (len && *dst) {
86 ++dst;
87 --len;
88 }
89 sncpy(dst, len, src);
90 }
91
92 /**
93 * Cat a string with a size limit.
94 * The destination string always has the terminating 0.
95 */
sncatc(char * dst,size_t len,char src)96 void sncatc(char* dst, size_t len, char src)
97 {
98 while (len && *dst) {
99 ++dst;
100 --len;
101 }
102 sncpyc(dst, len, src);
103 }
104
105
106 /**
107 * Print at the end of a string with a size limit.
108 * The destination string always has the terminating 0.
109 */
sncatf(char * str,size_t count,const char * fmt,...)110 void sncatf(char* str, size_t count, const char* fmt, ...)
111 {
112 unsigned l;
113 va_list arg;
114 va_start(arg, fmt);
115
116 l = 0;
117 while (l<count && str[l])
118 ++l;
119
120 if (count > l)
121 vsnprintf(str + l, count - l, fmt, arg);
122
123 va_end(arg);
124 }
125
126 /**
127 * Skip a subset of chars.
128 * \param p Index on the string.
129 * \param s String to scan.
130 * \param sep Set of chars to skip.
131 */
sskip(int * p,const char * s,const char * sep)132 void sskip(int* p, const char* s, const char* sep)
133 {
134 while (s[*p] && strchr(sep, s[*p])!=0)
135 ++*p;
136 }
137
138 /**
139 * Extract a token from a string.
140 * \param c Separator character. It's cleared in the string to ensure a 0 termination of the token. It's 0 if the token end the string.
141 * \param p Index on the string. The index is increased at the end of the token or after the separator if present.
142 * \param s String to scan. The string is modified to put the terminating 0 at the end of the token.
143 * \param sep Set of chars to use as separators.
144 * \param ignore Set of chars to ignore. They are removed at the start and at the end of the token. They are not removed after the separator.
145 * \return The extratect token, always 0 terminated.
146 */
stoken(char * c,int * p,char * s,const char * sep,const char * ignore)147 const char* stoken(char* c, int* p, char* s, const char* sep, const char* ignore)
148 {
149 unsigned begin;
150 unsigned end;
151
152 begin = *p;
153
154 while (s[*p] && strchr(sep, s[*p])==0)
155 ++*p;
156
157 end = *p;
158
159 *c = s[*p];
160 if (s[*p]) {
161 s[*p] = 0;
162 ++*p;
163 }
164
165 while (begin < end && strchr(ignore, s[begin])!=0) {
166 ++begin;
167 }
168
169 while (begin < end && strchr(ignore, s[end-1])!=0) {
170 --end;
171 s[end] = 0;
172 }
173
174 return s + begin;
175 }
176
177 /**
178 * Match a glob pattern to a string.
179 * \param s String to compare.
180 * \param glob Pattern to use. The glob chars * and ? are allowed. You can prefix
181 * these char with a backslash to prevent globbing expansion.
182 * \return If the pattern match.
183 */
sglob(const char * s,const char * glob)184 adv_bool sglob(const char* s, const char* glob)
185 {
186 while (*s && *glob) {
187 if (*glob == '*') {
188 if (sglob(s, glob+1))
189 return 1;
190 ++s;
191 continue;
192 }
193
194 if (*glob == '?') {
195 ++glob;
196 ++s;
197 continue;
198 }
199
200 if (glob[0] == '\\' && (glob[1] == '\\' || glob[1] == '*' || glob[1] == '?')) {
201 ++glob;
202 }
203
204 if (*glob != *s) {
205 return 0;
206 }
207
208 ++glob;
209 ++s;
210 }
211
212 while (*glob == '*')
213 ++glob;
214
215 return !*s && !*glob;
216 }
217
218