blob: 05a1d89e0be4182e30509a54689b1c8b62edd901 [file] [log] [blame]
Dustin Graves9243cd52016-07-22 13:19:02 -06001/* Copyright (c) 2016 The Khronos Group Inc.
2 * Copyright (c) 2016 Valve Corporation
3 * Copyright (c) 2016 LunarG, Inc.
4 * Copyright (c) 2016 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 vector 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 vector of format values are stored by the ParameterName object that is
40 * 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 */
44class ParameterName {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -070045 public:
Dustin Graves9243cd52016-07-22 13:19:02 -060046 /// Container for index values to be used with parameter name string formatting.
47 typedef std::vector<size_t> IndexVector;
48
49 /// Format specifier for the parameter name string, to be replaced by an index value. The parameter name string must contain
50 /// one format specifier for each index value specified.
51 const std::string IndexFormatSpecifier = "%i";
52
Mark Lobodzinski64318ba2017-01-26 13:34:13 -070053 public:
Dustin Graves9243cd52016-07-22 13:19:02 -060054 /**
55 * Construct a ParameterName object from a string literal, without formatting.
56 *
57 * @param source Paramater name string without format specifiers.
58 *
59 * @pre The source string must not contain the %i format specifier.
60 */
61 ParameterName(const char *source) : source_(source) { assert(IsValid()); }
62
63 /**
Dave Houltona9df0ce2018-02-07 10:51:23 -070064 * Construct a ParameterName object from a std::string object, without formatting.
65 *
66 * @param source Paramater name string without format specifiers.
67 *
68 * @pre The source string must not contain the %i format specifier.
69 */
Dustin Graves9243cd52016-07-22 13:19:02 -060070 ParameterName(const std::string &source) : source_(source) { assert(IsValid()); }
71
72 /**
Dave Houltona9df0ce2018-02-07 10:51:23 -070073 * Construct a ParameterName object from a std::string object, without formatting.
74 *
75 * @param source Paramater name string without format specifiers.
76 *
77 * @pre The source string must not contain the %i format specifier.
78 */
Dustin Graves9243cd52016-07-22 13:19:02 -060079 ParameterName(const std::string &&source) : source_(std::move(source)) { assert(IsValid()); }
80
81 /**
Dave Houltona9df0ce2018-02-07 10:51:23 -070082 * Construct a ParameterName object from a std::string object, with formatting.
83 *
84 * @param source Paramater name string with format specifiers.
85 * @param args Array index values to be used for formatting.
86 *
87 * @pre The number of %i format specifiers contained by the source string must match the number of elements contained
88 * by the index vector.
89 */
Dustin Graves9243cd52016-07-22 13:19:02 -060090 ParameterName(const std::string &source, const IndexVector &args) : source_(source), args_(args) { assert(IsValid()); }
91
92 /**
Dave Houltona9df0ce2018-02-07 10:51:23 -070093 * Construct a ParameterName object from a std::string object, with formatting.
94 *
95 * @param source Paramater name string with format specifiers.
96 * @param args Array index values to be used for formatting.
97 *
98 * @pre The number of %i format specifiers contained by the source string must match the number of elements contained
99 * by the index vector.
100 */
Dustin Graves9243cd52016-07-22 13:19:02 -0600101 ParameterName(const std::string &&source, const IndexVector &&args) : source_(std::move(source)), args_(std::move(args)) {
102 assert(IsValid());
103 }
104
105 /// Retrive the formatted name string.
106 std::string get_name() const { return (args_.empty()) ? source_ : Format(); }
107
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700108 private:
Dustin Graves9243cd52016-07-22 13:19:02 -0600109 /// Replace the %i format specifiers in the source string with the values from the index vector.
110 std::string Format() const {
111 std::string::size_type current = 0;
112 std::string::size_type last = 0;
113 std::stringstream format;
114
115 for (size_t index : args_) {
116 current = source_.find(IndexFormatSpecifier, last);
117 if (current == std::string::npos) {
118 break;
119 }
120 format << source_.substr(last, (current - last)) << index;
121 last = current + IndexFormatSpecifier.length();
122 }
123
124 format << source_.substr(last, std::string::npos);
125
126 return format.str();
127 }
128
129 /// Check that the number of %i format specifiers in the source string matches the number of elements in the index vector.
130 bool IsValid() {
131 // Count the number of occurances of the format specifier
132 uint32_t count = 0;
133 std::string::size_type pos = source_.find(IndexFormatSpecifier);
134
135 while (pos != std::string::npos) {
136 ++count;
137 pos = source_.find(IndexFormatSpecifier, pos + 1);
138 }
139
140 return (count == args_.size());
141 }
142
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700143 private:
144 std::string source_; ///< Format string.
145 IndexVector args_; ///< Array index values for formatting.
Dustin Graves9243cd52016-07-22 13:19:02 -0600146};
147
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700148#endif // PARAMETER_NAME_H