Last active
September 29, 2016 16:30
-
-
Save qgp9/b17f7a289a50a79dc23a3bdb4ae36963 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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