CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
lang_stream_stack.hpp
1 #ifndef CPPAD_CG_LANG_STREAM_STACK_INCLUDED
2 #define CPPAD_CG_LANG_STREAM_STACK_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2019 Joao Leal
6  *
7  * CppADCodeGen is distributed under multiple licenses:
8  *
9  * - Eclipse Public License Version 1.0 (EPL1), and
10  * - GNU General Public License Version 3 (GPL3).
11  *
12  * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13  * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14  * ----------------------------------------------------------------------------
15  * Author: Joao Leal
16  */
17 
18 #include <ostream>
19 
20 namespace CppAD {
21 namespace cg {
22 
23 namespace _private {
24 
25 template<class Base>
27 private:
28  OperationNode<Base>* _node;
29  std::string _text;
30 public:
32  _node(&node) {
33  }
34 
35  inline LangStreamOperation(std::string text) :
36  _node(nullptr),
37  _text(std::move(text)) {
38  }
39 
40  OperationNode<Base>* getNode() const {
41  return _node;
42  }
43 
44  const std::string& getText() const {
45  return _text;
46  }
47 };
48 
49 }
50 
57 template<class Base>
59 private:
60  std::ostream& _out;
61  std::forward_list<_private::LangStreamOperation<Base> > _cache;
62  typename std::forward_list<_private::LangStreamOperation<Base> >::iterator _it;
63 public:
64  inline LangStreamStack(std::ostream& out) :
65  _out(out),
66  _it(_cache.before_begin()) {
67  }
68 
69  inline bool empty() const {
70  return _cache.empty();
71  }
72 
73  inline void clear() {
74  _cache.clear();
75  _it = _cache.before_begin();
76  }
77 
78  inline void flush() {
79  if (empty())
80  return;
81 
82  while (!_cache.empty() && _cache.begin()->getNode() == nullptr) {
83  _out << _cache.begin()->getText();
84  _cache.erase_after(_cache.before_begin());
85  }
86  _it = _cache.before_begin();
87  }
88 
89  inline OperationNode<Base>& startNewOperationNode() {
90  CPPAD_ASSERT_KNOWN(!_cache.empty(), "Cannot extract an operation node from an empty list")
91  CPPAD_ASSERT_KNOWN(_cache.begin()->getNode() != nullptr, "The first element in the list is not an OperationNode")
92  OperationNode<Base>* node = _cache.begin()->getNode();
93  _cache.erase_after(_cache.before_begin());
94  _it = _cache.before_begin();
95 
96  return *node;
97  }
98 
99  friend inline LangStreamStack<Base>& operator<<(LangStreamStack<Base>& lss, std::string text) {
100  if (lss._it == lss._cache.before_begin()) {
101  lss._out << text;
102  } else {
103  lss._it = lss._cache.emplace_after(lss._it, std::move(text));
104  }
105  return lss;
106  }
107 
108  friend inline LangStreamStack<Base>& operator<<(LangStreamStack<Base>& lss, int i) {
109  return (lss << std::to_string(i));
110  }
111 
112  friend inline LangStreamStack<Base>& operator<<(LangStreamStack<Base>& lss, long int i) {
113  return (lss << std::to_string(i));
114  }
115 
116  friend inline LangStreamStack<Base>& operator<<(LangStreamStack<Base>& lss, long long int i) {
117  return (lss << std::to_string(i));
118  }
119 
120  friend inline LangStreamStack<Base>& operator<<(LangStreamStack<Base>& lss, unsigned int i) {
121  return (lss << std::to_string(i));
122  }
123 
124  friend inline LangStreamStack<Base>& operator<<(LangStreamStack<Base>& lss, long unsigned int i) {
125  return (lss << std::to_string(i));
126  }
127 
128  friend inline LangStreamStack<Base>& operator<<(LangStreamStack<Base>& lss, long long unsigned int i) {
129  return (lss << std::to_string(i));
130  }
131 
132  friend inline LangStreamStack<Base>& operator<<(LangStreamStack<Base>& lss, char text) {
133  return (lss << std::string(1, text));
134  }
135 
136  friend inline LangStreamStack<Base>& operator<<(LangStreamStack<Base>& lss, OperationNode<Base>& node) {
137  lss._it = lss._cache.emplace_after(lss._it, node);
138 
139  return lss;
140  }
141 };
142 
143 } // END cg namespace
144 } // END CppAD namespace
145 
146 #endif