/* 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
