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 | }>>> |