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