~ubuntu-branches/ubuntu/raring/simutrans/raring-proposed

« back to all changes in this revision

Viewing changes to utils/cbuffer_t.cc

  • Committer: Package Import Robot
  • Author(s): Ansgar Burchardt
  • Date: 2011-11-03 19:59:02 UTC
  • mfrom: (1.2.7)
  • Revision ID: package-import@ubuntu.com-20111103195902-uopgwf488mfctb75
Tags: 111.0-1
* New upstream release.
* debian/rules: Update get-orig-source target for new upstream release.
* Use xz compression for source and binary packages.
* Use override_* targets to simplify debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#include <assert.h>
2
2
#include <stdarg.h>
3
3
#include <stdio.h>
 
4
#include <errno.h>
4
5
#include <string.h>
5
6
#include "cbuffer_t.h"
6
7
#include "simstring.h"
7
8
#include "../simtypes.h"
8
9
 
9
10
 
10
 
/**
11
 
 * Creates a new cbuffer with capacity cap
12
 
 * @param cap the capacity
13
 
 * @author Hj. Malthaner
14
 
 */
15
 
cbuffer_t::cbuffer_t(unsigned int cap)
 
11
cbuffer_t::cbuffer_t() :
 
12
        capacity(256),
 
13
        size(0),
 
14
        buf(new char[capacity])
16
15
{
17
 
        capacity = (cap == 0 ? 1 : cap);
18
 
        size = 0;
19
 
 
20
 
        buf = new char[capacity];
21
16
        buf[0] = '\0';
22
17
}
23
18
 
25
20
cbuffer_t::~cbuffer_t()
26
21
{
27
22
  delete [] buf;
28
 
  buf = 0;
29
 
  capacity = 0;
30
 
  size = 0;
31
23
}
32
24
 
33
25
 
34
 
/**
35
 
 * Clears the buffer
36
 
 * @author Hj. Malthaner
37
 
 */
38
26
void cbuffer_t::clear()
39
27
{
40
28
  buf[0] = '\0';
42
30
}
43
31
 
44
32
 
45
 
/**
46
 
 * Appends text. If buffer is full, exceeding text will not
47
 
 * be appended.
48
 
 * @author Hj. Malthaner
49
 
 */
50
33
void cbuffer_t::append(const char * text)
51
34
{
52
 
        while(  *text  ) {
53
 
                if(  size>=capacity-1  ) {
54
 
                        // Knightly : double the capacity if full
55
 
                        extend(capacity);
56
 
                }
57
 
                buf[size++] = *text++;
58
 
        }
59
 
        buf[size] = 0;
60
 
}
61
 
 
62
 
 
63
 
/**
64
 
 * Appends a number. If buffer is full, exceeding digits will not
65
 
 * be appended.
66
 
 * @author Hj. Malthaner
67
 
 */
68
 
void cbuffer_t::append(long n)
69
 
{
70
 
        char tmp[32];
71
 
        char * p = tmp+31;
72
 
        bool neg = false;
73
 
        *p = '\0';
74
 
 
75
 
        if(n < 0) {
76
 
                neg = true;
77
 
                n = -n;
78
 
        }
79
 
 
80
 
        do {
81
 
                *--p  = '0' + (n % 10);
82
 
        } while((n/=10) > 0);
83
 
 
84
 
        if(neg) {
85
 
                *--p = '-';
86
 
        }
87
 
 
88
 
        append(p);
89
 
}
90
 
 
91
 
 
92
 
/**
93
 
 * Appends a number. If buffer is full, exceeding digits will not
94
 
 * be appended.
95
 
 * @author Hj. Malthaner
96
 
 */
 
35
        size_t const n = strlen(text);
 
36
        extend(n);
 
37
        memcpy(buf + size, text, n + 1);
 
38
        size += n;
 
39
}
 
40
 
 
41
 
97
42
void cbuffer_t::append(double n,int decimals)
98
43
{
99
44
        char tmp[32];
102
47
}
103
48
 
104
49
 
 
50
/* this is a vsnprintf which can always process positional parameters
 
51
 * like "%2$i: %1$s"
 
52
 * WARNING: posix specification as well as this function always assumes that
 
53
 * ALL parameter are either positional or not!!!
 
54
 *
 
55
 * When numbered argument specifications are used, specifying the Nth argument requires that all the
 
56
 * leading arguments, from the first to the (N-1)th, are specified in the format string.
 
57
 *
 
58
 * ATTENTION: no support for positional precision (which are not used in simutrans anyway!
 
59
 */
 
60
static int my_vsnprintf(char *buf, size_t n, const char* fmt, va_list ap )
 
