Skip to content

Instantly share code, notes, and snippets.

@qgp9
Last active September 29, 2016 16:30
Show Gist options
  • Save qgp9/b17f7a289a50a79dc23a3bdb4ae36963 to your computer and use it in GitHub Desktop.
Save qgp9/b17f7a289a50a79dc23a3bdb4ae36963 to your computer and use it in GitHub Desktop.
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <stdlib.h>
class SafeFormatter{
public:
SafeFormatter( const char * s ):fForm(s),fIterator(fForm.begin()){}
void compile(){return ;}
template< typename T, typename ... A >
void compile(T v, A ... args){
auto &it = fIterator;
auto end = fForm.end();
for( ;it!=end;it++ ){
if( *it != '%' ){
fStream << *it;
}else{
bool escape = true;
while( it!=end && *it=='%' ){
escape=!escape;
if( escape ) fStream << "%%";
it++;
}
if( !escape ){
bool _left = false;
auto _align = std::right;
std::string _width;
std::string _prec;
std::string _fill;
if( *it == '-' ) { _align=std::left; it++; }
if( *it == '0' ) { _fill='0'; it++; }
while(it!=end && *it=='0' ) it++;
while(it!=end && *it>='0' && *it<='9'){ _width += *it; it++;}
if( *it == '.' ){
it++;
while(it!=end && *it>='0' && *it<='9'){ _prec += *it; it++;}
}
int iwidth = atoi(_width.c_str());
int iprec = atoi(_prec.c_str());
if( *it=='d' || *it=='f' || *it=='s' || *it=='x' || *it=='o' ){
fStream << _align;
if( iwidth>0 ) fStream << std::setw(iwidth);
if( iprec>0 ) fStream << std::setprecision(iprec);
if( _fill.length()>0 ) {
if( _align == std::left ) fStream<<std::left;
else fStream<<std::internal;
fStream <<std::setfill(_fill[0]);
}
if( *it=='x' ) fStream<<std::setbase(16);
if( *it=='o' ) fStream<<std::setbase(8);
fStream << v;
it++;
compile(args...);
return;
}else{
std::cout<<"ERROR"<<std::endl;
return;
}
}
}
}
}
template< typename ... A >
static std::string format(SafeFormatter form, A ... args){
form.compile(args...);return form.str();
}
std::string str(){ return fStream.str(); }
private:
std::string fForm;
std::ostringstream fStream;
std::string::iterator fIterator;
};
#include <string>
#include <regex>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <stdlib.h>
class SafeFormatter{
public:
SafeFormatter( const char * s ):fForm(s){}
void compile(){fStream << fForm;}
template< typename T, typename ... A >
void compile(T v, A ... args){
std::smatch sm;
if( std::regex_search( fForm, sm, fRe )){
fStream << sm.prefix().str() << sm[1].str();
fStream << ( (sm[2]=="-") ? std::left : sm[3]=="" ? std::right : std::internal);
if( sm[3]!="" )
fStream << std::setfill(sm[3].str()[0]);
if( sm[4]!="" ) fStream << std::setw( atoi(sm[4].str().c_str()) );
if( sm[5]!="" ) fStream << std::setprecision( atoi(sm[5].str().c_str()) );
if( sm[6]=="x") fStream << std::setbase(16);
if( sm[6]=="o") fStream << std::setbase(8);
fStream << v;
fForm = sm.suffix().str();
compile( args... );
}else{
//std::cout<<"ERROR"<<std::endl;
// Pass Through
fStream <<v;
compile( args... );
}
}
template< typename ... A >
static std::string format(SafeFormatter form, A ... args){
form.compile(args...);return form.str();
}
std::string str(){ return fStream.str(); }
private:
std::string fForm;
std::ostringstream fStream;
const static std::regex fRe;
};
const std::regex SafeFormatter::fRe{R"(((?:^|[^%])(?:%%)*)%(-?)(0)?(\d+)?(?:\.(\d+))?([dfsxo]|ul))",std::regex::ECMAScript};
#include "SafeFormatter.h"
//#include "SafeFormatterRegexp.h"
template< typename ... A >
void test_format( const char * form, A ... args ){
std::cout<<std::setw(20)<<form<<" --- ";
std::cout<<SafeFormatter::format( form, args... );
std::cout<<std::endl;
}
int main(){
//std::cout<<SafeFormatter::format("%%d :%d\n%%%%d:%%d\t%f--%.3f123", 1, 4, 2.5, 12.1)<<std::endl;
//
test_format("%d",12, " this gives error or just printed");
test_format("escape %%d %%%d %%%% %%%%%d",12,12);
test_format("simple %d int",12);
test_format("%10d",12);
test_format("%-10d",12);
test_format("%-010d",12);
test_format("%010d",-12);
test_format("%f", 3.141592);
test_format("%20f", 3.141592);
test_format("%-20f", 3.141592);
test_format("%-20.3f", 3.141592);
test_format("%20.10f", 3.141592);
test_format("%-.10f", 3.141592);
test_format("%-020.10f",-3.141592);
test_format("%020.10f", -3.141592);
test_format("%s","test string");
test_format("%5s","test string");
test_format("%50s","test string");
test_format("%-50s","test string");
test_format("%050s","test string");
test_format("%-050s","test string");
test_format("%x",14);
test_format("%o",14);
test_format("%d\n%10d\n%-10d\n%010d\n",12,12,12,-12);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment