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