1 /*
2   dynamicstring.c
3 
4   $Id: dynamicstring.c,v 1.6 2002/12/27 21:48:25 bears Exp $
5 */
6 
7 #if HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <sys/types.h>
12 #include "dynamicstring.h"
13 #include "log.h"
14 #include "portable.h"
15 
16 struct DynStr
17 {
18     int len; /* Current length (without trailing '\0') */
19     int max; /* Max length that fits into buffer (incl. trailing '\0') */
20     char *str;
21 };
22 
23 static void
reallocStr(DynStr * self,int max)24 reallocStr( DynStr *self, int max )
25 {
26     ASSERT( max >= 0 );
27     if ( max <= self->max )
28         return;
29     if ( ! ( self->str = (char *)realloc( self->str, (size_t)max ) ) )
30         Log_fatal( "Realloc of DynStr failed" );
31     if ( self->max == 0 ) /* First allocation? */
32         *(self->str) = '\0';
33     self->max = max;
34 }
35 
36 DynStr *
new_DynStr(int reserve)37 new_DynStr( int reserve )
38 {
39     DynStr *s;
40 
41     if ( ! ( s = malloc( sizeof( DynStr ) ) ) )
42         Log_fatal( "Allocation of DynStr failed" );
43     s->len = 0;
44     s->max = 0;
45     s->str = NULL;
46     if ( reserve > 0 )
47         reallocStr( s, reserve + 1 );
48     return s;
49 }
50 
51 void
del_DynStr(DynStr * self)52 del_DynStr( DynStr *self )
53 {
54     if ( ! self )
55         return;
56     free( self->str );
57     self->str = NULL;
58     free( self );
59 }
60 
61 int
DynStr_len(const DynStr * self)62 DynStr_len( const DynStr *self )
63 {
64     return self->len;
65 }
66 
67 const char *
DynStr_str(const DynStr * self)68 DynStr_str( const DynStr *self )
69 {
70     return self->str;
71 }
72 
73 void
DynStr_app(DynStr * self,const char * s)74 DynStr_app( DynStr *self, const char *s )
75 {
76     int len;
77 
78     len = strlen( s );
79     if ( self->len + len + 1 > self->max )
80         reallocStr( self, self->len * 2 + len + 1 );
81     strcpy( self->str + self->len, s );
82     self->len += len;
83 }
84 
85 void
DynStr_appDynStr(DynStr * self,const DynStr * s)86 DynStr_appDynStr( DynStr *self, const DynStr *s )
87 {
88     if ( self->len + s->len + 1 > self->max )
89         reallocStr( self, self->len * 2 + s->len + 1 );
90     memcpy( self->str + self->len, s->str, (size_t)s->len + 1 );
91     self->len += s->len;
92 }
93 
94 void
DynStr_appLn(DynStr * self,const char * s)95 DynStr_appLn( DynStr *self, const char *s )
96 {
97     DynStr_app( self, s );
98     DynStr_app( self, "\n" );
99 }
100 
101 void
DynStr_appN(DynStr * self,const char * s,int n)102 DynStr_appN( DynStr *self, const char *s, int n )
103 {
104     int len = self->len;
105 
106     ASSERT( n >= 0 );
107     if ( len + n + 1 > self->max )
108         reallocStr( self, len * 2 + n + 1 );
109     strncat( self->str + len, s, (size_t)n );
110     self->len = len + strlen( self->str + len );
111 }
112 
113 void
DynStr_clear(DynStr * self)114 DynStr_clear( DynStr *self )
115 {
116     self->len = 0;
117     if ( self->max > 0 )
118         *(self->str) = '\0';
119 }
120 
121