KSeExpr  4.0.4.0
ControlSpec.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2011-2019 Disney Enterprises, Inc.
2 // SPDX-License-Identifier: LicenseRef-Apache-2.0
3 // SPDX-FileCopyrightText: 2020 L. E. Segovia <amy@amyspark.me>
4 // SPDX-License-Identifier: GPL-3.0-or-later
5 
6 #include <KSeExpr/ExprNode.h>
7 #include <KSeExpr/ExprPatterns.h>
8 #include <sstream>
9 
10 #include "ControlSpec.h"
11 #include "Utils.h"
12 
13 namespace KSeExpr
14 {
16 {
17  for (auto &i : _specList)
18  delete i;
19 }
20 
21 bool SpecExaminer::examine(const ExprNode *examinee)
22 {
23  if (const ExprScalarAssignSpec *s_spec = ExprScalarAssignSpec::match(examinee)) {
24  _specList.push_back(s_spec);
25  return false;
26  } else if (const ExprVectorAssignSpec *v_spec = ExprVectorAssignSpec::match(examinee)) {
27  _specList.push_back(v_spec);
28  return false;
29  } else if (const ExprCurveAssignSpec<double> *c_spec = ExprCurveAssignSpec<double>::match(examinee)) {
30  _specList.push_back(c_spec);
31  return false;
32  } else if (const ExprCurveAssignSpec<Vec3d> *cc_spec = ExprCurveAssignSpec<Vec3d>::match(examinee)) {
33  _specList.push_back(cc_spec);
34  return false;
35  } else if (const ExprStrSpec *str_spec = ExprStrSpec::match(examinee)) {
36  _specList.push_back(str_spec);
37  return false;
38  };
39 
40  return true;
41 }
42 
43 inline std::vector<const ControlSpec *>::const_iterator SpecExaminer::begin() const
44 {
45  return _specList.begin();
46 }
47 
48 inline std::vector<const ControlSpec *>::const_iterator SpecExaminer::end() const
49 {
50  return _specList.end();
51 }
52 
54 inline bool isWS(const char *source, int start, int end)
55 {
56  for (int i = start; i < end; ++i)
57  if (source[i] != '\n')
58  return false;
59  return true;
60 }
61 
63 inline std::string findComment(const ExprNode &node)
64 {
65  const Expression &expr = *node.expr();
66  using Comments = std::vector<std::pair<int, int>>;
67  const Comments &comments = expr.getComments();
68  const std::string &s = expr.getExpr();
69 
70  // TODO: user lower_bound to make this O(lg n) instead of O(n)
71  for (const auto &i : comments) {
72  if (i.first >= node.endPos() && isWS(s.c_str(), node.endPos(), i.first))
73  return s.substr(i.first, i.second - i.first + 1);
74  }
75  return "";
76 }
77 
79  : ControlSpec(node)
80  , _min(0)
81  , _max(1)
82  , _val(dynamic_cast<const ExprNumNode *>(node.child(0))->value())
83 {
84  _name = node.name();
85  std::string comment = findComment(node);
86  if (comment.find('.') != std::string::npos || comment.find('e') != std::string::npos) {
87  float fmin = NAN;
88  float fmax = NAN;
89  if (KSeExpr::Utils::parseRangeComment(comment, fmin, fmax)) {
90  _min = fmin;
91  _max = fmax;
92  return;
93  }
94  } else {
95  int32_t imin = 0;
96  int32_t imax = 0;
97  if (KSeExpr::Utils::parseRangeComment(comment, imin, imax)) {
98  _min = imin;
99  _max = imax;
100  } else {
101  _min = 0;
102  _max = 1;
103  }
104  }
105 }
106 
108 {
109  std::stringstream ss;
110 
111  ss << _name << ": " << value() << " in [" << _min << "," << _max << "]" << std::endl;
112 
113  return ss.str();
114 }
115 
117 {
118  if (const ExprAssignNode *assign = isScalarAssign(node))
119  return new ExprScalarAssignSpec(*assign);
120 
121  return nullptr;
122 }
123 
125  : ControlSpec(node)
126  , _min(0)
127  , _max(1)
128  , _val(Vec3d(dynamic_cast<const ExprNumNode *>(node.child(0)->child(0))->value(), dynamic_cast<const ExprNumNode *>(node.child(0)->child(1))->value(), dynamic_cast<const ExprNumNode *>(node.child(0)->child(2))->value()))
129 {
130  _name = node.name();
131  std::string comment = findComment(node);
132  if (comment.find('.') != std::string::npos || comment.find('e') != std::string::npos) {
133  float fmin = NAN;
134  float fmax = NAN;
135  if (KSeExpr::Utils::parseRangeComment(comment, fmin, fmax)) {
136  _min = fmin;
137  _max = fmax;
138  return;
139  }
140  }
141  _min = 0;
142  _max = 1;
143 }
144 
146 {
147  std::stringstream ss;
148 
149  ss << _name << ": " << value() << " in [" << _min << "," << _max << "]" << std::endl;
150  ;
151 
152  return ss.str();
153 }
154 
155 template<class T>
157  : ControlSpec(node)
158  , _vec()
159 {
160  _name = node.name();
161  const auto *cnode = dynamic_cast<const ExprFuncNode *>(node.child(0));
162  _lookupText = cnode->child(0)->toString();
163  int num = cnode->numChildren();
164  for (int i = 1; i < num - 2; i += 3) {
165  // Someone at disney forgot that doubles cannot go straight to enums... -amyspark
166  auto x = static_cast<typename Curve<T>::InterpType>((int)(dynamic_cast<const ExprNumNode *>(cnode->child(i + 2))->value()));
167  _vec.push_back(typename Curve<T>::CV(
168  dynamic_cast<const ExprNumNode *>(cnode->child(i))->value(),
169  dynamic_cast<const ExprNumNode *>(cnode->child(i + 1))->value(),
170  x));
171  }
172 }
173 
175 {
176  if (const ExprAssignNode *assign = isVectorAssign(node)) {
177  return new ExprVectorAssignSpec(*assign);
178  }
179 
180  return nullptr;
181 }
182 
183 template<class T> std::string ExprCurveAssignSpec<T>::toString() const
184 {
185  std::stringstream ss;
186 
187  ss << _name << ": "
188  << "curve(" << _lookupText;
189  int num = _vec.size();
190  for (int i = 0; i < num; ++i)
191  ss << _vec[i]._pos << _vec[i]._val << (int)_vec[i]._interp;
192  ss << ");";
193 
194  return ss.str();
195 }
196 
197 template<class T> const ExprCurveAssignSpec<T> *ExprCurveAssignSpec<T>::match(const ExprNode *node)
198 {
199  if (const ExprAssignNode *assign = isCurveAssign(node))
200  return new ExprCurveAssignSpec(*assign);
201 
202  return 0;
203 }
204 
205 #if 0
206 
207 ExprCcurveAssignSpec::
208 ExprCcurveAssignSpec(const ExprAssignNode& node)
209  : ControlSpec(node),
210  _vec()
211 {
212  _name=node.name();
213  const ExprFuncNode* cnode(static_cast<const ExprFuncNode*>(node.child(0)));
214  _lookupText=cnode->child(0)->toString();
215  int num = cnode->numChildren();
216  for(int i = 1; i < num - 2; i += 3)
217  if(dynamic_cast<const ExprNumNode*>(cnode->child(i+1)))
218  _vec.push_back(Curve<Vec3d>::CV(
219  static_cast<const ExprNumNode*>(cnode->child(i))->value(),
220  static_cast<const ExprNumNode*>(cnode->child(i+1))->value(),
221  (Curve<Vec3d>::InterpType) static_cast<const ExprNumNode*>(cnode->child(i+2))->value()));
222 }
223 
224 std::string
225 ExprCcurveAssignSpec::toString() const
226 {
227  std::stringstream ss;
228 
229  ss << _name
230  << " = "
231  << "ccurve("
232  << _lookupText;
233  int num = _vec.size();
234  for(int i = 0; i < num; ++i)
235  ss << ", "
236  << _vec[i]._pos
237  << ", "
238  << _vec[i]._val
239  << ", "
240  << (int)_vec[i]._interp;
241  ss << ");";
242 
243  return ss.str();
244 }
245 
246 const ExprCcurveAssignSpec*
247 ExprCcurveAssignSpec::match(const ExprNode* node)
248 {
249  if(const ExprAssignNode* assign = isCcurveAssign(node))
250  return new ExprCcurveAssignSpec(*assign);
251 
252 
253  return 0;
254 }
255 
256 #endif
257 
258 std::string ExprStrSpec::toString() const
259 {
260  std::stringstream ss;
261  ss << _name << ": \"" + _str + "\" ";
262  switch (_type) {
263  case STRING:
264  ss << "STRING";
265  break;
266  case FILE:
267  ss << "FILE";
268  break;
269  case DIRECTORY:
270  ss << "DIRECTORY";
271  break;
272  default:
273  ss << "INVALID";
274  break;
275  }
276  return ss.str();
277 }
278 
280 {
281  if (const ExprStrNode *strnode = isString(node)) {
282  std::string comment = findComment(*node);
283  std::string name {};
284  std::string type {};
285  bool parsed = KSeExpr::Utils::parseTypeNameComment(comment, type, name);
286 
287  if (parsed) {
288  if (type == "string")
289  return new ExprStrSpec(*strnode, name.c_str(), STRING);
290  else if (type == "file")
291  return new ExprStrSpec(*strnode, name.c_str(), FILE);
292  else if (type == "directory")
293  return new ExprStrSpec(*strnode, name.c_str(), DIRECTORY);
294  }
295  }
296  return nullptr;
297 }
298 } // namespace KSeExpr
Generic Expression control specification.
Definition: ControlSpec.h:20
std::string _name
Name of control.
Definition: ControlSpec.h:36
InterpType
Supported interpolation types.
Definition: Curve.h:32
Node that compute a local variable assignment.
Definition: ExprNode.h:414
const std::string & name() const
Definition: ExprNode.h:427
Curve assignment expression. Assignment of curve to a variable.
Definition: ControlSpec.h:83
std::string toString() const override
Generates a replacement string based on changes to the spec.
static const ExprCurveAssignSpec * match(const ExprNode *node)
std::string _lookupText
Lookup subexpression text.
Definition: ControlSpec.h:91
std::vector< typename Curve< T >::CV > _vec
Control points of curve spline.
Definition: ControlSpec.h:93
ExprCurveAssignSpec(const ExprAssignNode &node)
Node that calls a function.
Definition: ExprNode.h:654
const Expression * expr() const
Access expression.
Definition: ExprNode.h:89
unsigned short int endPos() const
Access end position in input string.
Definition: ExprNode.h:169
const ExprNode * child(size_t i) const
Get 0 indexed child.
Definition: ExprNode.h:114
Node that stores a numeric constant.
Definition: ExprNode.h:610
double value() const
Definition: ExprNode.h:621
Variable equals scalar control specification.
Definition: ControlSpec.h:45
static const ExprScalarAssignSpec * match(const ExprNode *node)
ExprScalarAssignSpec(const ExprAssignNode &node)
Definition: ControlSpec.cpp:78
double _min
Range of values.
Definition: ControlSpec.h:57
std::string toString() const override
Generates a replacement string based on changes to the spec.
Node that stores a string.
Definition: ExprNode.h:632
static const ExprStrSpec * match(const ExprNode *node)
ExprStrSpec(const ExprStrNode &node, const char *name, Type type)
Takes name and type comments and takes ownership of them!
Definition: ControlSpec.h:102
std::string toString() const override
Generates a replacement string based on changes to the spec.
Variable equals vector control specification.
Definition: ControlSpec.h:64
std::string toString() const override
Generates a replacement string based on changes to the spec.
static const ExprVectorAssignSpec * match(const ExprNode *node)
double _min
Range of values.
Definition: ControlSpec.h:76
const Vec3d & value() const
Definition: ControlSpec.h:68
ExprVectorAssignSpec(const ExprAssignNode &node)
main expression class
Definition: Expression.h:67
const std::vector< std::pair< int, int > > & getComments() const
Definition: Expression.h:149
const std::string & getExpr() const
Get the string that this expression is currently set to evaluate.
Definition: Expression.h:116
bool examine(const ExprNode *examinee) override
Definition: ControlSpec.cpp:21
std::vector< const ControlSpec * >::const_iterator end() const
Definition: ControlSpec.cpp:48
std::vector< const ControlSpec * > _specList
Definition: ControlSpec.h:147
std::vector< const ControlSpec * >::const_iterator begin() const
Definition: ControlSpec.cpp:43
bool parseRangeComment(const std::string &comment, double &from, double &to)
Definition: Utils.cpp:7
bool parseTypeNameComment(const std::string &comment, std::string &type, std::string &name)
Definition: Utils.cpp:99
bool isWS(const char *source, int start, int end)
Returns true if no newline separates comment and node.
Definition: ControlSpec.cpp:54
const ExprAssignNode * isCurveAssign(const ExprNode *testee)
Definition: ExprPatterns.h:138
const ExprAssignNode * isVectorAssign(const ExprNode *testee)
Definition: ExprPatterns.h:118
const ExprAssignNode * isCcurveAssign(const ExprNode *testee)
Definition: ExprPatterns.h:148
const ExprStrNode * isString(const ExprNode *testee)
Definition: ExprPatterns.h:36
std::string findComment(const ExprNode &node)
Checks if there is whitespace in the range specified in the string.
Definition: ControlSpec.cpp:63
const ExprAssignNode * isScalarAssign(const ExprNode *testee)
Definition: ExprPatterns.h:108