summaryrefslogtreecommitdiff
path: root/src/inc/outstring.h
blob: 5cf0236350c4daa0f833144ea30347aa5630df29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.


/*****************************************************************/
/*                         OutString.h                           */
/*****************************************************************/
/* A simple, lightweight, character output stream, with very few
   external dependancies (like sprintf ... ) */

/*  
   Date :  2/1/99               */
/*****************************************************************/

#ifndef _OutString_h
#define _OutString_h 1

#include "utilcode.h"   // for overloaded new
#include <string.h>     // for strlen, strcpy

/*****************************************************************/
    // a light weight character 'output' stream 
class OutString {
public:
    enum FormatFlags {          // used to control printing of numbers
        none        = 0,
        put0x       = 1,        // put leading 0x on hexidecimal 
        zeroFill    = 2,        // zero fill (instead of space fill)
    };

    OutString() : start(0), end(0), cur(0) {}

    OutString(unsigned initialAlloc) { 
        cur = start = new char[initialAlloc+1]; // for null termination
        end = &start[initialAlloc];
    }
    
    ~OutString() { delete start; }
    
    // shortcut for printing decimal  
    OutString& operator<<(int i) { return(dec(i)); }

    OutString& operator<<(double d);
 
    // FIX make this really unsigned
    OutString& operator<<(unsigned i) { return(dec(i)); }

    // prints out the hexidecimal representation
    OutString& dec(int i, size_t minWidth = 0);
    
    // prints out the hexidecimal representation 
    OutString& hex(unsigned i, int minWidth = 0, unsigned flags = none);

    OutString& hex(unsigned __int64 i, int minWidth = 0, unsigned flags = none);

    OutString& hex(int i, int minWidth = 0, unsigned flags = none) {
        return hex(unsigned(i), minWidth, flags);
    }

    OutString& hex(__int64 i, int minWidth = 0, unsigned flags = none) {
        return hex((unsigned __int64) i, minWidth, flags);
    }
    
    //  print out 'count' instances of the character 'c'
    OutString& pad(size_t count, char c);
    
    OutString& operator<<(char c) {
        if (cur >= end)
            Realloc(1);
        *cur++ = c;
        _ASSERTE(start <= cur && cur <= end);
        return(*this);
    }
    
    OutString& operator<<(const wchar_t* str) {
        size_t len = wcslen(str);
        if (cur+len > end)
            Realloc(len);
        while(str != 0) 
            *cur++ = (char) *str++;
        _ASSERTE(start <= cur && cur <= end);
        return(*this);
    }

    OutString& prepend(const char c) {
        char buff[2]; buff[0] = c; buff[1] = 0;
        return(prepend(buff));
    }

    OutString& prepend(const char* str) {
        size_t len = strlen(str);
        if (cur+len > end)
            Realloc(len);
        memmove(start+len, start, cur-start);
        memcpy(start, str, len);
        cur = cur + len;
        _ASSERTE(start <= cur && cur <= end);
        return(*this);
        }

    OutString& operator=(const OutString& str) {
        clear();
        *this << str;
        return(*this);
    }

    OutString& operator<<(const OutString& str) {
        write(str.start, str.cur-str.start);
        return(*this);
    }

    OutString& operator<<(const char* str) {
        write(str, strlen(str));
        return(*this);
    }

    void write(const char* str, size_t len) {
        if (cur+len > end)
            Realloc(len);
        memcpy(cur, str, len);
        cur = cur + len;
        _ASSERTE(start <= cur && cur <= end);
    }

    void swap(OutString& str) {
        char* tmp = start;
        start = str.start;
        str.start = tmp;
        tmp = end;
        end = str.end;
        str.end = tmp;
        tmp = cur;
        cur = str.cur;
        str.cur = tmp;
        _ASSERTE(start <= cur && cur <= end);
    }

    void clear()                { cur = start; }
    size_t length() const       { return(cur-start); }
    
    // return the null terminated string, OutString keeps ownership
    const char* val() const     { *cur = 0; return(start); }
    
    // grab string (caller must now delete) OutString is cleared 
    char* grab()        { char* ret = start; *cur = 0; end = cur = start = 0; return(ret); }
    
private:
    void Realloc(size_t neededSpace);
    
    char *start;    // start of the buffer
    char *end;      // points at the last place null terminator can go
    char *cur;      // points at a null terminator
};

#endif // _OutString_h