|
Boost : |
From: James S. Adelman (j.adelman_at_[hidden])
Date: 2002-02-09 18:11:59
It's manipulator-like; it can work for user-defined types. Currently,
though, it is expensive. It needs a seperator between units, because in
general there is no way to know what is and is not a manipulator. Pretty
much safe. It's only meant to be a proof of concept at present. Any
interest?
// -- test.cpp --
#include "format.hpp"
#include <iostream>
#include <string>
#include <complex>
int main()
{
int x=6;
double y=5;
std::complex<double> y2(5,0.5);
std::string s="foo";
std::cout<<format<char>("%1 %0 ")<<y2<<endi<<y<<endi<<x<<endf<<"\n";
std::cout<<"back to normal"<<std::endl;
std::cout<<y2<<std::endl;
std::cout<<format<char>("%1 %2 %0")<<y2<<endi<<y<<endf<<std::endl;
}
// -- end
// -- format.hpp --
#ifndef JSA_FORMAT_H
#define JSA_FORMAT_H
#include <streambuf>
#include <string>
#include <ostream>
#include <vector>
#include <cctype>
#include <iostream>
#include <cstddef>
template <typename Ch,typename Tr=std::char_traits<Ch> >
struct format
{
format(const std::basic_string<Ch,Tr>&s):
s_(s)
{}
std::basic_string<Ch,Tr> s_;
};
template <typename Ch, typename Tr=std::char_traits<Ch> >
struct formatbuf: std::basic_streambuf<Ch,Tr>
{
public:
formatbuf(std::basic_ostream<Ch,Tr>* os,
std::basic_streambuf<Ch,Tr>* old,
const format<Ch,Tr>& s):
os_(os),osb_(old),shutdown_(false),which_(0),howm_(0)
{
std::basic_string<Ch,Tr>::const_iterator p=s.s_.begin(),q=s.s_.end(),r=p;
for(;p!=q;++p)
{
std::cerr<<"foo"<<std::endl;
if(*p!='%') continue;
out_.push_back(std::basic_string<Ch,Tr>(r,p++));
std::size_t j=0;
while((p!=q)&&std::isdigit(*p)) j=j*10+*p++-'0';
if(j>=order_.size()) order_.resize(j+1);
if(*p=='$') ++p;
if(*p!='%') order_[j]=howm_++;
r=p;
if(p==q) break;
}
out_.push_back(std::basic_string<Ch,Tr>(r,p));
order_.push_back(howm_);
std::cerr<<"bar"<<std::endl;
}
formatbuf* shutdown()
{
std::cerr<<which_<<"()()"<<std::endl;;
if(!shutdown_){
for(std::vector<std::basic_string<Ch,Tr> >::iterator
p=out_.begin(),q=out_.end();
p!=q; ++p)
{
osb_->sputn(p->data(),p->length());
}
os_->rdbuf(osb_);
shutdown_=true;
}
return this;
}
void next()
{
++which_;
if(which_==howm_) {std::cerr<<"^y^";shutdown();}
}
protected:
std::streamsize xsputn(const Ch* p, std::streamsize n)
{
out_[order_[which_]].append(p,n);
return n;
}
typename Tr::int_type overflow(typename Tr::int_type c=Tr::eof())
{
if(!Tr::eq_int_type(c,Tr::eof()))
{
out_[order_[which_]].push_back(c);
return c;
}
return Tr::not_eof(c);
}
private:
std::basic_ostream<Ch,Tr> *os_;
std::basic_streambuf<Ch,Tr> *osb_;
std::vector<std::basic_string<Ch,Tr> > out_;
std::vector<int> order_;
bool shutdown_;
int which_,howm_;
};
template <typename Ch,typename Tr>
std::basic_ostream<Ch,Tr>& operator<<(std::basic_ostream<Ch,Tr>&os,
const format<Ch,Tr>& ft)
{
os.rdbuf(new formatbuf<Ch,Tr>(&os,os.rdbuf(),ft));
return os;
}
template <typename Ch,typename Tr>
std::basic_ostream<Ch,Tr>& endi(std::basic_ostream<Ch,Tr>& os)
{
if(formatbuf<Ch,Tr>* p=dynamic_cast<formatbuf<Ch,Tr>*>(os.rdbuf()))
p->next();
return os;
}
template <typename Ch,typename Tr>
std::basic_ostream<Ch,Tr>& endf(std::basic_ostream<Ch,Tr>& os)
{
if(formatbuf<Ch,Tr>* p=dynamic_cast<formatbuf<Ch,Tr>*>(os.rdbuf())) delete
p->shutdown();
return os;
}
#endif
// -- end
-- James S. Adelman
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk