1 #ifndef __GTK_ISTRING_PRIVATE_H__
2 #define __GTK_ISTRING_PRIVATE_H__
3
4 #include <glib.h>
5 #include <string.h>
6
7 typedef struct
8 {
9 guint n_bytes;
10 guint n_chars;
11 union {
12 char buf[24];
13 char *str;
14 } u;
15 } IString;
16
17 static inline gboolean
istring_is_inline(const IString * str)18 istring_is_inline (const IString *str)
19 {
20 return str->n_bytes <= (sizeof str->u.buf - 1);
21 }
22
23 static inline char *
istring_str(IString * str)24 istring_str (IString *str)
25 {
26 if (istring_is_inline (str))
27 return str->u.buf;
28 else
29 return str->u.str;
30 }
31
32 static inline void
istring_clear(IString * str)33 istring_clear (IString *str)
34 {
35 if (istring_is_inline (str))
36 str->u.buf[0] = 0;
37 else
38 g_clear_pointer (&str->u.str, g_free);
39
40 str->n_bytes = 0;
41 str->n_chars = 0;
42 }
43
44 static inline void
istring_set(IString * str,const char * text,guint n_bytes,guint n_chars)45 istring_set (IString *str,
46 const char *text,
47 guint n_bytes,
48 guint n_chars)
49 {
50 if G_LIKELY (n_bytes <= (sizeof str->u.buf - 1))
51 {
52 memcpy (str->u.buf, text, n_bytes);
53 str->u.buf[n_bytes] = 0;
54 }
55 else
56 {
57 str->u.str = g_strndup (text, n_bytes);
58 }
59
60 str->n_bytes = n_bytes;
61 str->n_chars = n_chars;
62 }
63
64 static inline gboolean
istring_empty(IString * str)65 istring_empty (IString *str)
66 {
67 return str->n_bytes == 0;
68 }
69
70 static inline gboolean
istring_ends_with_space(IString * str)71 istring_ends_with_space (IString *str)
72 {
73 return g_ascii_isspace (istring_str (str)[str->n_bytes - 1]);
74 }
75
76 static inline gboolean
istring_starts_with_space(IString * str)77 istring_starts_with_space (IString *str)
78 {
79 return g_unichar_isspace (g_utf8_get_char (istring_str (str)));
80 }
81
82 static inline gboolean
istring_contains_unichar(IString * str,gunichar ch)83 istring_contains_unichar (IString *str,
84 gunichar ch)
85 {
86 return g_utf8_strchr (istring_str (str), str->n_bytes, ch) != NULL;
87 }
88
89 static inline gboolean
istring_only_contains_space(IString * str)90 istring_only_contains_space (IString *str)
91 {
92 const char *iter;
93
94 for (iter = istring_str (str); *iter; iter = g_utf8_next_char (iter))
95 {
96 if (!g_unichar_isspace (g_utf8_get_char (iter)))
97 return FALSE;
98 }
99
100 return TRUE;
101 }
102
103 static inline gboolean
istring_contains_space(IString * str)104 istring_contains_space (IString *str)
105 {
106 const char *iter;
107
108 for (iter = istring_str (str); *iter; iter = g_utf8_next_char (iter))
109 {
110 if (g_unichar_isspace (g_utf8_get_char (iter)))
111 return TRUE;
112 }
113
114 return FALSE;
115 }
116
117 static inline void
istring_prepend(IString * str,IString * other)118 istring_prepend (IString *str,
119 IString *other)
120 {
121 if G_LIKELY (str->n_bytes + other->n_bytes < sizeof str->u.buf - 1)
122 {
123 memmove (str->u.buf + other->n_bytes, str->u.buf, str->n_bytes);
124 memcpy (str->u.buf, other->u.buf, other->n_bytes);
125 str->n_bytes += other->n_bytes;
126 str->n_chars += other->n_chars;
127 str->u.buf[str->n_bytes] = 0;
128 }
129 else
130 {
131 char *old = NULL;
132
133 if (!istring_is_inline (str))
134 old = str->u.str;
135
136 str->u.str = g_strconcat (istring_str (str), istring_str (other), NULL);
137 str->n_bytes += other->n_bytes;
138 str->n_chars += other->n_chars;
139
140 g_free (old);
141 }
142 }
143
144 static inline void
istring_append(IString * str,IString * other)145 istring_append (IString *str,
146 IString *other)
147 {
148 const char *text = istring_str (other);
149 guint n_bytes = other->n_bytes;
150 guint n_chars = other->n_chars;
151
152 if G_LIKELY (istring_is_inline (str))
153 {
154 if G_LIKELY (str->n_bytes + n_bytes <= (sizeof str->u.buf - 1))
155 memcpy (str->u.buf + str->n_bytes, text, n_bytes);
156 else
157 str->u.str = g_strconcat (str->u.buf, text, NULL);
158 }
159 else
160 {
161 str->u.str = g_realloc (str->u.str, str->n_bytes + n_bytes + 1);
162 memcpy (str->u.str + str->n_bytes, text, n_bytes);
163 }
164
165 str->n_bytes += n_bytes;
166 str->n_chars += n_chars;
167
168 istring_str (str)[str->n_bytes] = 0;
169 }
170
171 #endif /* __GTK_ISTRING_PRIVATE_H__ */
172