Subversion Repositories Kolibri OS

Rev

Rev 1905 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1905 serge 1
/*
2
	stringbuf: mimicking a bit of C++ to more safely handle strings
3
 
3960 Serge 4
	copyright 2006-10 by the mpg123 project - free software under the terms of the LGPL 2.1
1905 serge 5
	see COPYING and AUTHORS files in distribution or http://mpg123.org
6
	initially written by Thomas Orgis
7
*/
8
 
9
#include "mpg123lib_intern.h"
10
#include "config.h"
11
#include "mpg123.h"
12
#include "compat.h"
13
#include 
14
#include "debug.h"
15
 
16
void attribute_align_arg mpg123_init_string(mpg123_string* sb)
17
{
18
	sb->p = NULL;
19
	sb->size = 0;
20
	sb->fill = 0;
21
}
22
 
23
void attribute_align_arg mpg123_free_string(mpg123_string* sb)
24
{
25
	if(sb->p != NULL) free(sb->p);
26
	mpg123_init_string(sb);
27
}
28
 
29
int attribute_align_arg mpg123_grow_string(mpg123_string* sb, size_t new)
30
{
31
	if(sb->size < new) return mpg123_resize_string(sb, new);
32
	else return 1;
33
}
34
 
35
int attribute_align_arg mpg123_resize_string(mpg123_string* sb, size_t new)
36
{
37
	debug3("resizing string pointer %p from %lu to %lu", (void*) sb->p, (unsigned long)sb->size, (unsigned long)new);
38
	if(new == 0)
39
	{
40
		if(sb->size && sb->p != NULL) free(sb->p);
41
		mpg123_init_string(sb);
42
		return 1;
43
	}
44
	if(sb->size != new)
45
	{
46
		char* t;
47
		debug("really!");
48
		t = (char*) safe_realloc(sb->p, new*sizeof(char));
49
		debug1("safe_realloc returned %p", (void*) t);
50
		if(t != NULL)
51
		{
52
			sb->p = t;
53
			sb->size = new;
54
			return 1;
55
		}
56
		else return 0;
57
	}
58
	else return 1; /* success */
59
}
60
 
61
int attribute_align_arg mpg123_copy_string(mpg123_string* from, mpg123_string* to)
62
{
63
	size_t fill;
64
	char  *text;
65
	if(to == NULL) return -1;
66
 
67
	debug2("called copy_string with %p -> %p", (void*)from, (void*)to);
68
	if(from == NULL)
69
	{
70
		fill = 0;
71
		text = NULL;
72
	}
73
	else
74
	{
75
		fill = from->fill;
76
		text = from->p;
77
	}
78
 
79
	if(mpg123_resize_string(to, fill))
80
	{
81
		memcpy(to->p, text, fill);
82
		to->fill = fill;
83
		return 1;
84
	}
85
	else return 0;
86
}
87
 
88
int attribute_align_arg mpg123_add_string(mpg123_string* sb, const char* stuff)
89
{
90
	debug1("adding %s", stuff);
91
	return mpg123_add_substring(sb, stuff, 0, strlen(stuff));
92
}
93
 
94
int attribute_align_arg mpg123_add_substring(mpg123_string *sb, const char *stuff, size_t from, size_t count)
95
{
96
	debug("adding a substring");
97
	if(sb->fill) /* includes zero byte... */
98
	{
99
		if( (SIZE_MAX - sb->fill >= count) /* Avoid overflow. */
100
		    && (sb->size >= sb->fill+count || mpg123_grow_string(sb, sb->fill+count)) )
101
		{
102
			memcpy(sb->p+sb->fill-1, stuff+from, count);
103
			sb->fill += count;
104
			sb->p[sb->fill-1] = 0; /* Terminate! */
105
		}
106
		else return 0;
107
	}
108
	else
109
	{
110
		if( count < SIZE_MAX && mpg123_grow_string(sb, count+1) )
111
		{
112
			memcpy(sb->p, stuff+from, count);
113
			sb->fill = count+1;
114
			sb->p[sb->fill-1] = 0; /* Terminate! */
115
		}
116
		else return 0;
117
	}
118
	return 1;
119
}
120
 
121
int attribute_align_arg mpg123_set_substring(mpg123_string* sb, const char* stuff, size_t from, size_t count)
122
{
123
	sb->fill = 0;
124
	return mpg123_add_substring(sb, stuff, from, count);
125
}
126
 
127
int attribute_align_arg mpg123_set_string(mpg123_string* sb, const char* stuff)
128
{
129
	sb->fill = 0;
130
	return mpg123_add_string(sb, stuff);
131
}
3960 Serge 132
 
133
size_t attribute_align_arg mpg123_strlen(mpg123_string *sb, int utf8)
134
{
135
	size_t i;
136
	size_t bytelen;
137
 
138
	/* Notions of empty string. If there's only a single character, it has to be the trailing zero, and if the first is the trailing zero anyway, we got empty. */
139
	if(sb->fill < 2 || sb->p[0] == 0) return 0;
140
 
141
	/* Find the first non-null character from the back.
142
	   We already established that the first character is non-null
143
	   That at fill-2 has to be null, though. */
144
	for(i=sb->fill-2; i>0; --i)
145
	if(sb->p[i] != 0) break;
146
 
147
	/* For simple byte strings, we are done now. */
148
	bytelen = i+1;
149
 
150
	if(!utf8) return bytelen;
151
	else
152
	{
153
		/* Work out the actual count of UTF8 bytes.
154
		   This employs no particular encoding error checking. */
155
		size_t len = 0;
156
		for(i=0; i
157
		{
158
			/* Every byte that is not a continuation byte ( 0xc0 == 10xx xxxx ) stands for a character. */
159
			if((sb->p[i] & 0xc0) != 0x80) len++;
160
		}
161
		return len;
162
	}
163
}
164
 
165
int attribute_align_arg mpg123_chomp_string(mpg123_string *sb)
166
{
167
	ssize_t i;
168
	if(!sb || !sb->fill) return 0;
169
 
170
	/* Ensure that it is zero-terminated. */
171
	sb->p[sb->fill-1] = 0;
172
	for(i=sb->fill-2; i>=0; --i)
173
	{
174
		char *c = sb->p+i;
175
		/* Stop at the first proper character. */
176
		if(*c && *c != '\r' && *c != '\n') break;
177
		else *c = 0;
178
	}
179
	/* initial fill at least 1, so i at least -1,
180
	   +2 means nothing happened for fill=1 .
181
	   With i=0, we got one non-null character, fill shall be 2
182
	   to accomodate the trailing zero. */
183
	sb->fill = (size_t)i+2;
184
 
185
	return 1;
186
}