Fix compile time issues
[collectd.git] / src / daemon / utils_subst.c
1 /**
2  * collectd - src/utils_subst.c
3  * Copyright (C) 2008       Sebastian Harl
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Sebastian "tokkee" Harl <sh at tokkee.org>
25  **/
26
27 /*
28  * This module provides functions for string substitution.
29  */
30
31 #include "collectd.h"
32
33 #include "utils/common/common.h"
34 #include "utils_subst.h"
35
36 char *subst(char *buf, size_t buflen, const char *string, size_t off1,
37             size_t off2, const char *replacement) {
38   char *out = buf;
39
40   char const *front;
41   char const *back;
42   size_t front_len;
43   size_t replacement_len;
44   size_t back_len;
45
46   if ((NULL == buf) || (0 == buflen) || (NULL == string) ||
47       (NULL == replacement))
48     return NULL;
49
50   size_t string_len = strlen(string);
51   if ((off1 > string_len) || (off2 > string_len) || (off1 > off2))
52     return NULL;
53
54   front = string;
55   back = string + off2;
56   front_len = off1;
57   replacement_len = strlen(replacement);
58   back_len = strlen(back);
59
60   if (front_len >= buflen) {
61     front_len = buflen - 1;
62     replacement_len = 0;
63     back_len = 0;
64   } else if ((front_len + replacement_len) >= buflen) {
65     replacement_len = buflen - (front_len + 1);
66     back_len = 0;
67   } else if ((front_len + replacement_len + back_len) >= buflen) {
68     back_len = buflen - (front_len + replacement_len + 1);
69   } else {
70     buflen = front_len + replacement_len + back_len + 1;
71   }
72   assert((front_len + replacement_len + back_len) == (buflen - 1));
73
74   if (front_len != 0) {
75     sstrncpy(out, front, front_len + 1);
76     out += front_len;
77   }
78
79   if (replacement_len != 0) {
80     sstrncpy(out, replacement, replacement_len + 1);
81     out += replacement_len;
82   }
83
84   if (back_len != 0) {
85     sstrncpy(out, back, back_len + 1);
86     out += back_len;
87   }
88
89   out[0] = 0;
90   return buf;
91 } /* subst */
92
93 char *subst_string(char *buf, size_t buflen, const char *string,
94                    const char *needle, const char *replacement) {
95   size_t needle_len;
96   size_t i;
97
98   if ((buf == NULL) || (string == NULL) || (needle == NULL) ||
99       (replacement == NULL))
100     return NULL;
101
102   needle_len = strlen(needle);
103   sstrncpy(buf, string, buflen);
104
105   /* Limit the loop to prevent endless loops. */
106   for (i = 0; i < buflen; i++) {
107     char temp[buflen];
108     char *begin_ptr;
109     size_t begin;
110
111     /* Find `needle' in `buf'. */
112     begin_ptr = strstr(buf, needle);
113     if (begin_ptr == NULL)
114       break;
115
116     /* Calculate the start offset. */
117     begin = begin_ptr - buf;
118
119     /* Substitute the region using `subst'. The result is stored in
120      * `temp'. */
121     begin_ptr =
122         subst(temp, buflen, buf, begin, begin + needle_len, replacement);
123     if (begin_ptr == NULL) {
124       WARNING("subst_string: subst failed.");
125       break;
126     }
127
128     /* Copy the new string in `temp' to `buf' for the next round. */
129     strncpy(buf, temp, buflen);
130   }
131
132   if (i >= buflen) {
133     WARNING("subst_string: Loop exited after %" PRIsz " iterations: "
134             "string = %s; needle = %s; replacement = %s;",
135             i, string, needle, replacement);
136   }
137
138   return buf;
139 } /* char *subst_string */