1 /*
2 Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
3 All Rights Reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of Sony Pictures Imageworks nor the names of its
14 contributors may be used to endorse or promote products derived from
15 this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <OpenColorIO/OpenColorIO.h>
30
31 #include <algorithm>
32
33 #include "LookParse.h"
34 #include "ParseUtils.h"
35 #include "pystring/pystring.h"
36 #include <iostream>
37
38 OCIO_NAMESPACE_ENTER
39 {
40 void LookParseResult::Token::parse(const std::string & str)
41 {
42 // Assert no commas, colons, or | in str.
43
44 if(pystring::startswith(str, "+"))
45 {
46 name = pystring::lstrip(str, "+");
47 dir = TRANSFORM_DIR_FORWARD;
48 }
49 // TODO: Handle --
50 else if(pystring::startswith(str, "-"))
51 {
52 name = pystring::lstrip(str, "-");
53 dir = TRANSFORM_DIR_INVERSE;
54 }
55 else
56 {
57 name = str;
58 dir = TRANSFORM_DIR_FORWARD;
59 }
60 }
61
62 void LookParseResult::Token::serialize(std::ostream & os) const
63 {
64 if(dir==TRANSFORM_DIR_FORWARD)
65 {
66 os << name;
67 }
68 else if(dir==TRANSFORM_DIR_INVERSE)
69 {
70 os << "-" << name;
71 }
72 else
73 {
74 os << "?" << name;
75 }
76 }
77
78 void LookParseResult::serialize(std::ostream & os, const Tokens & tokens)
79 {
80 for(unsigned int i=0; i<tokens.size(); ++i)
81 {
82 if(i!=0) os << ", ";
83 tokens[i].serialize(os);
84 }
85 }
86
87 const LookParseResult::Options & LookParseResult::parse(const std::string & looksstr)
88 {
89 m_options.clear();
90
91 std::string strippedlooks = pystring::strip(looksstr);
92 if(strippedlooks.empty())
93 {
94 return m_options;
95 }
96
97 std::vector<std::string> options;
98 pystring::split(strippedlooks, options, "|");
99
100 std::vector<std::string> vec;
101
102 for(unsigned int optionsindex=0;
103 optionsindex<options.size();
104 ++optionsindex)
105 {
106 LookParseResult::Tokens tokens;
107
108 vec.clear();
109 SplitStringEnvStyle(vec, options[optionsindex].c_str());
110 for(unsigned int i=0; i<vec.size(); ++i)
111 {
112 LookParseResult::Token t;
113 t.parse(vec[i]);
114 tokens.push_back(t);
115 }
116
117 m_options.push_back(tokens);
118 }
119
120 return m_options;
121 }
122
123 const LookParseResult::Options & LookParseResult::getOptions() const
124 {
125 return m_options;
126 }
127
128 bool LookParseResult::empty() const
129 {
130 return m_options.empty();
131 }
132
133 void LookParseResult::reverse()
134 {
135 // m_options itself should NOT be reversed.
136 // The individual looks
137 // need to be applied in the inverse direction. But, the precedence
138 // for which option to apply is to be maintained!
139
140 for(unsigned int optionindex=0;
141 optionindex<m_options.size();
142 ++optionindex)
143 {
144 std::reverse(m_options[optionindex].begin(), m_options[optionindex].end());
145
146 for(unsigned int tokenindex=0;
147 tokenindex<m_options[optionindex].size();
148 ++tokenindex)
149 {
150 m_options[optionindex][tokenindex].dir =
151 GetInverseTransformDirection(
152 m_options[optionindex][tokenindex].dir);
153 }
154 }
155 }
156 }
157 OCIO_NAMESPACE_EXIT
158
159
160
161 ///////////////////////////////////////////////////////////////////////////////
162
163 #ifdef OCIO_UNIT_TEST
164
165 OCIO_NAMESPACE_USING
166
167 #include "UnitTest.h"
168
169 OIIO_ADD_TEST(LookParse, Parse)
170 {
171 LookParseResult r;
172
173 {
174 const LookParseResult::Options & options = r.parse("");
175 OIIO_CHECK_EQUAL(options.size(), 0);
176 OIIO_CHECK_EQUAL(options.empty(), true);
177 }
178
179 {
180 const LookParseResult::Options & options = r.parse(" ");
181 OIIO_CHECK_EQUAL(options.size(), 0);
182 OIIO_CHECK_EQUAL(options.empty(), true);
183 }
184
185 {
186 const LookParseResult::Options & options = r.parse("cc");
187 OIIO_CHECK_EQUAL(options.size(), 1);
188 OIIO_CHECK_EQUAL(options[0][0].name, "cc");
189 OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
190 OIIO_CHECK_EQUAL(options.empty(), false);
191 }
192
193 {
194 const LookParseResult::Options & options = r.parse("+cc");
195 OIIO_CHECK_EQUAL(options.size(), 1);
196 OIIO_CHECK_EQUAL(options[0][0].name, "cc");
197 OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
198 OIIO_CHECK_EQUAL(options.empty(), false);
199 }
200
201 {
202 const LookParseResult::Options & options = r.parse(" +cc");
203 OIIO_CHECK_EQUAL(options.size(), 1);
204 OIIO_CHECK_EQUAL(options[0][0].name, "cc");
205 OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
206 OIIO_CHECK_EQUAL(options.empty(), false);
207 }
208
209 {
210 const LookParseResult::Options & options = r.parse(" +cc ");
211 OIIO_CHECK_EQUAL(options.size(), 1);
212 OIIO_CHECK_EQUAL(options[0][0].name, "cc");
213 OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
214 OIIO_CHECK_EQUAL(options.empty(), false);
215 }
216
217 {
218 const LookParseResult::Options & options = r.parse("+cc,-di");
219 OIIO_CHECK_EQUAL(options.size(), 1);
220 OIIO_CHECK_EQUAL(options[0].size(), 2);
221 OIIO_CHECK_EQUAL(options[0][0].name, "cc");
222 OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
223 OIIO_CHECK_EQUAL(options[0][1].name, "di");
224 OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
225 OIIO_CHECK_EQUAL(options.empty(), false);
226 }
227
228 {
229 const LookParseResult::Options & options = r.parse(" +cc , -di");
230 OIIO_CHECK_EQUAL(options.size(), 1);
231 OIIO_CHECK_EQUAL(options[0].size(), 2);
232 OIIO_CHECK_EQUAL(options[0][0].name, "cc");
233 OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
234 OIIO_CHECK_EQUAL(options[0][1].name, "di");
235 OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
236 OIIO_CHECK_EQUAL(options.empty(), false);
237 }
238
239 {
240 const LookParseResult::Options & options = r.parse(" +cc : -di");
241 OIIO_CHECK_EQUAL(options.size(), 1);
242 OIIO_CHECK_EQUAL(options[0].size(), 2);
243 OIIO_CHECK_EQUAL(options[0][0].name, "cc");
244 OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
245 OIIO_CHECK_EQUAL(options[0][1].name, "di");
246 OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
247 OIIO_CHECK_EQUAL(options.empty(), false);
248 }
249
250 {
251 const LookParseResult::Options & options = r.parse("+cc, -di |-cc");
252 OIIO_CHECK_EQUAL(options.size(), 2);
253 OIIO_CHECK_EQUAL(options[0].size(), 2);
254 OIIO_CHECK_EQUAL(options[0][0].name, "cc");
255 OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
256 OIIO_CHECK_EQUAL(options[0][1].name, "di");
257 OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
258 OIIO_CHECK_EQUAL(options[1].size(), 1);
259 OIIO_CHECK_EQUAL(options.empty(), false);
260 OIIO_CHECK_EQUAL(options[1][0].name, "cc");
261 OIIO_CHECK_EQUAL(options[1][0].dir, TRANSFORM_DIR_INVERSE);
262 }
263
264 {
265 const LookParseResult::Options & options = r.parse("+cc, -di |-cc| ");
266 OIIO_CHECK_EQUAL(options.size(), 3);
267 OIIO_CHECK_EQUAL(options[0].size(), 2);
268 OIIO_CHECK_EQUAL(options[0][0].name, "cc");
269 OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
270 OIIO_CHECK_EQUAL(options[0][1].name, "di");
271 OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
272 OIIO_CHECK_EQUAL(options[1].size(), 1);
273 OIIO_CHECK_EQUAL(options.empty(), false);
274 OIIO_CHECK_EQUAL(options[1][0].name, "cc");
275 OIIO_CHECK_EQUAL(options[1][0].dir, TRANSFORM_DIR_INVERSE);
276 OIIO_CHECK_EQUAL(options[2].size(), 1);
277 OIIO_CHECK_EQUAL(options[2][0].name, "");
278 OIIO_CHECK_EQUAL(options[2][0].dir, TRANSFORM_DIR_FORWARD);
279 }
280 }
281
OIIO_ADD_TEST(LookParse,Reverse)282 OIIO_ADD_TEST(LookParse, Reverse)
283 {
284 LookParseResult r;
285
286 {
287 r.parse("+cc, -di |-cc| ");
288 r.reverse();
289 const LookParseResult::Options & options = r.getOptions();
290
291 OIIO_CHECK_EQUAL(options.size(), 3);
292 OIIO_CHECK_EQUAL(options[0].size(), 2);
293 OIIO_CHECK_EQUAL(options[0][1].name, "cc");
294 OIIO_CHECK_EQUAL(options[0][1].dir, TRANSFORM_DIR_INVERSE);
295 OIIO_CHECK_EQUAL(options[0][0].name, "di");
296 OIIO_CHECK_EQUAL(options[0][0].dir, TRANSFORM_DIR_FORWARD);
297 OIIO_CHECK_EQUAL(options[1].size(), 1);
298 OIIO_CHECK_EQUAL(options.empty(), false);
299 OIIO_CHECK_EQUAL(options[1][0].name, "cc");
300 OIIO_CHECK_EQUAL(options[1][0].dir, TRANSFORM_DIR_FORWARD);
301 OIIO_CHECK_EQUAL(options[2].size(), 1);
302 OIIO_CHECK_EQUAL(options[2][0].name, "");
303 OIIO_CHECK_EQUAL(options[2][0].dir, TRANSFORM_DIR_INVERSE);
304 }
305
306
307 }
308
309 #endif // OCIO_UNIT_TEST
310