1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief String template class.
22 *//*--------------------------------------------------------------------*/
23
24 #include "tcuStringTemplate.hpp"
25 #include "tcuDefs.hpp"
26
27 #include "deStringUtil.hpp"
28
29 #include <sstream>
30
31 using std::string;
32 using std::map;
33 using std::ostringstream;
34
35 namespace tcu
36 {
37
StringTemplate(void)38 StringTemplate::StringTemplate (void)
39 {
40 }
41
StringTemplate(const std::string & str)42 StringTemplate::StringTemplate (const std::string& str)
43 {
44 setString(str);
45 }
46
StringTemplate(StringTemplate && other)47 StringTemplate::StringTemplate (StringTemplate&& other)
48 : m_template(std::move(other.m_template))
49 {}
50
~StringTemplate(void)51 StringTemplate::~StringTemplate (void)
52 {
53 }
54
setString(const std::string & str)55 void StringTemplate::setString (const std::string& str)
56 {
57 m_template = str;
58 }
59
60 const string kSingleLineFlag = "single-line";
61 const string kOptFlag = "opt";
62 const string kDefaultFlag = "default=";
63
specialize(const map<string,string> & params) const64 string StringTemplate::specialize (const map<string, string>& params) const
65 {
66 ostringstream res;
67
68 size_t curNdx = 0;
69 for (;;)
70 {
71 size_t paramNdx = m_template.find("${", curNdx);
72 if (paramNdx != string::npos)
73 {
74 // Append in-between stuff.
75 res << m_template.substr(curNdx, paramNdx - curNdx);
76
77 // Find end-of-param.
78 size_t paramEndNdx = m_template.find("}", paramNdx);
79 if (paramEndNdx == string::npos)
80 TCU_THROW(InternalError, "No '}' found in template parameter");
81
82 // Parse parameter contents.
83 string paramStr = m_template.substr(paramNdx+2, paramEndNdx-2-paramNdx);
84 bool paramSingleLine = false;
85 bool paramOptional = false;
86 bool paramDefault = false;
87 string paramName;
88 string defaultValue;
89 size_t colonNdx = paramStr.find(":");
90 if (colonNdx != string::npos)
91 {
92 paramName = paramStr.substr(0, colonNdx);
93 string flagsStr = paramStr.substr(colonNdx+1);
94 if (flagsStr == kSingleLineFlag)
95 {
96 paramSingleLine = true;
97 }
98 else if (flagsStr == kOptFlag)
99 {
100 paramOptional = true;
101 }
102 else if (de::beginsWith(flagsStr, kDefaultFlag))
103 {
104 paramDefault = true;
105 defaultValue = flagsStr.substr(kDefaultFlag.size());
106 }
107 else
108 {
109 TCU_THROW(InternalError, (string("Unrecognized flag") + paramStr).c_str());
110 }
111 }
112 else
113 paramName = paramStr;
114
115 // Fill in parameter value.
116 if (params.find(paramName) != params.end())
117 {
118 const string& val = (*params.find(paramName)).second;
119 if (paramSingleLine)
120 {
121 string tmp = val;
122 for (size_t ndx = tmp.find("\n"); ndx != string::npos; ndx = tmp.find("\n"))
123 tmp = tmp.replace(ndx, 1, " ");
124 res << tmp;
125 }
126 else
127 res << val;
128 }
129 else if (paramDefault)
130 res << defaultValue;
131 else if (!paramOptional)
132 TCU_THROW(InternalError, (string("Value for parameter '") + paramName + "' not found in map").c_str());
133
134 // Skip over template.
135 curNdx = paramEndNdx + 1;
136 }
137 else
138 {
139 if (curNdx < m_template.length())
140 res << &m_template[curNdx];
141
142 break;
143 }
144 }
145
146 return res.str();
147 }
148
149 } // tcu
150