Permalink
Newer
Older
100644 258 lines (209 sloc) 5.02 KB
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
/*
3
* lt-string.c
4
* Copyright (C) 2011-2012 Akira TAGOH
5
*
6
* Authors:
7
* Akira TAGOH <akira@tagoh.org>
8
*
9
* You may distribute under the terms of either the GNU
10
* Lesser General Public License or the Mozilla Public
11
* License, as specified in the README file.
12
*/
13
#ifdef HAVE_CONFIG_H
14
#include "config.h"
15
#endif
16
17
#include <glib.h> /* XXX: just shut up GHashTable dependency in lt-mem.h */
18
#include <stdlib.h>
19
#include <string.h>
20
#include "lt-mem.h"
21
#include "lt-messages.h"
22
#include "lt-utils.h"
23
#include "lt-string.h"
24
25
#define LT_STRING_SIZE 128
26
27
struct _lt_string_t {
28
lt_mem_t parent;
29
char *string;
30
size_t len;
31
size_t allocated_len;
32
};
33
34
lt_bool_t _lt_string_expand(lt_string_t *string,
35
size_t size);
36
37
/*< private >*/
38
lt_bool_t
39
_lt_string_expand(lt_string_t *string,
40
size_t size)
41
{
42
string->allocated_len += LT_ALIGNED_TO_POINTER (size + LT_STRING_SIZE);
43
lt_mem_delete_ref(&string->parent, string->string);
44
string->string = realloc(string->string, string->allocated_len);
45
if (!string->string) {
46
string->len = 0;
47
string->allocated_len = 0;
48
49
return FALSE;
50
}
51
lt_mem_add_ref(&string->parent, string->string, free);
52
53
return TRUE;
54
}
55
56
/*< protected >*/
57
58
/*< public >*/
59
lt_string_t *
60
lt_string_new(const char *string)
61
{
62
lt_string_t *retval = lt_mem_alloc_object(sizeof (lt_string_t));
63
64
if (retval) {
65
retval->len = string ? strlen(string) : 0;
66
retval->allocated_len = LT_ALIGNED_TO_POINTER (retval->len + LT_STRING_SIZE);
67
retval->string = malloc(retval->allocated_len);
68
if (!retval->string) {
69
lt_mem_unref(&retval->parent);
70
return NULL;
71
}
72
if (string)
73
strcpy(retval->string, string);
74
else
75
retval->string[retval->len] = 0;
76
lt_mem_add_ref(&retval->parent, retval->string, free);
77
}
78
79
return retval;
80
}
81
82
lt_string_t *
83
lt_string_ref(lt_string_t *string)
84
{
85
lt_return_val_if_fail (string != NULL, NULL);
86
87
return lt_mem_ref(&string->parent);
88
}
89
90
void
91
lt_string_unref(lt_string_t *string)
92
{
93
if (string)
94
lt_mem_unref(&string->parent);
95
}
96
97
char *
98
lt_string_free(lt_string_t *string,
99
lt_bool_t free_segment)
100
{
101
char *retval = NULL;
102
103
if (!free_segment) {
104
lt_mem_delete_ref(&string->parent, string->string);
105
retval = string->string;
106
}
107
lt_string_unref(string);
108
109
return retval;
110
}
111
112
size_t
113
lt_string_length(const lt_string_t *string)
114
{
115
lt_return_val_if_fail (string != NULL, 0);
116
117
return string->len;
118
}
119
120
const char *
121
lt_string_value(const lt_string_t *string)
122
{
123
lt_return_val_if_fail (string != NULL, NULL);
124
125
return string->string;
126
}
127
128
lt_string_t *
129
lt_string_truncate(lt_string_t *string,
130
size_t len)
131
{
132
lt_return_val_if_fail (string != NULL, NULL);
133
134
string->len = LT_MIN (len, string->len);
135
string->string[string->len] = 0;
136
137
return string;
138
}
139
140
void
141
lt_string_clear(lt_string_t *string)
142
{
143
lt_string_truncate(string, 0);
144
}
145
146
lt_bool_t
147
lt_string_append_c(lt_string_t *string,
148
char c)
149
{
150
lt_return_val_if_fail (string != NULL, FALSE);
151
152
if ((string->len + 2) >= string->allocated_len) {
153
if (!_lt_string_expand(string, 1))
154
return FALSE;
155
}
156
string->string[string->len++] = c;
157
string->string[string->len] = 0;
158
159
return TRUE;
160
}
161
162
lt_bool_t
163
lt_string_append(lt_string_t *string,
164
const char *str)
165
{
166
size_t len;
167
168
lt_return_val_if_fail (string != NULL, FALSE);
169
lt_return_val_if_fail (str != NULL, FALSE);
170
171
len = strlen(str);
172
if ((string->len + len + 1) >= string->allocated_len) {
173
if (!_lt_string_expand(string, len))
174
return FALSE;
175
}
176
strncpy(&string->string[string->len], str, len);
177
string->len += len;
178
string->string[string->len] = 0;
179
180
return TRUE;
181
}
182
183
lt_bool_t
184
lt_string_append_filename(lt_string_t *string,
185
const char *path,
186
...)
187
{
188
lt_bool_t retval = FALSE;
189
va_list ap;
190
const char *p;
191
192
lt_return_val_if_fail (string != NULL, FALSE);
193
lt_return_val_if_fail (path != NULL, FALSE);
194
195
if (lt_string_length(string) == 0)
196
retval |= !lt_string_append(string, LT_DIR_SEPARATOR_S);
197
198
va_start(ap, path);
199
p = path;
200
while (p && !retval) {
201
if (lt_string_at(string, -1) != LT_DIR_SEPARATOR)
202
retval |= !lt_string_append(string, LT_DIR_SEPARATOR_S);
203
retval |= !lt_string_append(string, p);
204
p = (const char *)va_arg(ap, const char *);
205
}
206
207
return !retval;
208
}
209
210
lt_bool_t
211
lt_string_append_printf(lt_string_t *string,
212
const char *format,
213
...)
214
{
215
va_list ap;
216
char *str;
217
lt_bool_t retval;
218
219
lt_return_val_if_fail (string != NULL, FALSE);
220
lt_return_val_if_fail (format != NULL, FALSE);
221
222
va_start(ap, format);
223
str = lt_strdup_vprintf(format, ap);
224
retval = lt_string_append(string, str);
225
free(str);
226
227
va_end(ap);
228
229
return retval;
230
}
231
232
lt_string_t *
233
lt_string_replace_c(lt_string_t *string,
234
size_t pos,
235
char c)
236
{
237
lt_return_val_if_fail (string != NULL, NULL);
238
lt_return_val_if_fail (pos < string->len, NULL);
239
240
string->string[pos] = c;
241
242
return string;
243
}
244
245
char
246
lt_string_at(lt_string_t *string,
247
ssize_t pos)
248
{
249
lt_return_val_if_fail (string != NULL, 0);
250
251
if (pos < 0)
252
pos = string->len + pos;
253
pos = LT_MAX (pos, 0);
254
pos = LT_MIN (pos, string->len);
255
256
return string->string[pos];
257
}