123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- /******************************************************************************
- *
- * package: Log4Qt
- * file: properties.cpp
- * created: September 2007
- * author: Martin Heinrich
- *
- *
- * Copyright 2007 Martin Heinrich
- *
- * 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.
- *
- ******************************************************************************/
- /******************************************************************************
- * Dependencies
- ******************************************************************************/
- #include "log4qt/helpers/properties.h"
- #include <QtCore/QDebug>
- #include <QtCore/QIODevice>
- #include <QtCore/QSettings>
- #include <QtCore/QTextStream>
- #include "log4qt/logger.h"
- namespace Log4Qt
- {
-
-
-
- /**************************************************************************
- *Declarations
- **************************************************************************/
-
-
-
- /**************************************************************************
- * C helper functions
- **************************************************************************/
-
-
- LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Properties)
-
-
-
- /**************************************************************************
- * Class implementation: Properties
- **************************************************************************/
-
-
- void Properties::load(QIODevice *pDevice)
- {
- const QLatin1Char append_char(msEscapeChar);
-
- if (!pDevice)
- {
- logger()->warn("No device specified for load.");
- return;
- }
-
- QTextStream stream(pDevice);
- QString line;
- int line_number = 0;
- QString property;
- int property_start_line = 1;
-
- do {
- line = trimLeft(stream.readLine());
- line_number++;
-
- if (!line.isEmpty() && line.at(line.length() - 1) == append_char)
- property += line.left(line.length() - 1);
- else
- {
- property += line;
- parseProperty(property, property_start_line);
- property.clear();
- property_start_line = line_number + 1;
- }
- }
- while (!line.isNull());
- }
-
-
- void Properties::load(const QSettings &rSettings)
- {
- QStringList keys = rSettings.childKeys();
- QString key;
- Q_FOREACH(key, keys)
- insert(key, rSettings.value(key).toString());
- }
-
-
- QString Properties::property(const QString &rKey) const
- {
- // Null string indicates the property does not contain the key.
-
- if (contains(rKey))
- {
- QString value = this->value(rKey);
- if (value.isNull())
- return QString(QLatin1String(""));
- else
- return value;
- }
-
- if (mpDefaultProperties)
- return mpDefaultProperties->property(rKey);
- else
- return QString();
- }
-
- QString Properties::property(const QString &rKey,
- const QString &rDefaultValue) const
- {
- QString value = property(rKey);
- if (value.isNull())
- return rDefaultValue;
- else
- return value;
- }
-
-
- QStringList Properties::propertyNames() const
- {
- QStringList default_keys;
- if (mpDefaultProperties)
- default_keys = mpDefaultProperties->propertyNames();
-
- QStringList keys = this->keys();
- QString key;
- Q_FOREACH(key, default_keys)
- if (!keys.contains(key))
- keys << key;
-
- return keys;
- }
-
- void Properties::parseProperty(const QString &rProperty,
- int line)
- {
- Q_ASSERT_X(rProperty == trimLeft(rProperty), "parseProperty()", "rProperty has leading spaces");
-
- enum State
- {
- KEY_STATE,
- KEYSPACE_STATE,
- SPACEVALUE_STATE,
- VALUE_STATE,
- KEYESCAPE_STATE,
- VALUEESCAPE_STATE,
- UNICODEESCAPE_STATE
- };
- const QString value_escape_codes =QLatin1String(msValueEscapeCodes);
- const QString value_escape_chars = QLatin1String(msValueEscapeChars);
- Q_ASSERT_X(value_escape_codes.length() == value_escape_chars.length(), "parseProperty()", "Value escape sequence character definition does not map");
- const QString key_escape_codes = QLatin1String(msKeyEscapeCodes);
- const QString key_escape_chars = QLatin1String(msKeyEscapeChars);
- Q_ASSERT_X(key_escape_codes.length() == key_escape_chars.length(), "parseProperty()", "Key escape sequence character definition does not map");
-
- if (rProperty.isEmpty())
- return;
-
- int i = 0;
- QChar c;
- char ch;
- State state = KEY_STATE;
- QString key;
- QString value;
- QString *p_string = &key;
- uint ucs;
- int ucs_digits;
- while (i < rProperty.length())
- {
- // i points to the current character.
- // c contains the current character
- // ch contains the Latin1 equivalent of the current character
- // i is incremented at the end of the loop to consume the character.
- // continue is used to change state without consuming the character
-
- c = rProperty.at(i);
- ch = c.toLatin1();
-
- switch (state)
- {
- case KEY_STATE:
- if (ch == '!' || ch == '#' )
- return;
- else if (c.isSpace())
- {
- p_string = &value;
- state = KEYSPACE_STATE;
- }
- else if (ch == '=' || ch == ':')
- {
- p_string = &value;
- state = SPACEVALUE_STATE;
- }
- else if (ch == msEscapeChar)
- state = KEYESCAPE_STATE;
- else
- *p_string += c;
- break;
- case KEYSPACE_STATE:
- if (ch == '=' || ch == ':')
- state = SPACEVALUE_STATE;
- else if (!c.isSpace())
- {
- *p_string += c;
- state = VALUE_STATE;
- }
- break;
- case SPACEVALUE_STATE:
- if (!c.isSpace())
- {
- *p_string += c;
- state = VALUE_STATE;
- }
- break;
- case VALUE_STATE:
- if (ch == msEscapeChar)
- state = VALUEESCAPE_STATE;
- else
- *p_string += c;
- break;
- case KEYESCAPE_STATE:
- {
- int convert = key_escape_codes.indexOf(c);
- if (convert >= 0)
- *p_string += key_escape_chars.at(convert);
- else
- {
- logger()->warn("Unknown escape sequence '\\%1' in key of property starting at line %2",
- QString(c),
- line);
- *p_string += c;
- }
- state = KEY_STATE;
- break;
- }
- case VALUEESCAPE_STATE:
- {
- int convert = value_escape_codes.indexOf(c);
- if (convert >= 0)
- {
- *p_string += value_escape_chars.at(convert);
- state = VALUE_STATE;
- }
- else if (ch == 'u')
- {
- ucs = 0;
- ucs_digits = 0;
- state = UNICODEESCAPE_STATE;
- }
- else
- {
- logger()->warn("Unknown escape sequence '\\%1' in value of property starting at line %2", QString(c), line);
- *p_string += c;
- state = VALUE_STATE;
- }
- break;
- }
- case UNICODEESCAPE_STATE:
- {
- int hex = hexDigitValue(c);
- if (hex >= 0)
- {
- ucs = ucs * 16 + hex;
- ucs_digits++;
- if (ucs_digits == 4 || i == rProperty.length() - 1)
- {
- *p_string += QChar(ucs);
- state = VALUE_STATE;
- }
- }
- else
- {
- if (ucs_digits > 0)
- *p_string += QChar(ucs);
- state = VALUE_STATE;
- continue;
- }
- break;
- }
- default:
- Q_ASSERT_X(false, "Properties::parseProperty()", "Unknown state constant");
- return;
- }
- i++;
- }
-
- if (key.isEmpty() && !value.isEmpty())
- logger()->warn("Found value with no key in property starting at line %1", line);
-
- logger()->trace("Loaded property '%1' : '%2'", key, value);
- insert(key, value);
- }
-
-
- int Properties::hexDigitValue(const QChar &rDigit)
- {
- bool ok;
- int result = QString(rDigit).toInt(&ok, 16);
- if (!ok)
- return -1;
- else
- return result;
- }
-
-
- QString Properties::trimLeft(const QString &rLine)
- {
- int i = 0;
- while (i < rLine.length() && rLine.at(i).isSpace())
- i++;
- return rLine.right(rLine.length() - i);
- }
-
-
- const char Properties::msEscapeChar ='\\';
- const char *Properties::msValueEscapeCodes = "tnr\\\"\' ";
- const char *Properties::msValueEscapeChars = "\t\n\r\\\"\' ";
- const char *Properties::msKeyEscapeCodes = " :=";
- const char *Properties::msKeyEscapeChars = " :=";
- /**************************************************************************
- * Implementation: Operators, Helper
- **************************************************************************/
- #ifndef QT_NO_DEBUG_STREAM
- QDebug operator<<(QDebug debug, const Properties &rProperties)
- {
- debug.nospace() << "Properties("
- << "default:" << rProperties.defaultProperties() << " "
- << "properties:" << *reinterpret_cast<const QHash <QString, QString > *>(&rProperties)
- << ")";
- return debug.space();
- }
- #endif
-
-
-
- } // namespace Log4Qt
|