fork(2) download
  1. #include <iostream>
  2.  
  3. // Copyright 2013, Dmitry Ledentsov
  4. // Released under the MIT License: http://w...content-available-to-author-only...e.org/licenses/mit-license.php
  5. // see https://g...content-available-to-author-only...b.com/d-led/fakeformat
  6.  
  7. template <typename format>
  8. void tryout() {
  9. // try your formatting here
  10. std::cout<<format("with 3 zeroes: {1,num=fixed,precision=3}, without: {1}").with(1.0).now()<<std::endl;
  11. std::cout<<format("1:{1,width=10,fill=-}\n2:{2,width=10,fill=-}\n3:{3,width=10,fill=-}")
  12. .with(1)
  13. .also_with(10)
  14. .also_with(1000)
  15. .now()
  16. <<std::endl;
  17. }
  18.  
  19. #include <string>
  20. #include <sstream>
  21. #include <vector>
  22. #include <map>
  23. #include <utility>
  24. #include <iomanip>
  25.  
  26. namespace ff {
  27.  
  28. template <typename TChar>
  29. struct config {
  30. static const TChar scope_begin='{';
  31. static const TChar scope_end='}';
  32. static const TChar separator=',';
  33. static const TChar equals='=';
  34. static const size_t index_begin=1;
  35. static bool string_to_key(std::string const& to_parse,int& res) {
  36. std::istringstream ss(to_parse);
  37. ss.imbue(std::locale::classic());
  38. ss >> res;
  39. if (!ss.fail() && ss.eof())
  40. return true;
  41. return false;
  42. }
  43. };
  44.  
  45. typedef std::map<std::string,std::string> TKeyValueMap;
  46.  
  47. namespace detail {
  48.  
  49. template <
  50. typename TString=std::string,
  51. typename TStream=std::stringstream
  52. >
  53. class stream {
  54.  
  55. public:
  56. stream ()
  57. {
  58. flags=impl.flags();
  59. impl.imbue(std::locale());
  60. }
  61.  
  62. stream (const stream &)
  63. {
  64. flags=impl.flags();
  65. impl.imbue(std::locale());
  66. }
  67.  
  68. stream & operator = (const stream &) {
  69. return *this;
  70. }
  71.  
  72. public:
  73. template <typename T>
  74. stream const& put(T const& p) const {
  75. impl<<p;
  76. return *this;
  77. }
  78.  
  79. template <typename TIter>
  80. stream const& put(TIter first,TIter last) const {
  81. for (TIter it=first; it!=last; ++it)
  82. impl.put(*it);
  83. return *this;
  84. }
  85.  
  86. TString str() const {
  87. return impl.str();
  88. }
  89.  
  90. void clear() const {
  91. impl.str("");
  92. impl.flags(flags);
  93. }
  94.  
  95. void configure(TKeyValueMap const& config_map) {
  96. for (TKeyValueMap::const_iterator it=config_map.begin();
  97. it!=config_map.end();
  98. ++it) {
  99. if (it->first=="num"
  100. || it->first=="number") {
  101. if (it->second=="hex") {
  102. impl<<std::hex;
  103. } else if (it->second=="oct") {
  104. impl<<std::oct;
  105. } else if (it->second=="sci"
  106. || it->second=="scientific") {
  107. impl<<std::scientific;
  108. } else if (it->second=="fix"
  109. || it->second=="fixed") {
  110. impl<<std::fixed;
  111. }
  112. } else if (it->first=="w"
  113. || it->first=="width") {
  114. int width=-1;
  115. if (config<char>::string_to_key(it->second,width)
  116. && width>0) {
  117. impl.width(width);
  118. }
  119. } else if (it->first=="left") {
  120. impl<<std::left;
  121. } else if (it->first=="right") {
  122. impl<<std::right;
  123. } else if (it->first=="precision") {
  124. int precision=-1;
  125. if (config<char>::string_to_key(it->second,precision)
  126. && precision>0) {
  127. impl.precision(precision);
  128. }
  129. } else if (it->first=="fill") {
  130. if (it->second.length()==1) {
  131. impl.fill(it->second[0]);
  132. }
  133. }
  134. }
  135. }
  136.  
  137. private:
  138. mutable TStream impl;
  139. std::ios_base::fmtflags flags;
  140. };
  141. }
  142.  
  143. //////////////////PARSER BEGIN////////////////////////
  144.  
  145. static const int START_POS=-1;
  146.  
  147. struct Placeholder {
  148. int id;
  149. int length;
  150. TKeyValueMap config;
  151. Placeholder():id(START_POS),length(START_POS){}
  152. };
  153.  
  154. typedef std::vector< std::pair<int,Placeholder> > Placeholders;
  155.  
  156. class FormatContext
  157. {
  158. struct ParserState {
  159. std::string format_string;
  160. int pos;
  161. int last_left_brace;
  162. int last_key_start;
  163. int last_value_start;
  164. std::string last_key;
  165. Placeholder current_placeholder;
  166. Placeholders placeholders;
  167. } state;
  168.  
  169. int string_to_key(std::string const& to_parse) {
  170. int res=START_POS;
  171. std::istringstream ss(to_parse);
  172. ss.imbue(std::locale::classic());
  173. ss >> res;
  174. if (!ss.fail() && ss.eof())
  175. return res;
  176. return START_POS;
  177. }
  178.  
  179. public:
  180.  
  181. bool IsAtEnd() const {
  182. bool res=state.pos >= (static_cast<int>(state.format_string.size())-1);
  183. return res;
  184. }
  185.  
  186. char Step() {
  187. if (IsAtEnd())
  188. return '\0';
  189.  
  190. state.pos++;
  191. return state.format_string[state.pos];
  192. }
  193.  
  194. void ResetPlaceholderState() {
  195. state.last_value_start=state.last_key_start=state.last_left_brace=START_POS;
  196. }
  197.  
  198. void SetString(std::string const& _) {
  199. state.format_string=_;
  200. state.pos=START_POS;
  201. ResetPlaceholderState();
  202. }
  203.  
  204. void TryAddPlaceholder() {
  205. if (state.current_placeholder.id!=START_POS) {
  206. state.current_placeholder.length=state.pos-state.last_left_brace+1;
  207. state.placeholders.push_back(std::make_pair(state.last_left_brace,state.current_placeholder));
  208. }
  209. }
  210.  
  211. public:
  212.  
  213.  
  214. void StartCollectingPlaceholder() {
  215. state.current_placeholder=Placeholder();
  216. state.last_left_brace=state.pos;
  217. state.last_key_start=state.last_value_start=START_POS;
  218. state.last_key="";
  219. }
  220.  
  221. void ParsePlaceholder() {
  222. int id=string_to_key(std::string(state.format_string.begin()+state.last_left_brace+1,state.format_string.begin()+state.pos));
  223. state.current_placeholder.id=id;
  224. }
  225.  
  226. void AddValue() {
  227. state.current_placeholder.config[state.last_key]=
  228. std::string(state.format_string.begin()+state.last_value_start+1,state.format_string.begin()+state.pos);
  229. state.last_key_start=state.pos;
  230. state.last_value_start=START_POS;
  231. }
  232.  
  233. void StartKey() {
  234. state.last_key_start=state.pos;
  235. state.last_value_start=START_POS;
  236. state.last_key="";
  237. }
  238.  
  239. void AddKey() {
  240. if ( (state.pos-state.last_key_start) < 1 )
  241. return;
  242. state.last_key=std::string(state.format_string.begin()+state.last_key_start+1,state.format_string.begin()+state.pos);
  243. state.current_placeholder.config[state.last_key]="";
  244. }
  245.  
  246. void ContinueCollectingKeys() {
  247. state.last_key_start=state.pos;
  248. }
  249.  
  250. void StartAddingValue() {
  251. state.last_key_start=START_POS;
  252. state.last_value_start=state.pos;
  253. }
  254.  
  255. void FinishCollectingPlaceholder() {
  256. if (state.last_key_start!=START_POS)
  257. AddKey();
  258.  
  259. if (state.last_left_brace!=START_POS
  260. && (state.pos-state.last_left_brace) > 1) {
  261. TryAddPlaceholder();
  262. }
  263.  
  264. ResetPlaceholderState();
  265. }
  266.  
  267. void Continue() {
  268. }
  269.  
  270. void FSMError(const char*, const char*) {
  271. }
  272.  
  273. Placeholders Get() {
  274. return state.placeholders;
  275. }
  276.  
  277.  
  278. };
  279.  
  280.  
  281. // Forward Declarations
  282.  
  283. class FormatParser;
  284.  
  285. //----------------------------------------------
  286. // FormatParserState: The base state class
  287. //----------------------------------------------
  288. class FormatParserState
  289. {
  290. public:
  291. virtual const char* StateName() const = 0;
  292. virtual void ReadEqualsSign( FormatParser& );
  293. virtual void ReadRightBrace( FormatParser& );
  294. virtual void ReadLeftBrace( FormatParser& );
  295. virtual void ReadComma( FormatParser& );
  296. };
  297.  
  298. //----------------------------------------------
  299. // State: ReadingKey
  300. //----------------------------------------------
  301. class FormatParserReadingKeyState : public FormatParserState
  302. {
  303. public:
  304. virtual const char* StateName() const
  305. { return "ReadingKey"; }
  306. virtual void ReadEqualsSign( FormatParser& );
  307. virtual void ReadComma( FormatParser& );
  308. virtual void ReadLeftBrace( FormatParser& );
  309. virtual void ReadRightBrace( FormatParser& );
  310. };
  311. //----------------------------------------------
  312. // State: General
  313. //----------------------------------------------
  314. class FormatParserGeneralState : public FormatParserState
  315. {
  316. public:
  317. virtual const char* StateName() const
  318. { return "General"; }
  319. virtual void ReadLeftBrace( FormatParser& );
  320. };
  321. //----------------------------------------------
  322. // State: ReadingPlaceholder
  323. //----------------------------------------------
  324. class FormatParserReadingPlaceholderState : public FormatParserState
  325. {
  326. public:
  327. virtual const char* StateName() const
  328. { return "ReadingPlaceholder"; }
  329. virtual void ReadLeftBrace( FormatParser& );
  330. virtual void ReadRightBrace( FormatParser& );
  331. virtual void ReadComma( FormatParser& );
  332. };
  333. //----------------------------------------------
  334. // State: ReadingValue
  335. //----------------------------------------------
  336. class FormatParserReadingValueState : public FormatParserState
  337. {
  338. public:
  339. virtual const char* StateName() const
  340. { return "ReadingValue"; }
  341. virtual void ReadRightBrace( FormatParser& );
  342. virtual void ReadLeftBrace( FormatParser& );
  343. virtual void ReadComma( FormatParser& );
  344. };
  345. //----------------------------------------------
  346. // FormatParser: The Finite State Machine class
  347. //----------------------------------------------
  348. class FormatParser: public FormatContext
  349. {
  350. public:
  351. // Static State variables
  352. static FormatParserReadingKeyState ReadingKey;
  353. static FormatParserGeneralState General;
  354. static FormatParserReadingPlaceholderState ReadingPlaceholder;
  355. static FormatParserReadingValueState ReadingValue;
  356.  
  357. FormatParser(); // default Constructor
  358.  
  359. // Event functions
  360. virtual void ReadEqualsSign() { itsState->ReadEqualsSign( *this ); }
  361. virtual void ReadRightBrace() { itsState->ReadRightBrace( *this ); }
  362. virtual void ReadLeftBrace() { itsState->ReadLeftBrace( *this ); }
  363. virtual void ReadComma() { itsState->ReadComma( *this ); }
  364.  
  365. // State Accessor functions
  366. void SetState( FormatParserState& theState ) { itsState = &theState; }
  367. FormatParserState& GetState() const { return *itsState; }
  368.  
  369. const char* GetCurrentStateName() const { return itsState->StateName(); }
  370. const char* GetVersion() const;
  371.  
  372. private:
  373. FormatParserState* itsState;
  374. };
  375.  
  376. //////////////////PARSER END//////////////////////////
  377.  
  378.  
  379. typedef detail::stream<std::string,std::stringstream> TStream;
  380. typedef std::string TString;
  381. typedef size_t TPos;
  382. typedef std::string TParam;
  383. typedef std::map<TPos,TParam> TParameters;
  384. typedef config<char> TConfig;
  385.  
  386. template <
  387. typename TConfig
  388. >
  389. class formatter {
  390.  
  391. public:
  392. formatter(TString fmt):
  393. format_string(fmt),
  394. pos(TConfig::index_begin)
  395. {
  396. parse_format_string();
  397. }
  398.  
  399. public:
  400.  
  401. template <typename T>
  402. formatter& with(T const& param) {
  403. size_t count=placeholders.size();
  404. for (size_t it=0;
  405. it<count;
  406. it++) {
  407. stream.clear();
  408. if (placeholders[it].second.id==pos) {
  409. stream.configure(placeholders[it].second.config);
  410. stream.put(param);
  411. parameters[it]=stream.str();
  412. }
  413. }
  414. pos++;
  415. return *this;
  416. }
  417.  
  418. template <typename T>
  419. formatter& also_with(T const& param) {
  420. return with(param);
  421. }
  422.  
  423. TString now() const {
  424. size_t param_count=parameters.size();
  425.  
  426. if (param_count==0) {
  427. return format_string;
  428. } else {
  429. return assemble_string();
  430. }
  431. }
  432.  
  433. void clear_parameters() {
  434. parameters.clear();
  435. pos=TConfig::index_begin;
  436. }
  437.  
  438. private:
  439.  
  440. TString assemble_string() const {
  441. std::string res(format_string);
  442.  
  443. for (TParameters::const_reverse_iterator it=parameters.rbegin();
  444. it!=parameters.rend();
  445. ++it) {
  446. std::pair<int,Placeholder> const& pl=placeholders[it->first];
  447. res.replace(pl.first,pl.second.length,it->second);
  448. }
  449.  
  450. return res;
  451. }
  452.  
  453. private:
  454. void parse_format_string() {
  455. FormatParser f;
  456. f.SetString(format_string);
  457.  
  458. while (!f.IsAtEnd()) {
  459. char c=f.Step();
  460. switch (c) {
  461. case TConfig::scope_begin: f.ReadLeftBrace(); break;
  462. case TConfig::scope_end: f.ReadRightBrace(); break;
  463. case TConfig::separator: f.ReadComma(); break;
  464. case TConfig::equals: f.ReadEqualsSign(); break;
  465. default : f.Continue(); break;
  466. }
  467. }
  468. placeholders=f.Get();
  469. }
  470.  
  471. private:
  472. TString format_string;
  473. Placeholders placeholders;
  474. TParameters parameters;
  475. TPos pos;
  476.  
  477. TStream stream; // Caution: the stream is shared within the implementation!
  478. };
  479.  
  480. typedef formatter< config<char> > format;
  481.  
  482. }
  483.  
  484. namespace ff {
  485. //----------------------------------------------
  486. // format.cpp
  487. // FSM: FormatParser
  488. // Context: FormatContext
  489. // Version:
  490. // Generated: Samstag 09/21/2013 at 16:23:34 MESZ
  491. //
  492.  
  493.  
  494. static char _versID[] = "";
  495.  
  496.  
  497.  
  498. //----------------------------------------------
  499. // Definitions of static state objects
  500.  
  501. //----------------------------------------------
  502. FormatParserReadingKeyState FormatParser::ReadingKey;
  503. FormatParserGeneralState FormatParser::General;
  504. FormatParserReadingPlaceholderState FormatParser::ReadingPlaceholder;
  505. FormatParserReadingValueState FormatParser::ReadingValue;
  506.  
  507. //----------------------------------------------
  508. // Default Event Functions
  509.  
  510. //----------------------------------------------
  511.  
  512. void FormatParserState::ReadEqualsSign(FormatParser& s)
  513. { s.FSMError("ReadEqualsSign", s.GetState().StateName()); }
  514.  
  515. void FormatParserState::ReadRightBrace(FormatParser& s)
  516. { s.FSMError("ReadRightBrace", s.GetState().StateName()); }
  517.  
  518. void FormatParserState::ReadLeftBrace(FormatParser& s)
  519. { s.FSMError("ReadLeftBrace", s.GetState().StateName()); }
  520.  
  521. void FormatParserState::ReadComma(FormatParser& s)
  522. { s.FSMError("ReadComma", s.GetState().StateName()); }
  523.  
  524. //----------------------------------------------
  525. // The States and their Transitions
  526. //----------------------------------------------
  527.  
  528. //----------------------------------------------
  529. // ReadingKey Actions and Transitions
  530. //----------------------------------------------
  531.  
  532. // Starting State: ReadingKey
  533. // Event: ReadEqualsSign
  534. //
  535. void FormatParserReadingKeyState::ReadEqualsSign( FormatParser& s )
  536. {
  537.  
  538. s.AddKey();
  539. s.StartAddingValue();
  540.  
  541. // Change the state
  542. s.SetState(FormatParser::ReadingValue);
  543. }
  544.  
  545. // Starting State: ReadingKey
  546. // Event: ReadComma
  547. //
  548. void FormatParserReadingKeyState::ReadComma( FormatParser& s )
  549. {
  550.  
  551. s.AddKey();
  552. s.ContinueCollectingKeys();
  553.  
  554. // Change the state
  555. s.SetState(FormatParser::ReadingKey);
  556. }
  557.  
  558. // Starting State: ReadingKey
  559. // Event: ReadLeftBrace
  560. //
  561. void FormatParserReadingKeyState::ReadLeftBrace( FormatParser& s )
  562. {
  563.  
  564. s.StartCollectingPlaceholder();
  565.  
  566. // Change the state
  567. s.SetState(FormatParser::ReadingPlaceholder);
  568. }
  569.  
  570. // Starting State: ReadingKey
  571. // Event: ReadRightBrace
  572. //
  573. void FormatParserReadingKeyState::ReadRightBrace( FormatParser& s )
  574. {
  575.  
  576. s.FinishCollectingPlaceholder();
  577.  
  578. // Change the state
  579. s.SetState(FormatParser::General);
  580. }
  581.  
  582. //----------------------------------------------
  583. // General Actions and Transitions
  584. //----------------------------------------------
  585.  
  586. // Starting State: General
  587. // Event: ReadLeftBrace
  588. //
  589. void FormatParserGeneralState::ReadLeftBrace( FormatParser& s )
  590. {
  591.  
  592. s.StartCollectingPlaceholder();
  593.  
  594. // Change the state
  595. s.SetState(FormatParser::ReadingPlaceholder);
  596. }
  597.  
  598. //----------------------------------------------
  599. // ReadingPlaceholder Actions and Transitions
  600. //----------------------------------------------
  601.  
  602. // Starting State: ReadingPlaceholder
  603. // Event: ReadLeftBrace
  604. //
  605. void FormatParserReadingPlaceholderState::ReadLeftBrace( FormatParser& s )
  606. {
  607.  
  608. s.StartCollectingPlaceholder();
  609.  
  610. // Change the state
  611. s.SetState(FormatParser::ReadingPlaceholder);
  612. }
  613.  
  614. // Starting State: ReadingPlaceholder
  615. // Event: ReadRightBrace
  616. //
  617. void FormatParserReadingPlaceholderState::ReadRightBrace( FormatParser& s )
  618. {
  619.  
  620. s.ParsePlaceholder();
  621. s.FinishCollectingPlaceholder();
  622.  
  623. // Change the state
  624. s.SetState(FormatParser::General);
  625. }
  626.  
  627. // Starting State: ReadingPlaceholder
  628. // Event: ReadComma
  629. //
  630. void FormatParserReadingPlaceholderState::ReadComma( FormatParser& s )
  631. {
  632.  
  633. s.ParsePlaceholder();
  634. s.StartKey();
  635.  
  636. // Change the state
  637. s.SetState(FormatParser::ReadingKey);
  638. }
  639.  
  640. //----------------------------------------------
  641. // ReadingValue Actions and Transitions
  642. //----------------------------------------------
  643.  
  644. // Starting State: ReadingValue
  645. // Event: ReadRightBrace
  646. //
  647. void FormatParserReadingValueState::ReadRightBrace( FormatParser& s )
  648. {
  649.  
  650. s.AddValue();
  651. s.FinishCollectingPlaceholder();
  652.  
  653. // Change the state
  654. s.SetState(FormatParser::General);
  655. }
  656.  
  657. // Starting State: ReadingValue
  658. // Event: ReadLeftBrace
  659. //
  660. void FormatParserReadingValueState::ReadLeftBrace( FormatParser& s )
  661. {
  662.  
  663. s.StartCollectingPlaceholder();
  664.  
  665. // Change the state
  666. s.SetState(FormatParser::ReadingPlaceholder);
  667. }
  668.  
  669. // Starting State: ReadingValue
  670. // Event: ReadComma
  671. //
  672. void FormatParserReadingValueState::ReadComma( FormatParser& s )
  673. {
  674.  
  675. s.AddValue();
  676.  
  677. // Change the state
  678. s.SetState(FormatParser::ReadingKey);
  679. }
  680.  
  681. //----------------------------------------------
  682. // State Machine Constructor: FormatParser
  683. // set Initial State to: General
  684. //
  685. //----------------------------------------------
  686. FormatParser::FormatParser() : itsState(&General)
  687. {
  688. // Entry functions for: General
  689. }
  690.  
  691. // Get version information
  692. //
  693. const char* FormatParser::GetVersion() const
  694. { return _versID; }
  695.  
  696. }
  697.  
  698. template <typename T1>
  699. std::string Format (std::string const& format_string,T1 p1) {
  700. return ff::format(format_string).with(p1).now();
  701. }
  702.  
  703. int main() {
  704. tryout<ff::format>();
  705. std::cout<<Format("test={1}",42)<<std::endl;
  706. return 0;
  707. }
  708.  
Success #stdin #stdout 0s 3512KB
stdin
Standard input is empty
stdout
with 3 zeroes: 1.000, without: 1
1:---------1
2:--------10
3:------1000
test=42