1/*
2 * Copyright (c) 2011-2015, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30#include "SelectionCriterionType.h"
31#include "Tokenizer.h"
32#include <sstream>
33#include <climits>
34
35#define base CElement
36
37const std::string CSelectionCriterionType::_strDelimiter = "|";
38
39CSelectionCriterionType::CSelectionCriterionType(bool bIsInclusive) : _bInclusive(bIsInclusive)
40{
41    // For inclusive criterion type, appends the pair none,0 by default.
42    if (_bInclusive) {
43
44        _numToLitMap["none"] = 0;
45    }
46}
47
48std::string CSelectionCriterionType::getKind() const
49{
50    return "SelectionCriterionType";
51}
52
53// From ISelectionCriterionTypeInterface
54bool CSelectionCriterionType::addValuePair(int iValue, const std::string &strValue,
55                                           std::string &strError)
56{
57    // Check 1 bit set only for inclusive types
58    if (_bInclusive && (!iValue || (iValue & (iValue - 1)))) {
59
60        std::ostringstream error;
61        error << "Rejecting value pair association: 0x" << std::hex << iValue << " - " << strValue
62              << " for Selection Criterion Type " << getName();
63        strError = error.str();
64
65        return false;
66    }
67
68    // Check already inserted
69    if (_numToLitMap.find(strValue) != _numToLitMap.end()) {
70
71        std::ostringstream error;
72        error << "Rejecting value pair association (literal already present): 0x" << std::hex
73              << iValue << " - " << strValue << " for Selection Criterion Type " << getName();
74        strError = error.str();
75
76        return false;
77    }
78    for (NumToLitMapConstIt it = _numToLitMap.begin(); it != _numToLitMap.end(); ++it) {
79        if (it->second == iValue) {
80            std::ostringstream error;
81            error << "Rejecting value pair association (numerical already present):"
82                  << " 0x" << std::hex << iValue << " - " << strValue
83                  << " for Selection Criterion Type " << getName();
84            strError = error.str();
85            return false;
86        }
87    }
88    _numToLitMap[strValue] = iValue;
89
90    return true;
91}
92
93bool CSelectionCriterionType::getNumericalValue(const std::string &strValue, int &iValue) const
94{
95    if (_bInclusive) {
96
97        Tokenizer tok(strValue, _strDelimiter);
98        std::vector<std::string> astrValues = tok.split();
99        size_t uiNbValues = astrValues.size();
100        int iResult = 0;
101        size_t uiValueIndex;
102        iValue = 0;
103
104        // Looping on each std::string delimited by "|" token and adding the associated value
105        for (uiValueIndex = 0; uiValueIndex < uiNbValues; uiValueIndex++) {
106
107            if (!getAtomicNumericalValue(astrValues[uiValueIndex], iResult)) {
108
109                return false;
110            }
111            iValue |= iResult;
112        }
113        return true;
114    }
115    return getAtomicNumericalValue(strValue, iValue);
116}
117
118bool CSelectionCriterionType::getAtomicNumericalValue(const std::string &strValue,
119                                                      int &iValue) const
120{
121    NumToLitMapConstIt it = _numToLitMap.find(strValue);
122
123    if (it != _numToLitMap.end()) {
124
125        iValue = it->second;
126
127        return true;
128    }
129    return false;
130}
131
132bool CSelectionCriterionType::getLiteralValue(int iValue, std::string &strValue) const
133{
134    NumToLitMapConstIt it;
135
136    for (it = _numToLitMap.begin(); it != _numToLitMap.end(); ++it) {
137
138        if (it->second == iValue) {
139
140            strValue = it->first;
141
142            return true;
143        }
144    }
145    return false;
146}
147
148bool CSelectionCriterionType::isTypeInclusive() const
149{
150    return _bInclusive;
151}
152
153// Value list
154std::string CSelectionCriterionType::listPossibleValues() const
155{
156    std::string strValueList = "{";
157
158    // Get comma seprated list of values
159    NumToLitMapConstIt it;
160    bool bFirst = true;
161
162    for (it = _numToLitMap.begin(); it != _numToLitMap.end(); ++it) {
163
164        if (bFirst) {
165
166            bFirst = false;
167        } else {
168            strValueList += ", ";
169        }
170        strValueList += it->first;
171    }
172
173    strValueList += "}";
174
175    return strValueList;
176}
177
178// Formatted state
179std::string CSelectionCriterionType::getFormattedState(int iValue) const
180{
181    std::string strFormattedState;
182
183    if (_bInclusive) {
184
185        // Need to go through all set bit
186        bool bFirst = true;
187
188        for (size_t bit = 0; bit < sizeof(iValue) * CHAR_BIT; bit++) {
189
190            int iSingleBitValue = iValue & (1 << bit);
191
192            // Check if current bit is set
193            if (!iSingleBitValue) {
194
195                continue;
196            }
197
198            // Simple translation
199            std::string strSingleValue;
200
201            if (!getLiteralValue(iSingleBitValue, strSingleValue)) {
202                // Numeric value not part supported values for this criterion type.
203                continue;
204            }
205
206            if (bFirst) {
207
208                bFirst = false;
209            } else {
210                strFormattedState += "|";
211            }
212
213            strFormattedState += strSingleValue;
214        }
215
216    } else {
217        // Simple translation
218        getLiteralValue(iValue, strFormattedState);
219    }
220
221    // Sometimes nothing is set
222    if (strFormattedState.empty()) {
223
224        strFormattedState = "<none>";
225    }
226
227    return strFormattedState;
228}
229
230// From IXmlSource
231void CSelectionCriterionType::toXml(CXmlElement &xmlElement,
232                                    CXmlSerializingContext &serializingContext) const
233{
234    // Type Kind
235    xmlElement.setAttribute("Kind", isTypeInclusive() ? "Inclusive" : "Exclusive");
236
237    // Value pairs as children
238    NumToLitMapConstIt it;
239
240    for (it = _numToLitMap.begin(); it != _numToLitMap.end(); ++it) {
241
242        CXmlElement childValuePairElement;
243
244        xmlElement.createChild(childValuePairElement, "ValuePair");
245        // Literal
246        childValuePairElement.setAttribute("Literal", it->first);
247        // Numerical
248        childValuePairElement.setAttribute("Numerical", it->second);
249    }
250
251    base::toXml(xmlElement, serializingContext);
252}
253