/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 _LOG4CXX_HELPER_PROPERTIES_H
#define _LOG4CXX_HELPER_PROPERTIES_H

#if defined(_MSC_VER)
    #pragma warning (push)
    #pragma warning ( disable: 4231 4251 4275 4786 )
#endif


#include <log4cxx/logstring.h>
#include <log4cxx/helpers/objectptr.h>
#include <log4cxx/helpers/objectimpl.h>
#include <log4cxx/helpers/inputstream.h>
#include <map>
#include <vector>
#include <istream>

namespace log4cxx
{
namespace helpers
{
class LOG4CXX_EXPORT Properties
{
    private:
        typedef std::map<LogString, LogString> PropertyMap;
        PropertyMap* properties;
        Properties(const Properties&);
        Properties& operator=(const Properties&);

    public:
        /**
         *  Create new instance.
         */
        Properties();
        /**
         * Destructor.
         */
        ~Properties();
        /**
        Reads a property list (key and element pairs) from the input stream.
        The stream is assumed to be using the ISO 8859-1 character encoding.

        <p>Every property occupies one line of the input stream.
        Each line is terminated by a line terminator (<code>\\n</code> or
        <code>\\r</code> or <code>\\r\\n</code>).
        Lines from the input stream are processed until end of file is reached
        on the input stream.

        <p>A line that contains only whitespace or whose first non-whitespace
        character is an ASCII <code>#</code> or <code>!</code> is ignored
        (thus, <code>#</code> or <code>!</code> indicate comment lines).

        <p>Every line other than a blank line or a comment line describes one
        property to be added to the table (except that if a line ends with \,
        then the following line, if it exists, is treated as a continuation
        line, as described below). The key consists of all the characters in
        the line starting with the first non-whitespace character and up to,
        but   not including, the first ASCII <code>=</code>, <code>:</code>,
        or whitespace character. All of the
        key termination characters may be included in the key by preceding them
        with a <code>\\</code>. Any whitespace after the key is skipped;
        if the first
        non-whitespace character after the key is <code>=</code> or
        <code>:</code>, then it is ignored
        and any whitespace characters after it are also skipped. All remaining
        characters on the line become part of the associated element string.
        Within the element string, the ASCII escape sequences <code>\\t</code>,
        <code>\\n</code>, <code>\\r</code>, <code>\\</code>, <code>\\"</code>,
        <code>\\'</code>, <code>\\</code> (a backslash and a space), and
        <code>\\uxxxx</code> are recognized
        and converted to single characters. Moreover, if the last character on
        the line is <code>\\</code>, then the next line is treated as a
        continuation of the
        current line; the <code>\\</code> and line terminator are simply
        discarded, and any
        leading whitespace characters on the continuation line are also
        discarded and are not part of the element string.

        <p>As an example, each of the following four lines specifies the key
        "Truth" and the associated element value "Beauty":

        <pre>
        Truth = Beauty
        Truth:Beauty
        Truth         :Beauty
        </pre>

        As another example, the following three lines specify a single
        property:
        <pre>
        fruits           apple, banana, pear, \
                  cantaloupe, watermelon, \
                  kiwi, mango
        </pre>
        The key is "<code>fruits</code>" and the associated element is:
        <pre>
        "apple, banana, pear, cantaloupe, watermelon, kiwi, mango"
        </pre>
        Note that a space appears before each \ so that a space will appear
        after each comma in the final result; the \, line terminator, and
        leading whitespace on the continuation line are merely discarded and are
        not replaced by one or more other characters.

        <p>As a third example, the line:
        <pre>
        cheeses
        </pre>
        specifies that the key is "<code>cheeses</code>" and the associated
        element is the empty string.

        @param inStream the input stream.

        @throw IOException if an error occurred when reading from the input
        stream.
        */
        void load(InputStreamPtr inStream);

        /**
         *  Calls Properties::put.
         *   @param key the key to be placed into this property list.
         *   @param value the value corresponding to key.
         *   @return the previous value of the specified key in this
         *   property list, or an empty string if it did not have one.
        */
        LogString setProperty(const LogString& key, const LogString& value);
        /**
         *  Puts a property value into the collection.
         *   @param key the key to be placed into this property list.
         *   @param value the value corresponding to key.
         *   @return the previous value of the specified key in this
         *   property list, or an empty string if it did not have one.
        */
        LogString put(const LogString& key, const LogString& value);


        /**
         * Calls Properties::get.
         * @param key the property key.
         * @return the value in this property list with the specified
         *   key value or empty string.
        */
        LogString getProperty(const LogString& key) const;
        /**
         * Gets a property value.
         * @param key the property key.
         * @return the value in this property list with the specified
         *   key value or empty string.
        */
        LogString get(const LogString& key) const;

        /**
        Returns an enumeration of all the keys in this property list,
        including distinct keys in the default property list if a key
        of the same name has not already been found from the main
        properties list.
        @return an array of all the keys in this
        property list, including the keys in the default property list.
        */
        std::vector<LogString> propertyNames() const;
}; // class Properties
}  // namespace helpers
} // namespace log4cxx

#if defined(_MSC_VER)
    #pragma warning (pop)
#endif


#endif //_LOG4CXX_HELPER_PROPERTIES_H
