1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include "dyn_string.h"
28 #include <klib/text.h>
29 #include <klib/printf.h>
30 #include <klib/out.h>
31
32 typedef struct dyn_string
33 {
34 char * data;
35 size_t allocated;
36 size_t data_len;
37 } dyn_string;
38
39
allocated_dyn_string(struct dyn_string ** self,size_t size)40 rc_t allocated_dyn_string ( struct dyn_string **self, size_t size )
41 {
42 rc_t rc = 0;
43 struct dyn_string * res = malloc( sizeof *res );
44 *self = NULL;
45 if ( res == NULL )
46 rc = RC( rcApp, rcNoTarg, rcConstructing, rcMemory, rcExhausted );
47 else
48 {
49 res->data_len = 0;
50 res->data = malloc( size );
51 if ( res->data != NULL )
52 res->allocated = size;
53 else
54 {
55 res->allocated = 0;
56 rc = RC( rcApp, rcNoTarg, rcConstructing, rcMemory, rcExhausted );
57 }
58 if ( rc != 0 )
59 free( res );
60 else
61 *self = res;
62 }
63 return rc;
64 }
65
66
free_dyn_string(struct dyn_string * self)67 void free_dyn_string ( struct dyn_string *self )
68 {
69 free( self->data );
70 self->data = NULL;
71 self->allocated = 0;
72 self->data_len = 0;
73 free( ( void * ) self );
74 }
75
76
reset_dyn_string(struct dyn_string * self)77 void reset_dyn_string( struct dyn_string *self )
78 {
79 self->data_len = 0;
80 }
81
82
expand_dyn_string(struct dyn_string * self,size_t new_size)83 rc_t expand_dyn_string( struct dyn_string *self, size_t new_size )
84 {
85 rc_t rc = 0;
86 if ( new_size > self->allocated )
87 {
88 self->data = realloc ( self->data, new_size );
89 if ( self->data != NULL )
90 {
91 self->allocated = new_size;
92 }
93 else
94 {
95 self->allocated = 0;
96 self->data_len = 0;
97 rc = RC( rcApp, rcNoTarg, rcConstructing, rcMemory, rcExhausted );
98 }
99 }
100 return rc;
101 }
102
103
add_char_2_dyn_string(struct dyn_string * self,const char c)104 rc_t add_char_2_dyn_string( struct dyn_string *self, const char c )
105 {
106 /* does nothing if self->data_len + 2 < self->allocated */
107 rc_t rc = expand_dyn_string( self, self->data_len + 2 );
108 if ( rc == 0 )
109 {
110 self->data[ self->data_len++ ] = c;
111 self->data[ self->data_len ] = 0;
112 }
113 return rc;
114 }
115
116
dyn_string_char(struct dyn_string * self,uint32_t idx)117 char * dyn_string_char( struct dyn_string *self, uint32_t idx )
118 {
119 return( &self->data[ idx ] );
120 }
121
122
add_string_2_dyn_string(struct dyn_string * self,const char * s)123 rc_t add_string_2_dyn_string( struct dyn_string *self, const char * s )
124 {
125 rc_t rc;
126 size_t size = string_size ( s );
127 /* does nothing if self->data_len + size + 1 < self->allocated */
128 rc = expand_dyn_string( self, self->data_len + size + 1 );
129 if ( rc == 0 )
130 {
131 string_copy ( &(self->data[ self->data_len ]), self->allocated, s, size );
132 self->data_len += size;
133 self->data[ self->data_len ] = 0;
134 }
135 return rc;
136 }
137
138
add_dyn_string_2_dyn_string(struct dyn_string * self,struct dyn_string * other)139 rc_t add_dyn_string_2_dyn_string( struct dyn_string *self, struct dyn_string *other )
140 {
141 rc_t rc = 0;
142 size_t size = other->data_len;
143 if ( size > 0 )
144 {
145 /* does nothing if self->data_len + size + 1 < self->allocated */
146 rc = expand_dyn_string( self, self->data_len + size + 1 );
147 if ( rc == 0 )
148 {
149 string_copy ( &(self->data[ self->data_len ]), self->allocated, other->data, size );
150 self->data_len += size;
151 self->data[ self->data_len ] = 0;
152 }
153 }
154 return rc;
155
156 }
157
158
print_2_dyn_string(struct dyn_string * self,const char * fmt,...)159 rc_t print_2_dyn_string( struct dyn_string * self, const char *fmt, ... )
160 {
161 rc_t rc = 0;
162 bool not_enough;
163
164 do
165 {
166 size_t num_writ;
167 va_list args;
168 va_start ( args, fmt );
169 rc = string_vprintf ( &(self->data[ self->data_len ]),
170 self->allocated - ( self->data_len + 1 ),
171 &num_writ,
172 fmt,
173 args );
174 va_end ( args );
175
176 if ( rc == 0 )
177 {
178 self->data_len += num_writ;
179 self->data[ self->data_len ] = 0;
180 }
181 not_enough = ( GetRCState( rc ) == rcInsufficient );
182 if ( not_enough )
183 {
184 rc = expand_dyn_string( self, self->allocated + ( num_writ * 2 ) );
185 }
186 } while ( not_enough && rc == 0 );
187 return rc;
188 }
189
190
print_dyn_string(struct dyn_string * self)191 rc_t print_dyn_string( struct dyn_string * self )
192 {
193 if ( self != NULL )
194 return KOutMsg( "%.*s", self->data_len, self->data );
195 else
196 return 0;
197 }
198
199
dyn_string_len(struct dyn_string * self)200 size_t dyn_string_len( struct dyn_string * self )
201 {
202 if ( self != NULL )
203 return self->data_len;
204 else
205 return 0;
206 }
207