Make the thread functions a bit easier to use
[ira/wip.git] / lib / util / substitute.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    
5    Copyright (C) Andrew Tridgell 1992-2001
6    Copyright (C) Simo Sorce      2001-2002
7    Copyright (C) Martin Pool     2003
8    Copyright (C) James Peach     2005
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25
26 /**
27  * @file
28  * @brief Substitute utilities.
29  **/
30
31 /**
32  Substitute a string for a pattern in another string. Make sure there is 
33  enough room!
34
35  This routine looks for pattern in s and replaces it with 
36  insert. It may do multiple replacements.
37
38  Any of " ; ' $ or ` in the insert string are replaced with _
39  if len==0 then the string cannot be extended. This is different from the old
40  use of len==0 which was for no length checks to be done.
41 **/
42
43 _PUBLIC_ void string_sub(char *s, const char *pattern, const char *insert, size_t len)
44 {
45         char *p;
46         ssize_t ls, lp, li, i;
47
48         if (!insert || !pattern || !*pattern || !s)
49                 return;
50
51         ls = (ssize_t)strlen(s);
52         lp = (ssize_t)strlen(pattern);
53         li = (ssize_t)strlen(insert);
54
55         if (len == 0)
56                 len = ls + 1; /* len is number of *bytes* */
57
58         while (lp <= ls && (p = strstr(s, pattern))) {
59                 if (ls + (li-lp) >= len) {
60                         DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
61                                  (int)(ls + (li-lp) - len),
62                                  pattern, (int)len));
63                         break;
64                 }
65                 if (li != lp) {
66                         memmove(p+li,p+lp,strlen(p+lp)+1);
67                 }
68                 for (i=0;i<li;i++) {
69                         switch (insert[i]) {
70                         case '`':
71                         case '"':
72                         case '\'':
73                         case ';':
74                         case '$':
75                         case '%':
76                         case '\r':
77                         case '\n':
78                                 p[i] = '_';
79                                 break;
80                         default:
81                                 p[i] = insert[i];
82                         }
83                 }
84                 s = p + li;
85                 ls += (li-lp);
86         }
87 }
88
89 /**
90  * Talloc'ed version of string_sub
91  */
92 _PUBLIC_ char *string_sub_talloc(TALLOC_CTX *mem_ctx, const char *s, 
93                                 const char *pattern, const char *insert)
94 {
95         const char *p;
96         char *ret;
97         size_t len, alloc_len;
98
99         if (insert == NULL || pattern == NULL || !*pattern || s == NULL)
100                 return NULL;
101
102         /* determine length needed */
103         len = strlen(s);
104         
105         for (p = strstr(s, pattern); p != NULL; 
106              p = strstr(p+strlen(pattern), pattern)) {
107                 len += strlen(insert) - strlen(pattern);
108         }
109
110         alloc_len = MAX(len, strlen(s))+1;
111         ret = talloc_array(mem_ctx, char, alloc_len);
112         if (ret == NULL)
113                 return NULL;
114         strncpy(ret, s, alloc_len);
115         string_sub(ret, pattern, insert, alloc_len);
116
117         ret = talloc_realloc(mem_ctx, ret, char, len+1);
118         if (ret == NULL)
119                 return NULL;
120
121         SMB_ASSERT(ret[len] == '\0');
122
123         talloc_set_name_const(ret, ret);
124
125         return ret;
126 }
127
128 /**
129  Similar to string_sub() but allows for any character to be substituted. 
130  Use with caution!
131  if len==0 then the string cannot be extended. This is different from the old
132  use of len==0 which was for no length checks to be done.
133 **/
134
135 _PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
136 {
137         char *p;
138         ssize_t ls,lp,li;
139
140         if (!insert || !pattern || !s)
141                 return;
142
143         ls = (ssize_t)strlen(s);
144         lp = (ssize_t)strlen(pattern);
145         li = (ssize_t)strlen(insert);
146
147         if (!*pattern)
148                 return;
149         
150         if (len == 0)
151                 len = ls + 1; /* len is number of *bytes* */
152         
153         while (lp <= ls && (p = strstr(s,pattern))) {
154                 if (ls + (li-lp) >= len) {
155                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
156                                  (int)(ls + (li-lp) - len),
157                                  pattern, (int)len));
158                         break;
159                 }
160                 if (li != lp) {
161                         memmove(p+li,p+lp,strlen(p+lp)+1);
162                 }
163                 memcpy(p, insert, li);
164                 s = p + li;
165                 ls += (li-lp);
166         }
167 }