1*b7893ccfSSadaf Ebrahimi /* Copyright (c) 2016-2019 The Khronos Group Inc. 2*b7893ccfSSadaf Ebrahimi * Copyright (c) 2016-2019 Valve Corporation 3*b7893ccfSSadaf Ebrahimi * Copyright (c) 2016-2019 LunarG, Inc. 4*b7893ccfSSadaf Ebrahimi * Copyright (c) 2016-2019 Google Inc. 5*b7893ccfSSadaf Ebrahimi * 6*b7893ccfSSadaf Ebrahimi * Licensed under the Apache License, Version 2.0 (the "License"); 7*b7893ccfSSadaf Ebrahimi * you may not use this file except in compliance with the License. 8*b7893ccfSSadaf Ebrahimi * You may obtain a copy of the License at 9*b7893ccfSSadaf Ebrahimi * 10*b7893ccfSSadaf Ebrahimi * http://www.apache.org/licenses/LICENSE-2.0 11*b7893ccfSSadaf Ebrahimi * 12*b7893ccfSSadaf Ebrahimi * Unless required by applicable law or agreed to in writing, software 13*b7893ccfSSadaf Ebrahimi * distributed under the License is distributed on an "AS IS" BASIS, 14*b7893ccfSSadaf Ebrahimi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15*b7893ccfSSadaf Ebrahimi * See the License for the specific language governing permissions and 16*b7893ccfSSadaf Ebrahimi * limitations under the License. 17*b7893ccfSSadaf Ebrahimi */ 18*b7893ccfSSadaf Ebrahimi #ifndef PARAMETER_NAME_H 19*b7893ccfSSadaf Ebrahimi #define PARAMETER_NAME_H 20*b7893ccfSSadaf Ebrahimi 21*b7893ccfSSadaf Ebrahimi #include <cassert> 22*b7893ccfSSadaf Ebrahimi #include <sstream> 23*b7893ccfSSadaf Ebrahimi #include <string> 24*b7893ccfSSadaf Ebrahimi #include <vector> 25*b7893ccfSSadaf Ebrahimi 26*b7893ccfSSadaf Ebrahimi /** 27*b7893ccfSSadaf Ebrahimi * Parameter name string supporting deferred formatting for array subscripts. 28*b7893ccfSSadaf Ebrahimi * 29*b7893ccfSSadaf Ebrahimi * Custom parameter name class with support for deferred formatting of names containing array subscripts. The class stores 30*b7893ccfSSadaf Ebrahimi * a format string and a pointer to an array of index values, and performs string formatting when an accessor function is called to 31*b7893ccfSSadaf Ebrahimi * retrieve the name string. This class was primarily designed to be used with validation functions that receive a parameter name 32*b7893ccfSSadaf Ebrahimi * string and value as arguments, and print an error message that includes the parameter name when the value fails a validation 33*b7893ccfSSadaf Ebrahimi * test. Using standard strings with these validation functions requires that parameter names containing array subscripts be 34*b7893ccfSSadaf Ebrahimi * formatted before each validation function is called, performing the string formatting even when the value passes validation 35*b7893ccfSSadaf Ebrahimi * and the string is not used: 36*b7893ccfSSadaf Ebrahimi * sprintf(name, "pCreateInfo[%d].sType", i); 37*b7893ccfSSadaf Ebrahimi * validate_stype(name, pCreateInfo[i].sType); 38*b7893ccfSSadaf Ebrahimi * 39*b7893ccfSSadaf Ebrahimi * With the ParameterName class, a format string and a pointer to an array of format values are stored by the ParameterName object 40*b7893ccfSSadaf Ebrahimi * that is provided to the validation function. String formatting is then performed only when the validation function retrieves the 41*b7893ccfSSadaf Ebrahimi * name string from the ParameterName object: 42*b7893ccfSSadaf Ebrahimi * validate_stype(ParameterName("pCreateInfo[%i].sType", IndexVector{ i }), pCreateInfo[i].sType); 43*b7893ccfSSadaf Ebrahimi * 44*b7893ccfSSadaf Ebrahimi * Since the IndexVector is not copied into the object, the lifetime of the ParameterName should not outlast the lifetime of 45*b7893ccfSSadaf Ebrahimi * the IndexVector, but that's fine given how it is used in parameter validation. 46*b7893ccfSSadaf Ebrahimi */ 47*b7893ccfSSadaf Ebrahimi class ParameterName { 48*b7893ccfSSadaf Ebrahimi public: 49*b7893ccfSSadaf Ebrahimi /// Container for index values to be used with parameter name string formatting. 50*b7893ccfSSadaf Ebrahimi typedef std::initializer_list<size_t> IndexVector; 51*b7893ccfSSadaf Ebrahimi 52*b7893ccfSSadaf Ebrahimi /// Format specifier for the parameter name string, to be replaced by an index value. The parameter name string must contain 53*b7893ccfSSadaf Ebrahimi /// one format specifier for each index value specified. 54*b7893ccfSSadaf Ebrahimi const char *const IndexFormatSpecifier = "%i"; 55*b7893ccfSSadaf Ebrahimi 56*b7893ccfSSadaf Ebrahimi public: 57*b7893ccfSSadaf Ebrahimi /** 58*b7893ccfSSadaf Ebrahimi * Construct a ParameterName object from a string literal, without formatting. 59*b7893ccfSSadaf Ebrahimi * 60*b7893ccfSSadaf Ebrahimi * @param source Paramater name string without format specifiers. 61*b7893ccfSSadaf Ebrahimi * 62*b7893ccfSSadaf Ebrahimi * @pre The source string must not contain the %i format specifier. 63*b7893ccfSSadaf Ebrahimi */ ParameterName(const char * source)64*b7893ccfSSadaf Ebrahimi ParameterName(const char *source) : source_(source), num_indices_(0) { assert(IsValid()); } 65*b7893ccfSSadaf Ebrahimi 66*b7893ccfSSadaf Ebrahimi /** 67*b7893ccfSSadaf Ebrahimi * Construct a ParameterName object from a string literal, with formatting. 68*b7893ccfSSadaf Ebrahimi * 69*b7893ccfSSadaf Ebrahimi * @param source Paramater name string with format specifiers. 70*b7893ccfSSadaf Ebrahimi * @param args Array index values to be used for formatting. 71*b7893ccfSSadaf Ebrahimi * 72*b7893ccfSSadaf Ebrahimi * @pre The number of %i format specifiers contained by the source string must match the number of elements contained 73*b7893ccfSSadaf Ebrahimi * by the index vector. 74*b7893ccfSSadaf Ebrahimi */ ParameterName(const char * source,const IndexVector & args)75*b7893ccfSSadaf Ebrahimi ParameterName(const char *source, const IndexVector &args) 76*b7893ccfSSadaf Ebrahimi : source_(source), args_(args.size() ? args.begin() : (const size_t *)nullptr), num_indices_(args.size()) { 77*b7893ccfSSadaf Ebrahimi assert(IsValid()); 78*b7893ccfSSadaf Ebrahimi } 79*b7893ccfSSadaf Ebrahimi 80*b7893ccfSSadaf Ebrahimi /// Retrive the formatted name string. get_name()81*b7893ccfSSadaf Ebrahimi std::string get_name() const { return (num_indices_ == 0) ? std::string(source_) : Format(); } 82*b7893ccfSSadaf Ebrahimi 83*b7893ccfSSadaf Ebrahimi private: 84*b7893ccfSSadaf Ebrahimi /// Replace the %i format specifiers in the source string with the values from the index vector. Format()85*b7893ccfSSadaf Ebrahimi std::string Format() const { 86*b7893ccfSSadaf Ebrahimi std::string::size_type current = 0; 87*b7893ccfSSadaf Ebrahimi std::string::size_type last = 0; 88*b7893ccfSSadaf Ebrahimi std::stringstream format; 89*b7893ccfSSadaf Ebrahimi 90*b7893ccfSSadaf Ebrahimi std::string source(source_); 91*b7893ccfSSadaf Ebrahimi 92*b7893ccfSSadaf Ebrahimi for (size_t i = 0; i < num_indices_; ++i) { 93*b7893ccfSSadaf Ebrahimi auto index = args_[i]; 94*b7893ccfSSadaf Ebrahimi current = source.find(IndexFormatSpecifier, last); 95*b7893ccfSSadaf Ebrahimi if (current == std::string::npos) { 96*b7893ccfSSadaf Ebrahimi break; 97*b7893ccfSSadaf Ebrahimi } 98*b7893ccfSSadaf Ebrahimi format << source.substr(last, (current - last)) << index; 99*b7893ccfSSadaf Ebrahimi last = current + strlen(IndexFormatSpecifier); 100*b7893ccfSSadaf Ebrahimi } 101*b7893ccfSSadaf Ebrahimi 102*b7893ccfSSadaf Ebrahimi format << source.substr(last, std::string::npos); 103*b7893ccfSSadaf Ebrahimi 104*b7893ccfSSadaf Ebrahimi return format.str(); 105*b7893ccfSSadaf Ebrahimi } 106*b7893ccfSSadaf Ebrahimi 107*b7893ccfSSadaf Ebrahimi /// Check that the number of %i format specifiers in the source string matches the number of elements in the index vector. IsValid()108*b7893ccfSSadaf Ebrahimi bool IsValid() { 109*b7893ccfSSadaf Ebrahimi // Count the number of occurances of the format specifier 110*b7893ccfSSadaf Ebrahimi uint32_t count = 0; 111*b7893ccfSSadaf Ebrahimi 112*b7893ccfSSadaf Ebrahimi std::string source(source_); 113*b7893ccfSSadaf Ebrahimi 114*b7893ccfSSadaf Ebrahimi std::string::size_type pos = source.find(IndexFormatSpecifier); 115*b7893ccfSSadaf Ebrahimi 116*b7893ccfSSadaf Ebrahimi while (pos != std::string::npos) { 117*b7893ccfSSadaf Ebrahimi ++count; 118*b7893ccfSSadaf Ebrahimi pos = source.find(IndexFormatSpecifier, pos + 1); 119*b7893ccfSSadaf Ebrahimi } 120*b7893ccfSSadaf Ebrahimi 121*b7893ccfSSadaf Ebrahimi return (count == num_indices_); 122*b7893ccfSSadaf Ebrahimi } 123*b7893ccfSSadaf Ebrahimi 124*b7893ccfSSadaf Ebrahimi private: 125*b7893ccfSSadaf Ebrahimi const char *source_; ///< Format string. 126*b7893ccfSSadaf Ebrahimi const size_t *args_; ///< Array index values for formatting. 127*b7893ccfSSadaf Ebrahimi size_t num_indices_; ///< Number of array index values. 128*b7893ccfSSadaf Ebrahimi }; 129*b7893ccfSSadaf Ebrahimi 130*b7893ccfSSadaf Ebrahimi #endif // PARAMETER_NAME_H 131