fork(1) download
  1. /*!
  2.  * Hello world! application
  3.  *
  4.  * \file hello.cpp
  5.  */
  6.  
  7. #include <iostream>
  8. #include <vector>
  9. #include <algorithm>
  10. #include <functional>
  11. #include <cassert>
  12.  
  13. /*!
  14.  * Dispay message.
  15.  */
  16. void displayMessage();
  17.  
  18. /*!
  19.  * Sentence type
  20.  *
  21.  * Type of sentence, used to decide how to terminate sentence.
  22.  */
  23. enum ESentenceType {
  24. eStatement,
  25. eExclamation,
  26. sQuestion,
  27. eCommand
  28. };
  29.  
  30. /*!
  31.  * Utility class to prevent unintended copying of class instances.
  32.  */
  33. class nonCopyable {
  34. protected:
  35. nonCopyable() {
  36. }
  37.  
  38. ~nonCopyable() {
  39. }
  40.  
  41. private:
  42. nonCopyable(const nonCopyable&);
  43. const nonCopyable& operator=(const nonCopyable&);
  44. };
  45.  
  46. /*!
  47.  * Utility function to obtain punctuation mark to end sentence
  48.  * of specified type.
  49.  */
  50. inline char getPunctionMark(ESentenceType sentenceType) {
  51. char puncMark = '.';
  52. switch(sentenceType) {
  53. case eStatement : puncMark = '.'; break;
  54. case eExclamation: puncMark = '!'; break;
  55. case sQuestion : puncMark = '?'; break;
  56. case eCommand : puncMark = '.'; break;
  57. default: {
  58. // should never get here
  59. assert(false);
  60. }
  61. }
  62. return puncMark;
  63. }
  64.  
  65. /*!
  66.  * Utility class for creation of instances.
  67.  */
  68. template<typename TElem>
  69. class Creatable {
  70. protected:
  71. Creatable() {
  72. }
  73.  
  74. virtual ~Creatable() {
  75. clear();
  76. }
  77.  
  78. public:
  79. static TElem* create() {
  80. TElem* e = new TElem;
  81. return e;
  82. }
  83.  
  84. void free() {
  85. delete this;
  86. }
  87.  
  88. virtual void clear() {
  89. }
  90. };
  91.  
  92. template<typename TElem, typename TParam>
  93. class CreatableParam {
  94. protected:
  95. CreatableParam() {
  96. }
  97.  
  98. virtual ~CreatableParam() {
  99. }
  100.  
  101. public:
  102. static TElem* create(TParam p) {
  103. TElem* e = new TElem;
  104. e->initialize(p);
  105. return e;
  106. }
  107.  
  108. void free() {
  109. finalize();
  110. delete this;
  111. }
  112.  
  113. virtual void initialize(TParam /*p*/) {
  114. }
  115.  
  116. virtual void finalize() {
  117. clear();
  118. }
  119.  
  120. virtual void clear() {
  121. }
  122. };
  123.  
  124. /*!
  125.  * Base class for displayable content
  126.  */
  127. class DisplayElem
  128. : public nonCopyable {
  129. protected:
  130. DisplayElem() {
  131. }
  132.  
  133. virtual ~DisplayElem() {
  134. }
  135.  
  136. public:
  137. virtual void display(std::ostream& os) const = 0;
  138. };
  139.  
  140. /*!
  141.  * STL algorithm for displaying elements
  142.  */
  143. class Displayer
  144. : public std::unary_function<void, const DisplayElem*> {
  145. private:
  146. std::ostream& m_os;
  147. char m_sep;
  148. size_t m_count;
  149.  
  150. public:
  151. Displayer(std::ostream& os, char sep = '\0')
  152. : m_os(os)
  153. , m_sep(sep)
  154. , m_count(0) {
  155. }
  156.  
  157. ~Displayer() {
  158. }
  159.  
  160. void operator()(const DisplayElem* e) {
  161. if(('\0' != m_sep) && (0 < m_count)) {
  162. m_os << m_sep;
  163. }
  164. e->display(m_os);
  165. ++m_count;
  166. }
  167. };
  168.  
  169. /*!
  170.  * STL algorithm for freeing display elements
  171.  */
  172. template <typename TElem>
  173. class Freer
  174. : public std::unary_function<void, TElem*> {
  175. public:
  176. void operator()(TElem* e) {
  177. e->free();
  178. }
  179. };
  180.  
  181. /*!
  182.  * Display element for letter.
  183.  *
  184.  * The letter is the fundamental element: it has no substructure.
  185.  */
  186. class Letter
  187. : public DisplayElem
  188. , public CreatableParam<Letter, char> {
  189. private:
  190. char m_ch;
  191.  
  192. protected:
  193. /*virtual*/ ~Letter() {
  194. }
  195.  
  196. public:
  197. Letter() : m_ch('\0') {
  198. }
  199.  
  200. void initialize(char ch) {
  201. m_ch = ch;
  202. }
  203.  
  204. void finalize() {
  205. m_ch = '\0';
  206. }
  207.  
  208. void display(std::ostream& os) const {
  209. os << m_ch;
  210. // no endLetter()
  211. }
  212. };
  213.  
  214. /*!
  215.  * Display element for word.
  216.  *
  217.  * A word is a sequence of letters.
  218.  */
  219. class Word
  220. : public DisplayElem
  221. , public Creatable<Word> {
  222. private:
  223. std::vector<Letter*> m_letters;
  224.  
  225. protected:
  226. /*virtual*/ ~Word() {
  227. clear();
  228. }
  229.  
  230. public:
  231. Word() {
  232. }
  233.  
  234. void clear() {
  235. std::for_each(m_letters.begin(), m_letters.end(), Freer<Letter>());
  236. m_letters.clear();
  237. }
  238.  
  239. void addLetter(Letter* s) {
  240. m_letters.push_back(s);
  241. }
  242.  
  243. /*virtual*/ void display(std::ostream& os) const {
  244. std::for_each(m_letters.begin(), m_letters.end(), Displayer(os));
  245. // no endLetter()
  246. }
  247. };
  248.  
  249. /*!
  250.  * Display element for sentence.
  251.  *
  252.  * A sentence is a sequence of words.
  253.  */
  254. class Sentence
  255. : public DisplayElem
  256. , public CreatableParam<Sentence, ESentenceType> {
  257. private:
  258. std::vector<Word*> m_words;
  259.  
  260. ESentenceType m_sentenceType;
  261.  
  262. protected:
  263. /*virtual*/ ~Sentence() {
  264. clear();
  265. }
  266.  
  267. void endSentence(std::ostream& os) const {
  268. const char puncMark = getPunctionMark(m_sentenceType);
  269. os << puncMark;
  270. }
  271.  
  272. public:
  273. Sentence()
  274. : m_sentenceType(eStatement) {
  275. }
  276.  
  277. void initialize(ESentenceType sentenceType) {
  278. m_sentenceType = sentenceType;
  279. }
  280.  
  281. void finalize() {
  282. m_sentenceType = eStatement;
  283. }
  284.  
  285. void clear() {
  286. std::for_each(m_words.begin(), m_words.end(), Freer<Word>());
  287. m_words.clear();
  288. }
  289.  
  290. void addWord(Word* w) {
  291. m_words.push_back(w);
  292. }
  293.  
  294. void display(std::ostream& os) const {
  295. std::for_each(m_words.begin(), m_words.end(), Displayer(os, ' '));
  296. endSentence(os);
  297. }
  298. };
  299.  
  300. /*!
  301.  * Display element for message.
  302.  *
  303.  * A message is a sequence of sentences.
  304.  */
  305. class Message
  306. : public DisplayElem
  307. , public Creatable<Message> {
  308. private:
  309. std::vector<Sentence*> m_sentences;
  310.  
  311. protected:
  312. /*virtual*/ ~Message() {
  313. clear();
  314. }
  315.  
  316. void endMessage(std::ostream& os) const {
  317. os << std::endl;
  318. }
  319.  
  320. public:
  321. Message() {
  322. }
  323.  
  324. void clear() {
  325. std::for_each(m_sentences.begin(), m_sentences.end(), Freer<Sentence>());
  326. m_sentences.clear();
  327. }
  328.  
  329. void addSentence(Sentence* s) {
  330. m_sentences.push_back(s);
  331. }
  332.  
  333. void display(std::ostream& os) const {
  334. std::for_each(m_sentences.begin(), m_sentences.end(), Displayer(os, ' '));
  335. endMessage(os);
  336. }
  337. };
  338.  
  339. /*!
  340.  * Main entrance point.
  341.  */
  342. int main() {
  343. displayMessage();
  344. return 0;
  345. }
  346.  
  347. /*!
  348.  * Display message.
  349.  */
  350. void displayMessage() {
  351. Word* first_word = Word::create();
  352. first_word->addLetter(Letter::create('H'));
  353. first_word->addLetter(Letter::create('e'));
  354. first_word->addLetter(Letter::create('l'));
  355. first_word->addLetter(Letter::create('l'));
  356. first_word->addLetter(Letter::create('o'));
  357.  
  358. Word* second_word = Word::create();
  359. second_word->addLetter(Letter::create('w'));
  360. second_word->addLetter(Letter::create('o'));
  361. second_word->addLetter(Letter::create('r'));
  362. second_word->addLetter(Letter::create('l'));
  363. second_word->addLetter(Letter::create('d'));
  364.  
  365. Sentence* sentence = Sentence::create(eExclamation);
  366. sentence->addWord(first_word);
  367. sentence->addWord(second_word);
  368.  
  369. Message* message = Message::create();
  370. message->addSentence(sentence);
  371.  
  372. message->display(std::cout);
  373.  
  374. message->free();
  375. // sentences, etc freed by parent
  376. }
Success #stdin #stdout 0s 3480KB
stdin
Standard input is empty
stdout
Hello world!