61
{
 
62
#if defined _MSC_FULL_VER  &&  _MSC_FULL_VER >= 140050727  &&  !defined __WXWINCE__
 
63
        // this MSC function can handle positional parameters since 2008
 
64
        return _vsprintf_p(buf, n, fmt, ap);
 
65
#else
 
66
#if !defined(HAVE_UNIX98_PRINTF)
 
67
        // this function cannot handle positional parameters
 
68
        if(  const char *c=strstr( fmt, "%1$" )  ) {
 
69
                // but they are requested here ...
 
70
                // our routine can only handle max. 9 parameters
 
71
                char pos[6];
 
72
                static char format_string[256];
 
73
                char *cfmt = format_string;
 
74
                static char buffer[16000];      // the longest possible buffer ...
 
75
                int count = 0;
 
76
                for(  ;  c  &&  count<9;  count++  ) {
 
77
                        sprintf( pos, "%%%i$", count+1 );
 
78
                        c = strstr( fmt, pos );
 
79
                        if(  c  ) {
 
80
                                // extend format string, using 1 as marke between strings
 
81
                                if(  count  ) {
 
82
                                        *cfmt++ = '\01';
 
83
                                }
 
84
                                *cfmt++ = '%';
 
85
                                // now find the end
 
86
                                c += 3;
 
87
                                int len = strspn( c, "+-0123456789 #.hlI" )+1;
 
88
                                while(  len-->0  ) {
 
89
                                        *cfmt++ = *c++;
 
90
                                }
 
91
                        }
 
92
                }
 
93
                *cfmt = 0;
 
94
                // now printf into buffer
 
95
                int result = vsnprintf( buffer, 16000, format_string, ap );
 
96
                if(  result<0  ||  result>=16000  ) {
 
97
                        *buf = 0;
 
98
                        return 0;
 
99
                }
 
100
                // check the length
 
101
                result += strlen(fmt);
 
102
                if(   (size_t)result > n  ) {
 
103
                        // increase the size please ...
 
104
                        return result;
 
105
                }
 
106
                // we have enough size: copy everything together
 
107
                *buf = 0;
 
108
                char *cbuf = buf;
 
109
                cfmt = const_cast<char *>(fmt); // cast is save, as the string is not modified
 
110
                while(  *cfmt!=0  ) {
 
111
                        while(  *cfmt!='%'  &&  *cfmt  ) {
 
112
                                *cbuf++ = *cfmt++;
 
113
                        }
 
114
                        if(  *cfmt==0  ) {
 
115
                                break;
 
116
                        }
 
117
                        // get the nth argument
 
118
                        char *carg = buffer;
 
119
                        int current = cfmt[1]-'1';
 
120
                        for(  int j=0;  j<current;  j++  ) {
 
121
                                while(  *carg  &&  *carg!='\01'  ) {
 
122
                                        carg ++;
 
123
                                }
 
124
                                assert( *carg );
 
125
                                carg ++;
 
126
                        }
 
127
                        while(  *carg  &&  *carg!='\01'  ) {
 
128
                                *cbuf++ = *carg++;
 
129
                        }
 
130
                        // jump rest
 
131
                        cfmt += 3;
 
132
                        cfmt += strspn( cfmt, "+-0123456789 #.hlI" )+1;
 
133
                }
 
134
                *cbuf = 0;
 
135
                return cbuf-buf;
 
136
        }
 
137
        // no positional parameters: use standard vsnprintf
 
138
#endif
 
139
        // normal posix system can handle positional parameters
 
140
        return vsnprintf(buf, n, fmt, ap);
 
141
#endif
 
142
}
 
143
 
 
144
 
105
145
void cbuffer_t::printf(const char* fmt, ...)
106
146
{
107
 
        va_list ap;
108
 
        va_start(ap, fmt);
109
 
        int count = vsnprintf( buf+size, capacity-size, fmt, ap);
110
 
        va_end(ap);
111
 
        // buffer too small?
112
 
        // we do not increase it beyond 1MB, as this is usually only needed when %s of a random memory location
113
 
        while(0 <= count  &&  capacity-size <= (uint)count  &&  capacity < 1048576) {
114
 
                // enlarge buffer
115
 
                extend( capacity);
116
 
                // and try again
 
147
        for (;;) {
 
148
                size_t const n     = capacity - size;
 
149
                size_t inc;
 
150
 
 
151
                va_list ap;
117
152
                va_start(ap, fmt);
118
 
                count = vsnprintf( buf+size, capacity-size, fmt, ap);
 
153
                int    const count = my_vsnprintf(buf + size, n, fmt, ap );
119
154
                va_end(ap);
120
 
                // .. until everything fit into buffer
121
 
        }
122
 
        // error
123
 
        if(count<0) {
124
 
                // truncate
125
 
                buf[capacity-1] = 0;
126
 
        }
127
 
        else {
128
 
                size += count;
 
155
                if (count < 0) {
 
156
#ifdef _WIN32
 
157
                        inc = capacity;
 
158
#else
 
159
                        // error
 
160
                        buf[size] = '\0';
 
161
                        break;
 
162
#endif
 
163
                } else if ((size_t)count < n) {
 
164
                        size += count;
 
165
                        break;
 
166
                } else {
 
167
                        // Make room for the string.
 
168
                        inc = (size_t)count;
 
169
                }
 
170
                extend(inc);
129
171
        }
130
172
}
131
173
 
132
174
 
133
 
void cbuffer_t::extend(const unsigned int by_amount)
 
175
void cbuffer_t::extend(unsigned int min_free_space)
134
176
{
135
 
        if(  size+by_amount>=capacity  ) {
 
177
        if (min_free_space >= capacity - size) {
 
178
                unsigned int by_amount = min_free_space + 1 - (capacity - size);
 
179
                if (by_amount < capacity) {
 
180
                        // At least double the size of the buffer.
 
181
                        by_amount = capacity;
 
182
                }
136
183
                unsigned int new_capacity = capacity + by_amount;
137
184
                char *new_buf = new char [new_capacity];
138
185
                memcpy( new_buf, buf, capacity );