| /* Copyright (c) 2016 The Khronos Group Inc. |
| * Copyright (c) 2016 Valve Corporation |
| * Copyright (c) 2016 LunarG, Inc. |
| * Copyright (c) 2016 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #ifndef PARAMETER_NAME_H |
| #define PARAMETER_NAME_H |
| |
| #include <cassert> |
| #include <sstream> |
| #include <string> |
| #include <vector> |
| |
| /** |
| * Parameter name string supporting deferred formatting for array subscripts. |
| * |
| * Custom parameter name class with support for deferred formatting of names containing array subscripts. The class stores |
| * a format string and a vector of index values, and performs string formatting when an accessor function is called to |
| * retrieve the name string. This class was primarily designed to be used with validation functions that receive a parameter name |
| * string and value as arguments, and print an error message that includes the parameter name when the value fails a validation |
| * test. Using standard strings with these validation functions requires that parameter names containing array subscripts be |
| * formatted before each validation function is called, performing the string formatting even when the value passes validation |
| * and the string is not used: |
| * sprintf(name, "pCreateInfo[%d].sType", i); |
| * validate_stype(name, pCreateInfo[i].sType); |
| * |
| * With the ParameterName class, a format string and a vector of format values are stored by the ParameterName object that is |
| * provided to the validation function. String formatting is then performed only when the validation function retrieves the |
| * name string from the ParameterName object: |
| * validate_stype(ParameterName("pCreateInfo[%i].sType", IndexVector{ i }), pCreateInfo[i].sType); |
| */ |
| class ParameterName { |
| public: |
| /// Container for index values to be used with parameter name string formatting. |
| typedef std::vector<size_t> IndexVector; |
| |
| /// Format specifier for the parameter name string, to be replaced by an index value. The parameter name string must contain |
| /// one format specifier for each index value specified. |
| const std::string IndexFormatSpecifier = "%i"; |
| |
| public: |
| /** |
| * Construct a ParameterName object from a string literal, without formatting. |
| * |
| * @param source Paramater name string without format specifiers. |
| * |
| * @pre The source string must not contain the %i format specifier. |
| */ |
| ParameterName(const char *source) : source_(source) { assert(IsValid()); } |
| |
| /** |
| * Construct a ParameterName object from a std::string object, without formatting. |
| * |
| * @param source Paramater name string without format specifiers. |
| * |
| * @pre The source string must not contain the %i format specifier. |
| */ |
| ParameterName(const std::string &source) : source_(source) { assert(IsValid()); } |
| |
| /** |
| * Construct a ParameterName object from a std::string object, without formatting. |
| * |
| * @param source Paramater name string without format specifiers. |
| * |
| * @pre The source string must not contain the %i format specifier. |
| */ |
| ParameterName(const std::string &&source) : source_(std::move(source)) { assert(IsValid()); } |
| |
| /** |
| * Construct a ParameterName object from a std::string object, with formatting. |
| * |
| * @param source Paramater name string with format specifiers. |
| * @param args Array index values to be used for formatting. |
| * |
| * @pre The number of %i format specifiers contained by the source string must match the number of elements contained |
| * by the index vector. |
| */ |
| ParameterName(const std::string &source, const IndexVector &args) : source_(source), args_(args) { assert(IsValid()); } |
| |
| /** |
| * Construct a ParameterName object from a std::string object, with formatting. |
| * |
| * @param source Paramater name string with format specifiers. |
| * @param args Array index values to be used for formatting. |
| * |
| * @pre The number of %i format specifiers contained by the source string must match the number of elements contained |
| * by the index vector. |
| */ |
| ParameterName(const std::string &&source, const IndexVector &&args) : source_(std::move(source)), args_(std::move(args)) { |
| assert(IsValid()); |
| } |
| |
| /// Retrive the formatted name string. |
| std::string get_name() const { return (args_.empty()) ? source_ : Format(); } |
| |
| private: |
| /// Replace the %i format specifiers in the source string with the values from the index vector. |
| std::string Format() const { |
| std::string::size_type current = 0; |
| std::string::size_type last = 0; |
| std::stringstream format; |
| |
| for (size_t index : args_) { |
| current = source_.find(IndexFormatSpecifier, last); |
| if (current == std::string::npos) { |
| break; |
| } |
| format << source_.substr(last, (current - last)) << index; |
| last = current + IndexFormatSpecifier.length(); |
| } |
| |
| format << source_.substr(last, std::string::npos); |
| |
| return format.str(); |
| } |
| |
| /// Check that the number of %i format specifiers in the source string matches the number of elements in the index vector. |
| bool IsValid() { |
| // Count the number of occurances of the format specifier |
| uint32_t count = 0; |
| std::string::size_type pos = source_.find(IndexFormatSpecifier); |
| |
| while (pos != std::string::npos) { |
| ++count; |
| pos = source_.find(IndexFormatSpecifier, pos + 1); |
| } |
| |
| return (count == args_.size()); |
| } |
| |
| private: |
| std::string source_; ///< Format string. |
| IndexVector args_; ///< Array index values for formatting. |
| }; |
| |
| #endif // PARAMETER_NAME_H |