/*
 * Cppcheck - A tool for static C/C++ code analysis
 * Copyright (C) 2007-2009 Daniel Marjamäki and Cppcheck team.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

// THIS FILE IS GENERATED BY MACHINE, SEE ../tools/errmsg.cpp !

#ifndef errorloggerH
#define errorloggerH
#include <list>
#include <string>
#include "settings.h"
class Token;
class Tokenizer;

/// @addtogroup Core
/// @{

/**
 * This is an interface, which the class responsible of error logging
 * should implement.
 */
class ErrorLogger
{
public:

    /**
     * Wrapper for error messages, provided by reportErr()
     */
    class ErrorMessage
    {
    public:
        /**
         * File name and line number.
         */
        class FileLocation
        {
        public:
            FileLocation()
            {
                line = 0;
            }

            std::string getfile() const;
            std::string file;
            unsigned int line;
        };

        ErrorMessage(const std::list<FileLocation> &callStack, const std::string &severity, const std::string &msg, const std::string &id);
        ErrorMessage();
        std::string toXML() const;

        static std::string getXMLHeader();
        static std::string getXMLFooter();

        /**
         * Format the error message into a string.
         * @param outputFormat Empty string to use default output format
         * or template to be used. E.g. "{file}:{line},{severity},{id},{message}"
         */
        std::string toText(const std::string &outputFormat = "") const;

        /**
         * Replace all occurances of searchFor with replaceWith in the
         * given source.
         * @param source The string to modify
         * @param searchFor What should be searched for
         * @param replaceWith What will replace the found item
         */
        static void findAndReplace(std::string &source, const std::string &searchFor, const std::string &replaceWith);
        std::string serialize() const;
        bool deserialize(const std::string &data);
        std::list<FileLocation> _callStack;
        std::string _severity;
        std::string _msg;
        std::string _id;
    };

    ErrorLogger() { }
    virtual ~ErrorLogger() { }

    /**
     * Information about progress is directed here.
     * Override this to receive the progress messages.
     *
     * @param outmsg Message to show e.g. "Checking main.cpp..."
     */
    virtual void reportOut(const std::string &outmsg) = 0;

    /**
     * Information about found errors and warnings is directed
     * here. Override this to receive the errormessages.
     *
     * @param msg Location and other information about the found.
     * error
     */
    virtual void reportErr(const ErrorLogger::ErrorMessage &msg) = 0;

    /**
     * Information about how many files have been checked
     *
     * @param index This many files have been checked.
     * @param max This many files there are in total.
     */
    virtual void reportStatus(unsigned int index, unsigned int max) = 0;


    static bool arrayIndexOutOfBounds(const Settings &s)
    {
        return s._showAll;
    }

    static bool bufferOverrun(const Settings &s)
    {
        return s._showAll;
    }


    static bool strncatUsage(const Settings &s)
    {
        return s._showAll;
    }

    static bool outOfBounds()
    {
        return true;
    }

    static bool stlOutOfBounds()
    {
        return true;
    }

    static bool noConstructor(const Settings &s)
    {
        return s._checkCodingStyle;
    }

    static bool uninitVar(const Settings &s)
    {
        return s._checkCodingStyle;
    }

    static bool unusedPrivateFunction(const Settings &s)
    {
        return s._checkCodingStyle;
    }

    static bool memsetClass()
    {
        return true;
    }

    static bool memsetStruct()
    {
        return true;
    }

    static bool operatorEq(const Settings &s)
    {
        return s._checkCodingStyle;
    }

    static bool virtualDestructor()
    {
        return true;
    }

    void unusedFunction(const std::string &filename, const std::string &funcname)
    {
        std::list<ErrorLogger::ErrorMessage::FileLocation> loc;
        ErrorLogger::ErrorMessage::FileLocation fileLoc;
        fileLoc.file = filename;
        fileLoc.line = 1;
        loc.push_back(fileLoc);
        reportErr(ErrorLogger::ErrorMessage(loc, "style", "The function '" + funcname + "' is never used", "unusedFunction"));
    }

    static bool unusedFunction(const Settings &s)
    {
        return s._checkCodingStyle || s._showAll;
    }


    static bool mismatchAllocDealloc()
    {
        return true;
    }

    static bool memleak()
    {
        return true;
    }

    static bool memleakall(const Settings &s)
    {
        return s._showAll;
    }


    static bool resourceLeak()
    {
        return true;
    }

    static bool deallocDealloc()
    {
        return true;
    }

    static bool deallocuse()
    {
        return true;
    }

    static bool mismatchSize()
    {
        return true;
    }

    static bool cstyleCast(const Settings &s)
    {
        return s._checkCodingStyle;
    }


    static bool redundantIfDelete0(const Settings &s)
    {
        return s._checkCodingStyle;
    }


    static bool redundantIfRemove(const Settings &s)
    {
        return s._checkCodingStyle;
    }

    static bool dangerousUsageStrtol()
    {
        return true;
    }

    static bool ifNoAction(const Settings &s)
    {
        return s._checkCodingStyle;
    }

    static bool sprintfOverlappingData()
    {
        return true;
    }


    static bool udivError()
    {
        return true;
    }


    static bool udivWarning(const Settings &s)
    {
        return s._checkCodingStyle || s._showAll;
    }


    static bool unusedStructMember(const Settings &s)
    {
        return s._checkCodingStyle;
    }

    static bool passedByValue(const Settings &s)
    {
        return s._checkCodingStyle;
    }

    static bool constStatement(const Settings &s)
    {
        return s._checkCodingStyle;
    }


    static bool charArrayIndex(const Settings &s)
    {
        return s._checkCodingStyle;
    }


    static bool charBitOp(const Settings &s)
    {
        return s._checkCodingStyle;
    }


    static bool variableScope()
    {
        return false;
    }

    static bool conditionAlwaysTrueFalse(const Settings &s)
    {
        return s._checkCodingStyle;
    }


    static bool strPlusChar()
    {
        return true;
    }


    static bool returnLocalVariable()
    {
        return true;
    }


    static bool dangerousFunctionmktemp(const Settings &s)
    {
        return s._checkCodingStyle;
    }


    static bool dangerousFunctiongets(const Settings &s)
    {
        return s._checkCodingStyle;
    }


    static bool dangerousFunctionscanf(const Settings &s)
    {
        return s._checkCodingStyle;
    }


    static std::string callStackToString(const std::list<ErrorLogger::ErrorMessage::FileLocation> &callStack);

private:
    void _writemsg(const Tokenizer *tokenizer, const Token *tok, const char severity[], const std::string &msg, const std::string &id);
    void _writemsg(const Tokenizer *tokenizer, const std::list<const Token *> &callstack, const char severity[], const std::string &msg, const std::string &id);
};

/** enum class for severity */
class Severity
{
public:
    enum e { error, style, possibleError, possibleStyle };
    static std::string stringify(e severity)
    {
        switch (severity)
        {
        case error:
            return "error";
        case style:
            return "style";
        case possibleError:
            return "possible error";
        case possibleStyle:
            return "possible style";
        };
        return "???";
    }
};


/// @}

#endif
