00001 #ifndef OST_IO_FORMATTED_LINE_HH
00002 #define OST_IO_FORMATTED_LINE_HH
00003
00004 #ifdef _MSC_VER
00005 #define snprintf _snprintf
00006 #endif
00007
00008 #include <cstdio>
00009
00010 #include <ost/string_ref.hh>
00011
00012
00013
00014
00015
00016 namespace ost { namespace io {
00017
00018 namespace fmt {
00019
00020 struct LPadded : public StringRef {
00021 LPadded(const char* s, size_t l):
00022 StringRef(s, l)
00023 { }
00024
00025 explicit LPadded(const String& s): StringRef(s.data(), s.size())
00026 { }
00027
00028 explicit LPadded(const char* s): StringRef(s, strlen(s))
00029 { }
00030 };
00031
00032 struct RPadded : public StringRef {
00033 RPadded(const char* s, size_t l):
00034 StringRef(s, l)
00035 { }
00036
00037 explicit RPadded(const String& s): StringRef(s.data(), s.size())
00038 { }
00039
00040 explicit RPadded(const char* s): StringRef(s, strlen(s))
00041 { }
00042 };
00043
00044
00045 struct LPaddedInt {
00046 LPaddedInt(int val) {
00047 size_t curr=0;
00048 bool minus=val<0;
00049 val=std::abs(val);
00050 if (minus) {
00051 data[curr]='-';
00052 ++curr;
00053 }
00054 do {
00055 int m=val%10;
00056 data[curr]='0'+m;
00057 ++curr;
00058 val/=10;
00059 } while(val);
00060
00061 for (size_t i=0, e=(curr-int(minus))/2; i<e; ++i) {
00062 std::swap(data[int(minus)+i], data[curr-i-1]);
00063 }
00064 data[curr]='\0';
00065 len=curr;
00066 }
00067 char data[20];
00068 size_t len;
00069 };
00070
00071
00072
00073
00074 struct LPaddedFloat {
00075 LPaddedFloat(Real val, int prec)
00076 {
00077 switch(prec){
00078 case 0:
00079 len = snprintf(data, sizeof(data), "%.0f", val);
00080 break;
00081 case 1:
00082 len = snprintf(data, sizeof(data), "%.1f", val);
00083 break;
00084 case 2:
00085 len = snprintf(data, sizeof(data), "%.2f", val);
00086 break;
00087 case 3:
00088 len = snprintf(data, sizeof(data), "%.3f", val);
00089 break;
00090 default:
00091 Real rounded_val=round(val*pow(Real(10), prec))*pow(Real(0.1), prec);
00092 size_t curr=0;
00093 bool minus=rounded_val<0;
00094 rounded_val=std::abs(rounded_val);
00095 int int_val=int(rounded_val);
00096 if (minus) {
00097 data[curr]='-';
00098 ++curr;
00099 }
00100 do {
00101 int m=int_val%10;
00102 data[curr]='0'+m;
00103 ++curr;
00104 int_val/=10;
00105 } while(int_val);
00106
00107 for (size_t i=0, e=(curr-int(minus))/2; i<e; ++i) {
00108 std::swap(data[int(minus)+i], data[curr-i-1]);
00109 }
00110 data[curr]='\0';
00111 len=curr;
00112 if (prec==0) {
00113 return;
00114 }
00115 data[curr]='.';
00116 curr++;
00117 rounded_val-=int(rounded_val);
00118 while(prec>0) {
00119 rounded_val*=10;
00120 int m=int(rounded_val);
00121 rounded_val-=int(rounded_val);
00122 data[curr]='0'+m;
00123 curr++;
00124 --prec;
00125 }
00126 data[curr]='\0';
00127 len=curr;
00128 }
00129 }
00130 char data[20];
00131 size_t len;
00132 };
00133
00134
00135
00136 }
00137
00138 class LineSlice {
00139 public:
00140 LineSlice(char* data, size_t l): data_(data), len_(l)
00141 {
00142 }
00143
00144 LineSlice& operator=(const StringRef& str)
00145 {
00146 assert(str.length()==len_);
00147 memcpy(data_, str.data(), str.size());
00148 return *this;
00149 }
00150
00151 LineSlice& operator=(const fmt::LPadded& str)
00152 {
00153 assert(str.size()<=len_);
00154 memcpy(data_+len_-str.size(), str.data(), str.size());
00155 return *this;
00156 }
00157
00158 LineSlice& operator=(const fmt::RPadded& str)
00159 {
00160 assert(str.size()<=len_);
00161 memcpy(data_, str.data(), str.size());
00162 return *this;
00163 }
00164
00165 LineSlice& operator=(const fmt::LPaddedInt& i)
00166 {
00167 assert(i.len<=len_);
00168 memcpy(data_+len_-i.len, i.data, i.len);
00169 return *this;
00170 }
00171
00172 LineSlice& operator=(const fmt::LPaddedFloat& f)
00173 {
00174 assert(f.len<=len_);
00175 memcpy(data_+len_-f.len, f.data, f.len);
00176 return *this;
00177 }
00178 void Clear()
00179 {
00180 memset(data_, ' ', len_);
00181 }
00182 private:
00183 char* data_;
00184 size_t len_;
00185 };
00186
00187 class FormattedLine {
00188 public:
00189 FormattedLine(size_t width):
00190 data_(new char[width]), len_(width)
00191 {
00192 this->Clear();
00193 }
00194
00195 void Clear()
00196 {
00197 memset(data_, ' ', len_);
00198 }
00199 ~FormattedLine() { delete[] data_; }
00200
00201 LineSlice operator()(int start, int len)
00202 {
00203 assert(start>=0 && start+len<=static_cast<int>(len_));
00204 return LineSlice(data_+start, len);
00205 }
00206
00207 const char* Data() const { return data_; }
00208
00209 size_t GetWidth() const { return len_; }
00210
00211 char operator[](size_t index) const
00212 {
00213 assert(index<len_);
00214 return data_[index];
00215 }
00216
00217 char& operator[](size_t index)
00218 {
00219 assert(index<len_);
00220 return data_[index];
00221 }
00222 private:
00223 FormattedLine& operator=(const FormattedLine& rhs);
00224 FormattedLine(const FormattedLine& rhs);
00225 char* data_;
00226 size_t len_;
00227 };
00228
00229 inline std::ostream& operator<<(std::ostream& stream, const FormattedLine& line)
00230 {
00231 stream.write(line.Data(), line.GetWidth());
00232 stream << std::endl;
00233 return stream;
00234 }
00235
00236
00237 }}
00238
00239 #endif