summaryrefslogtreecommitdiff
path: root/ext/Log4Qt/src/helpers/properties.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ext/Log4Qt/src/helpers/properties.cpp')
-rwxr-xr-xext/Log4Qt/src/helpers/properties.cpp364
1 files changed, 364 insertions, 0 deletions
diff --git a/ext/Log4Qt/src/helpers/properties.cpp b/ext/Log4Qt/src/helpers/properties.cpp
new file mode 100755
index 0000000..5bfecd0
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/properties.cpp
@@ -0,0 +1,364 @@
+/******************************************************************************
+ *
+ * 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 "helpers/properties.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QIODevice>
+#include <QtCore/QSettings>
+#include <QtCore/QTextStream>
+#include "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 = 0;
+ int ucs_digits = 0;
+ 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