syslog-ng source
str-utils.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002-2012 Balabit
3  * Copyright (c) 1998-2012 Balázs Scheidler
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  * As an additional exemption you are allowed to compile & link against the
20  * OpenSSL libraries as published by the OpenSSL project. See the file
21  * COPYING for details.
22  *
23  */
24 
25 #ifndef STR_UTILS_H_INCLUDED
26 #define STR_UTILS_H_INCLUDED 1
27 
28 #include "syslog-ng.h"
29 #include <string.h>
30 
31 /* functions that should be implemented by GLib but they aren't */
32 GString *g_string_assign_len(GString *s, const gchar *val, gint len);
33 gchar *g_string_steal(GString *s);
34 
35 static inline GString *
36 g_string_append_unichar_optimized(GString *string, gunichar wc)
37 {
38  if (wc < 0x80)
39  g_string_append_c(string, (gchar) wc);
40  else
41  g_string_append_unichar(string, wc);
42 
43  return string;
44 }
45 
46 /*
47  * DO NOT USE THIS MACRO UNLESS STRICTLY NECESSARY FOR PERFORMANCE REASONS.
48  *
49  * This macro tries hard to zero-terminate the string without moving it to a
50  * new buffer.
51  *
52  * It is expected to be used at sites where the length is known and where
53  * the input string is expected to be properly NUL terminated but not always.
54  *
55  * The macro checks if the string is indeed NUL terminated and if it is it
56  * just assigns the original pointer to dest. If it's not, it allocates a
57  * new string via g_alloca() so it is automatically freed when the current
58  * scope exits.
59  *
60  * This does not work as an inline function as we use g_alloca() and that
61  * would be freed when the inline function exits (e.g. when it is in fact
62  * not inlined).
63  */
64 #define APPEND_ZERO(dest, value, value_len) \
65  do { \
66  gchar *__buf; \
67  if (G_UNLIKELY(value[value_len] != 0)) \
68  { \
69  /* value is NOT zero terminated */ \
70  \
71  __buf = g_alloca(value_len + 1); \
72  memcpy(__buf, value, value_len); \
73  __buf[value_len] = 0; \
74  } \
75  else \
76  { \
77  /* value is zero terminated */ \
78  __buf = (gchar *) value; \
79  } \
80  dest = __buf; \
81  } while (0)
82 
83 gchar *__normalize_key(const gchar *buffer);
84 gchar *normalize_flag(const gchar *buffer);
85 
86 
87 /* This version of strchr() is optimized for cases where the string we are
88  * looking up characters in is often zero or one character in length. In
89  * those cases we can avoid the strchr() call, which can make a tight loop
90  * doing a lot of strchr() calls a lot faster, especially as this function
91  * is inlined.
92  *
93  * Naming: I originally wanted to use the original function as a prefix
94  * (strchr), however that would potentially pollute the namespace of the
95  * library that we are optimizing. So I've added an underscore prefix in
96  * order not to clash, with that it is still obvious that it intends to
97  * behave the same as strchr().
98  *
99  * NOTE: don't use this unless strchr() really shows up in your profile.
100  */
101 static inline const char *
102 _strchr_optimized_for_single_char_haystack(const char *str, int c)
103 {
104  if (str[0] == c)
105  return str;
106  else if (str[0] == '\0')
107  return NULL;
108  if (str[1] == '\0')
109  {
110  if (c != '\0')
111  return NULL;
112  else
113  return &str[1];
114  }
115  return strchr(str + 1, c);
116 }
117 
118 /*
119  * strsplit() splits the `str` into `maxtokens` pieces.
120  * This version skips multiple `delims`.
121  *
122  */
123 static inline
124 gchar **strsplit(const gchar *str, char delim, gint maxtokens)
125 {
126  if (!str || delim == '\0')
127  return NULL;
128 
129  const gchar *delim_pos = NULL;
130  const gchar *remainder = str;
131  GPtrArray *array = g_ptr_array_new();
132 
133  if (maxtokens < 1)
134  maxtokens = G_MAXINT;
135 
136  for (delim_pos = strchr(remainder, delim); delim_pos && maxtokens; maxtokens--)
137  {
138  const gchar *d = delim_pos;
139  while (d && *d++ == delim);
140  if (!d)
141  break;
142  --d;
143  gint len = delim_pos - remainder;
144 
145  if (len > 0)
146  g_ptr_array_add(array, g_strndup(remainder, len));
147  remainder = d;
148  delim_pos = strchr(remainder, delim);
149  }
150 
151  if (remainder)
152  g_ptr_array_add(array, g_strdup(remainder));
153  g_ptr_array_add(array, NULL);
154 
155  return (gchar **) g_ptr_array_free(array, FALSE);
156 }
157 
158 #endif
gchar * __normalize_key(const gchar *buffer)
Definition: str-utils.c:68
gchar * g_string_steal(GString *s)
Definition: str-utils.c:36
gchar * normalize_flag(const gchar *buffer)
Definition: str-utils.c:74
GString * g_string_assign_len(GString *s, const gchar *val, gint len)
Definition: str-utils.c:27
GString * buffer
Definition: test_smart_multi_line.c:69