| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | |
| 5 | |
| 6 | /*****************************************************************/ |
| 7 | /* OutString.h */ |
| 8 | /*****************************************************************/ |
| 9 | /* A simple, lightweight, character output stream, with very few |
| 10 | external dependancies (like sprintf ... ) */ |
| 11 | |
| 12 | /* |
| 13 | Date : 2/1/99 */ |
| 14 | /*****************************************************************/ |
| 15 | |
| 16 | #ifndef _OutString_h |
| 17 | #define _OutString_h 1 |
| 18 | |
| 19 | #include "utilcode.h" // for overloaded new |
| 20 | #include <string.h> // for strlen, strcpy |
| 21 | |
| 22 | /*****************************************************************/ |
| 23 | // a light weight character 'output' stream |
| 24 | class OutString { |
| 25 | public: |
| 26 | enum FormatFlags { // used to control printing of numbers |
| 27 | none = 0, |
| 28 | put0x = 1, // put leading 0x on hexidecimal |
| 29 | zeroFill = 2, // zero fill (instead of space fill) |
| 30 | }; |
| 31 | |
| 32 | OutString() : start(0), end(0), cur(0) {} |
| 33 | |
| 34 | OutString(unsigned initialAlloc) { |
| 35 | cur = start = new char[initialAlloc+1]; // for null termination |
| 36 | end = &start[initialAlloc]; |
| 37 | } |
| 38 | |
| 39 | ~OutString() { delete start; } |
| 40 | |
| 41 | // shortcut for printing decimal |
| 42 | OutString& operator<<(int i) { return(dec(i)); } |
| 43 | |
| 44 | OutString& operator<<(double d); |
| 45 | |
| 46 | // FIX make this really unsigned |
| 47 | OutString& operator<<(unsigned i) { return(dec(i)); } |
| 48 | |
| 49 | // prints out the hexidecimal representation |
| 50 | OutString& dec(int i, size_t minWidth = 0); |
| 51 | |
| 52 | // prints out the hexidecimal representation |
| 53 | OutString& hex(unsigned i, int minWidth = 0, unsigned flags = none); |
| 54 | |
| 55 | OutString& hex(unsigned __int64 i, int minWidth = 0, unsigned flags = none); |
| 56 | |
| 57 | OutString& hex(int i, int minWidth = 0, unsigned flags = none) { |
| 58 | return hex(unsigned(i), minWidth, flags); |
| 59 | } |
| 60 | |
| 61 | OutString& hex(__int64 i, int minWidth = 0, unsigned flags = none) { |
| 62 | return hex((unsigned __int64) i, minWidth, flags); |
| 63 | } |
| 64 | |
| 65 | // print out 'count' instances of the character 'c' |
| 66 | OutString& pad(size_t count, char c); |
| 67 | |
| 68 | OutString& operator<<(char c) { |
| 69 | if (cur >= end) |
| 70 | Realloc(1); |
| 71 | *cur++ = c; |
| 72 | _ASSERTE(start <= cur && cur <= end); |
| 73 | return(*this); |
| 74 | } |
| 75 | |
| 76 | OutString& operator<<(const wchar_t* str) { |
| 77 | size_t len = wcslen(str); |
| 78 | if (cur+len > end) |
| 79 | Realloc(len); |
| 80 | while(str != 0) |
| 81 | *cur++ = (char) *str++; |
| 82 | _ASSERTE(start <= cur && cur <= end); |
| 83 | return(*this); |
| 84 | } |
| 85 | |
| 86 | OutString& prepend(const char c) { |
| 87 | char buff[2]; buff[0] = c; buff[1] = 0; |
| 88 | return(prepend(buff)); |
| 89 | } |
| 90 | |
| 91 | OutString& prepend(const char* str) { |
| 92 | size_t len = strlen(str); |
| 93 | if (cur+len > end) |
| 94 | Realloc(len); |
| 95 | memmove(start+len, start, cur-start); |
| 96 | memcpy(start, str, len); |
| 97 | cur = cur + len; |
| 98 | _ASSERTE(start <= cur && cur <= end); |
| 99 | return(*this); |
| 100 | } |
| 101 | |
| 102 | OutString& operator=(const OutString& str) { |
| 103 | clear(); |
| 104 | *this << str; |
| 105 | return(*this); |
| 106 | } |
| 107 | |
| 108 | OutString& operator<<(const OutString& str) { |
| 109 | write(str.start, str.cur-str.start); |
| 110 | return(*this); |
| 111 | } |
| 112 | |
| 113 | OutString& operator<<(const char* str) { |
| 114 | write(str, strlen(str)); |
| 115 | return(*this); |
| 116 | } |
| 117 | |
| 118 | void write(const char* str, size_t len) { |
| 119 | if (cur+len > end) |
| 120 | Realloc(len); |
| 121 | memcpy(cur, str, len); |
| 122 | cur = cur + len; |
| 123 | _ASSERTE(start <= cur && cur <= end); |
| 124 | } |
| 125 | |
| 126 | void swap(OutString& str) { |
| 127 | char* tmp = start; |
| 128 | start = str.start; |
| 129 | str.start = tmp; |
| 130 | tmp = end; |
| 131 | end = str.end; |
| 132 | str.end = tmp; |
| 133 | tmp = cur; |
| 134 | cur = str.cur; |
| 135 | str.cur = tmp; |
| 136 | _ASSERTE(start <= cur && cur <= end); |
| 137 | } |
| 138 | |
| 139 | void clear() { cur = start; } |
| 140 | size_t length() const { return(cur-start); } |
| 141 | |
| 142 | // return the null terminated string, OutString keeps ownership |
| 143 | const char* val() const { *cur = 0; return(start); } |
| 144 | |
| 145 | // grab string (caller must now delete) OutString is cleared |
| 146 | char* grab() { char* ret = start; *cur = 0; end = cur = start = 0; return(ret); } |
| 147 | |
| 148 | private: |
| 149 | void Realloc(size_t neededSpace); |
| 150 | |
| 151 | char *start; // start of the buffer |
| 152 | char *end; // points at the last place null terminator can go |
| 153 | char *cur; // points at a null terminator |
| 154 | }; |
| 155 | |
| 156 | #endif // _OutString_h |
| 157 | |
| 158 | |