<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include <set>
#include <memory>
#include <vector>

#include "caf/fwd.hpp"

namespace caf {
namespace io {

class hook;

// safes us some typing for the static dispatching
#define CAF_IO_HOOK_DISPATCH(eventname)                                        \
  template <typename... Ts>                                                    \
  void dispatch(event<eventname>, Ts&&... ts) {                                \
    eventname##_cb(std::forward<Ts>(ts)...);                                   \
  }

/// @relates hook
using hook_uptr = std::unique_ptr<hook>;

/// Interface to define hooks into the IO layer.
class hook {
public:
  explicit hook(actor_system& sys);

  virtual ~hook();

  /// Called whenever a message has arrived via the network.
  virtual void message_received_cb(const node_id& source,
                                   const strong_actor_ptr& from,
                                   const strong_actor_ptr& dest,
                                   message_id mid,
                                   const message& msg);

  /// Called whenever a message has been sent to the network.
  /// @param from The address of the sending actor.
  /// @param hop The node in the network we've sent the message to.
  /// @param dest The address of the receiving actor. Note that the node ID
  ///             of `dest` can differ from `hop` in case we don't
  ///             have a direct connection to `dest_node`.
  /// @param mid The ID of the message.
  /// @param payload The message we've sent.
  virtual void message_sent_cb(const strong_actor_ptr& from, const node_id& hop,
                               const strong_actor_ptr& dest, message_id mid,
                               const message& payload);

  /// Called whenever no route for sending a message exists.
  virtual void message_sending_failed_cb(const strong_actor_ptr& from,
                                         const strong_actor_ptr& dest,
                                         message_id mid,
                                         const message& payload);

  /// Called whenever a message is forwarded to a different node.
  virtual void message_forwarded_cb(const basp::header& hdr,
                                    const std::vector<char>* payload);

  /// Called whenever no route for a forwarding request exists.
  virtual void message_forwarding_failed_cb(const basp::header& hdr,
                                            const std::vector<char>* payload);

  /// Called whenever an actor has been published.
  virtual void actor_published_cb(const strong_actor_ptr& addr,
                                  const std::set<std::string>& ifs,
                                  uint16_t port);

  /// Called whenever a new remote actor appeared.
  virtual void new_remote_actor_cb(const strong_actor_ptr& addr);

  /// Called whenever a handshake via a direct TCP connection succeeded.
  virtual void new_connection_established_cb(const node_id& node);

  /// Called whenever a message from or to a yet unknown node was received.
  /// @param via The node that has sent us the message.
  /// @param node The newly added entry to the routing table.
  virtual void new_route_added_cb(const node_id& via, const node_id& node);

  /// Called whenever a direct connection was lost.
  virtual void connection_lost_cb(const node_id& dest);

  /// Called whenever a route became unavailable.
  /// @param hop The node that was either disconnected
  ///            or lost a connection itself.
  /// @param dest The node that is no longer reachable via `hop`.
  virtual void route_lost_cb(const node_id& hop, const node_id& dest);

  /// Called whenever a message was discarded because a remote node
  /// tried to send a message to an actor ID that could not be found
  /// in the registry.
  virtual void invalid_message_received_cb(const node_id& source,
                                           const strong_actor_ptr& sender,
                                           actor_id invalid_dest,
                                           message_id mid, const message& msg);

  /// Called before middleman shuts down.
  virtual void before_shutdown_cb();

  /// All possible events for IO hooks.
  enum event_type {
    message_received,
    message_sent,
    message_forwarded,
    message_sending_failed,
    message_forwarding_failed,
    actor_published,
    new_remote_actor,
    new_connection_established,
    new_route_added,
    connection_lost,
    route_lost,
    invalid_message_received,
    before_shutdown
  };

  /// Handles an event by invoking the associated callback.
  template <event_type Event, typename... Ts>
  void handle(Ts&&... ts) {
    dispatch(event<Event>{}, std::forward<Ts>(ts)...);
  }

  inline actor_system& system() const {
    return system_;
  }

private:
  // ------------ convenience interface based on static dispatching ------------
  template <event_type Id>
  using event = std::integral_constant<event_type, Id>;

  CAF_IO_HOOK_DISPATCH(message_received)
  CAF_IO_HOOK_DISPATCH(message_sent)
  CAF_IO_HOOK_DISPATCH(message_forwarded)
  CAF_IO_HOOK_DISPATCH(message_sending_failed)
  CAF_IO_HOOK_DISPATCH(message_forwarding_failed)
  CAF_IO_HOOK_DISPATCH(actor_published)
  CAF_IO_HOOK_DISPATCH(new_remote_actor)
  CAF_IO_HOOK_DISPATCH(new_connection_established)
  CAF_IO_HOOK_DISPATCH(new_route_added)
  CAF_IO_HOOK_DISPATCH(connection_lost)
  CAF_IO_HOOK_DISPATCH(route_lost)
  CAF_IO_HOOK_DISPATCH(invalid_message_received)
  CAF_IO_HOOK_DISPATCH(before_shutdown)

  actor_system& system_;
};

} // namespace io
} // namespace caf

<commit_msg>Add missing <string> include to use std::string.<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include <set>
#include <string>
#include <memory>
#include <vector>

#include "caf/fwd.hpp"

namespace caf {
namespace io {

class hook;

// safes us some typing for the static dispatching
#define CAF_IO_HOOK_DISPATCH(eventname)                                        \
  template <typename... Ts>                                                    \
  void dispatch(event<eventname>, Ts&&... ts) {                                \
    eventname##_cb(std::forward<Ts>(ts)...);                                   \
  }

/// @relates hook
using hook_uptr = std::unique_ptr<hook>;

/// Interface to define hooks into the IO layer.
class hook {
public:
  explicit hook(actor_system& sys);

  virtual ~hook();

  /// Called whenever a message has arrived via the network.
  virtual void message_received_cb(const node_id& source,
                                   const strong_actor_ptr& from,
                                   const strong_actor_ptr& dest,
                                   message_id mid,
                                   const message& msg);

  /// Called whenever a message has been sent to the network.
  /// @param from The address of the sending actor.
  /// @param hop The node in the network we've sent the message to.
  /// @param dest The address of the receiving actor. Note that the node ID
  ///             of `dest` can differ from `hop` in case we don't
  ///             have a direct connection to `dest_node`.
  /// @param mid The ID of the message.
  /// @param payload The message we've sent.
  virtual void message_sent_cb(const strong_actor_ptr& from, const node_id& hop,
                               const strong_actor_ptr& dest, message_id mid,
                               const message& payload);

  /// Called whenever no route for sending a message exists.
  virtual void message_sending_failed_cb(const strong_actor_ptr& from,
                                         const strong_actor_ptr& dest,
                                         message_id mid,
                                         const message& payload);

  /// Called whenever a message is forwarded to a different node.
  virtual void message_forwarded_cb(const basp::header& hdr,
                                    const std::vector<char>* payload);

  /// Called whenever no route for a forwarding request exists.
  virtual void message_forwarding_failed_cb(const basp::header& hdr,
                                            const std::vector<char>* payload);

  /// Called whenever an actor has been published.
  virtual void actor_published_cb(const strong_actor_ptr& addr,
                                  const std::set<std::string>& ifs,
                                  uint16_t port);

  /// Called whenever a new remote actor appeared.
  virtual void new_remote_actor_cb(const strong_actor_ptr& addr);

  /// Called whenever a handshake via a direct TCP connection succeeded.
  virtual void new_connection_established_cb(const node_id& node);

  /// Called whenever a message from or to a yet unknown node was received.
  /// @param via The node that has sent us the message.
  /// @param node The newly added entry to the routing table.
  virtual void new_route_added_cb(const node_id& via, const node_id& node);

  /// Called whenever a direct connection was lost.
  virtual void connection_lost_cb(const node_id& dest);

  /// Called whenever a route became unavailable.
  /// @param hop The node that was either disconnected
  ///            or lost a connection itself.
  /// @param dest The node that is no longer reachable via `hop`.
  virtual void route_lost_cb(const node_id& hop, const node_id& dest);

  /// Called whenever a message was discarded because a remote node
  /// tried to send a message to an actor ID that could not be found
  /// in the registry.
  virtual void invalid_message_received_cb(const node_id& source,
                                           const strong_actor_ptr& sender,
                                           actor_id invalid_dest,
                                           message_id mid, const message& msg);

  /// Called before middleman shuts down.
  virtual void before_shutdown_cb();

  /// All possible events for IO hooks.
  enum event_type {
    message_received,
    message_sent,
    message_forwarded,
    message_sending_failed,
    message_forwarding_failed,
    actor_published,
    new_remote_actor,
    new_connection_established,
    new_route_added,
    connection_lost,
    route_lost,
    invalid_message_received,
    before_shutdown
  };

  /// Handles an event by invoking the associated callback.
  template <event_type Event, typename... Ts>
  void handle(Ts&&... ts) {
    dispatch(event<Event>{}, std::forward<Ts>(ts)...);
  }

  inline actor_system& system() const {
    return system_;
  }

private:
  // ------------ convenience interface based on static dispatching ------------
  template <event_type Id>
  using event = std::integral_constant<event_type, Id>;

  CAF_IO_HOOK_DISPATCH(message_received)
  CAF_IO_HOOK_DISPATCH(message_sent)
  CAF_IO_HOOK_DISPATCH(message_forwarded)
  CAF_IO_HOOK_DISPATCH(message_sending_failed)
  CAF_IO_HOOK_DISPATCH(message_forwarding_failed)
  CAF_IO_HOOK_DISPATCH(actor_published)
  CAF_IO_HOOK_DISPATCH(new_remote_actor)
  CAF_IO_HOOK_DISPATCH(new_connection_established)
  CAF_IO_HOOK_DISPATCH(new_route_added)
  CAF_IO_HOOK_DISPATCH(connection_lost)
  CAF_IO_HOOK_DISPATCH(route_lost)
  CAF_IO_HOOK_DISPATCH(invalid_message_received)
  CAF_IO_HOOK_DISPATCH(before_shutdown)

  actor_system& system_;
};

} // namespace io
} // namespace caf
<|endoftext|>


<commit_before>/* This file is part of QJson
 *
 * Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <QtTest/QtTest>

#include "parser.h"

#include <QtCore/QVariant>

class TestParser: public QObject
{
  Q_OBJECT
  private slots:
    void parseNonAsciiString();
    void parseSimpleObject();
    void parseEmptyObject();
    void parseEmptyValue();
    void parseUrl();
    void parseMultipleObject();

    void parseSimpleArray();
    void parseInvalidObject();
    void parseMultipleArray();

    void testTrueFalseNullValues();
    void testEscapeChars();
    void testNumbers();
    void testNumbers_data();
};

Q_DECLARE_METATYPE(QVariant)
Q_DECLARE_METATYPE(QVariant::Type)

using namespace QJson;

void TestParser::parseSimpleObject() {
  QByteArray json = "{\"foo\":\"bar\"}";
  QVariantMap map;
  map.insert (QLatin1String("foo"), QLatin1String("bar"));
  QVariant expected(map);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

void TestParser::parseEmptyObject() {
  QByteArray json = "{}";
  QVariantMap map;
  QVariant expected (map);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

void TestParser::parseEmptyValue() {
  QByteArray json = "{\"value\": \"\"}";

  QVariantMap map;
  map.insert (QLatin1String("value"), QString(QLatin1String("")));
  QVariant expected (map);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
  QVERIFY (result.toMap().value(QLatin1String("value")).type() == QVariant::String);

  QString value = result.toMap().value(QLatin1String("value")).toString();
  QVERIFY (value.isEmpty());
}

void TestParser::parseInvalidObject() {
  QByteArray json = "{\"foo\":\"bar\"";

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (!ok);
}

void TestParser::parseNonAsciiString() {
  QByteArray json = "{\"artist\":\"Queensr\\u00ffche\"}";
  QVariantMap map;

  QChar unicode_char (0x00ff);
  QString unicode_string;
  unicode_string.setUnicode(&unicode_char, 1);
  unicode_string = QLatin1String("Queensr") + unicode_string + QLatin1String("che");

  map.insert (QLatin1String("artist"), unicode_string);
  QVariant expected (map);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

void TestParser::parseMultipleObject() {
  //put also some extra spaces inside the json string
  QByteArray json = "{ \"foo\":\"bar\",\n\"number\" : 51.3 , \"array\":[\"item1\", 123]}";
  QVariantMap map;
  map.insert (QLatin1String("foo"), QLatin1String("bar"));
  map.insert (QLatin1String("number"), 51.3);
  QVariantList list;
  list.append (QLatin1String("item1"));
  list.append (QLatin1String("123"));
  map.insert (QLatin1String("array"), list);
  QVariant expected (map);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
  QVERIFY (result.toMap().value(QLatin1String("number")).canConvert<float>());
  QVERIFY (result.toMap().value(QLatin1String("array")).canConvert<QVariantList>());
}

void TestParser::parseUrl(){
  //"http:\/\/www.last.fm\/venue\/8926427"
  QByteArray json = "[\"http:\\/\\/www.last.fm\\/venue\\/8926427\"]";
  QVariantList list;
  list.append (QVariant(QLatin1String("http://www.last.fm/venue/8926427")));
  QVariant expected (list);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

 void TestParser::parseSimpleArray() {
  QByteArray json = "[\"foo\",\"bar\"]";
  QVariantList list;
  list.append (QLatin1String("foo"));
  list.append (QLatin1String("bar"));
  QVariant expected (list);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

void TestParser::parseMultipleArray() {
  //put also some extra spaces inside the json string
  QByteArray json = "[ {\"foo\":\"bar\"},\n\"number\",51.3 , [\"item1\", 123]]";
  QVariantMap map;
  map.insert (QLatin1String("foo"), QLatin1String("bar"));

  QVariantList array;
  array.append (QLatin1String("item1"));
  array.append (123);

  QVariantList list;
  list.append (map);
  list.append (QLatin1String("number"));
  list.append (QLatin1String("51.3"));
  list.append ((QVariant) array);

  QVariant expected (list);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

void TestParser::testTrueFalseNullValues() {
  QByteArray json = "[true,false, null, {\"foo\" : true}]";
  QVariantList list;
  list.append (QVariant(true));
  list.append (QVariant(false));
  list.append (QVariant());
  QVariantMap map;
  map.insert (QLatin1String("foo"), true);
  list.append (map);
  QVariant expected (list);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
  QCOMPARE (result.toList().at(0).toBool(), true);
  QCOMPARE (result.toList().at(1).toBool(), false);
  QVERIFY (result.toList().at(2).isNull());
}

void TestParser::testEscapeChars() {
  QByteArray json = "[\"\\b \\f \\n \\r \\t \", \" \\\\ \\/ \\\\\", \"http:\\/\\/foo.com\"]";

  QVariantList list;
  list.append (QLatin1String("\b \f \n \r \t "));
  list.append (QLatin1String(" \\ / \\"));
  list.append (QLatin1String("http://foo.com"));

  QVariant expected (list);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result.toList().size(), expected.toList().size() );
  QCOMPARE(result, expected);
}

void TestParser::testNumbers() {
  QFETCH(QByteArray, input);
  QFETCH(QVariant, expected);
  QFETCH(QVariant::Type, type);

  Parser parser;
  bool ok;
  QVariant result = parser.parse ("[" + input +"]", &ok);
  QVERIFY (ok);

  QVariant value = result.toList().at(0);
  QCOMPARE(value, expected);
  QCOMPARE( value.type(), type);
}

void TestParser::testNumbers_data() {
  QTest::addColumn<QByteArray>( "input" );
  QTest::addColumn<QVariant>( "expected" );
  QTest::addColumn<QVariant::Type>( "type" );

  QByteArray input;
  QVariant output;

  // simple ulonglong
  input = QByteArray("1");
  output = QVariant(QVariant::ULongLong);
  output.setValue(1);

  QTest::newRow("simple ulonglong") << input << output << QVariant::ULongLong;

  // big number
  input = QByteArray("128708157440");
  output = QVariant(QVariant::ULongLong);
  output.setValue(128708157440ull);

  QTest::newRow("big number") << input << output << QVariant::ULongLong;

  // simple double
  input = QByteArray("2.4");
  output = QVariant(QVariant::Double);
  output.setValue(2.4);

  QTest::newRow("simple double") << input << output << QVariant::Double;

  // negative int
  input = QByteArray("-100");
  output = QVariant(QVariant::LongLong);
  output.setValue(-100);

  QTest::newRow("negative int") << input << output << QVariant::LongLong;

  // negative double
  input = QByteArray("-3.4");
  output = QVariant(QVariant::Double);
  output.setValue(-3.4);

  QTest::newRow("negative double") << input << output << QVariant::Double;

  // exp1
  input = QByteArray("-5e+");
  output = QVariant(QVariant::ByteArray);
  output.setValue(input);

  QTest::newRow("exp1") << input << output << QVariant::ByteArray;

  // exp2
  input = QByteArray("2e");
  output = QVariant(QVariant::ByteArray);
  output.setValue(input);

  QTest::newRow("exp2") << input << output << QVariant::ByteArray;

  // exp3
  input = QByteArray("3e+");
  output = QVariant(QVariant::ByteArray);
  output.setValue(input);

  QTest::newRow("exp3") << input << output << QVariant::ByteArray;

  // exp4
  input = QByteArray("4.3E");
  output = QVariant(QVariant::ByteArray);
  output.setValue(input);

  QTest::newRow("exp4") << input << output << QVariant::ByteArray;

  // exp5
  input = QByteArray("5.4E-");
  output = QVariant(QVariant::ByteArray);
  output.setValue(input);

  QTest::newRow("exp5") << input << output << QVariant::ByteArray;
}

QTEST_MAIN(TestParser)

#ifdef QMAKE_BUILD
  #include "testparser.moc"
#else
  #include "moc_testparser.cxx"
#endif
<commit_msg>add a unit test for the "allow top level values" feature<commit_after>/* This file is part of QJson
 *
 * Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <QtTest/QtTest>

#include "parser.h"

#include <QtCore/QVariant>

class TestParser: public QObject
{
  Q_OBJECT
  private slots:
    void parseNonAsciiString();
    void parseSimpleObject();
    void parseEmptyObject();
    void parseEmptyValue();
    void parseUrl();
    void parseMultipleObject();

    void parseSimpleArray();
    void parseInvalidObject();
    void parseMultipleArray();

    void testTrueFalseNullValues();
    void testEscapeChars();
    void testNumbers();
    void testNumbers_data();
    void testTopLevelValues();
    void testTopLevelValues_data();
};

Q_DECLARE_METATYPE(QVariant)
Q_DECLARE_METATYPE(QVariant::Type)

using namespace QJson;

void TestParser::parseSimpleObject() {
  QByteArray json = "{\"foo\":\"bar\"}";
  QVariantMap map;
  map.insert (QLatin1String("foo"), QLatin1String("bar"));
  QVariant expected(map);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

void TestParser::parseEmptyObject() {
  QByteArray json = "{}";
  QVariantMap map;
  QVariant expected (map);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

void TestParser::parseEmptyValue() {
  QByteArray json = "{\"value\": \"\"}";

  QVariantMap map;
  map.insert (QLatin1String("value"), QString(QLatin1String("")));
  QVariant expected (map);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
  QVERIFY (result.toMap().value(QLatin1String("value")).type() == QVariant::String);

  QString value = result.toMap().value(QLatin1String("value")).toString();
  QVERIFY (value.isEmpty());
}

void TestParser::parseInvalidObject() {
  QByteArray json = "{\"foo\":\"bar\"";

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (!ok);
}

void TestParser::parseNonAsciiString() {
  QByteArray json = "{\"artist\":\"Queensr\\u00ffche\"}";
  QVariantMap map;

  QChar unicode_char (0x00ff);
  QString unicode_string;
  unicode_string.setUnicode(&unicode_char, 1);
  unicode_string = QLatin1String("Queensr") + unicode_string + QLatin1String("che");

  map.insert (QLatin1String("artist"), unicode_string);
  QVariant expected (map);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

void TestParser::parseMultipleObject() {
  //put also some extra spaces inside the json string
  QByteArray json = "{ \"foo\":\"bar\",\n\"number\" : 51.3 , \"array\":[\"item1\", 123]}";
  QVariantMap map;
  map.insert (QLatin1String("foo"), QLatin1String("bar"));
  map.insert (QLatin1String("number"), 51.3);
  QVariantList list;
  list.append (QLatin1String("item1"));
  list.append (QLatin1String("123"));
  map.insert (QLatin1String("array"), list);
  QVariant expected (map);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
  QVERIFY (result.toMap().value(QLatin1String("number")).canConvert<float>());
  QVERIFY (result.toMap().value(QLatin1String("array")).canConvert<QVariantList>());
}

void TestParser::parseUrl(){
  //"http:\/\/www.last.fm\/venue\/8926427"
  QByteArray json = "[\"http:\\/\\/www.last.fm\\/venue\\/8926427\"]";
  QVariantList list;
  list.append (QVariant(QLatin1String("http://www.last.fm/venue/8926427")));
  QVariant expected (list);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

 void TestParser::parseSimpleArray() {
  QByteArray json = "[\"foo\",\"bar\"]";
  QVariantList list;
  list.append (QLatin1String("foo"));
  list.append (QLatin1String("bar"));
  QVariant expected (list);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

void TestParser::parseMultipleArray() {
  //put also some extra spaces inside the json string
  QByteArray json = "[ {\"foo\":\"bar\"},\n\"number\",51.3 , [\"item1\", 123]]";
  QVariantMap map;
  map.insert (QLatin1String("foo"), QLatin1String("bar"));

  QVariantList array;
  array.append (QLatin1String("item1"));
  array.append (123);

  QVariantList list;
  list.append (map);
  list.append (QLatin1String("number"));
  list.append (QLatin1String("51.3"));
  list.append ((QVariant) array);

  QVariant expected (list);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
}

void TestParser::testTrueFalseNullValues() {
  QByteArray json = "[true,false, null, {\"foo\" : true}]";
  QVariantList list;
  list.append (QVariant(true));
  list.append (QVariant(false));
  list.append (QVariant());
  QVariantMap map;
  map.insert (QLatin1String("foo"), true);
  list.append (map);
  QVariant expected (list);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result, expected);
  QCOMPARE (result.toList().at(0).toBool(), true);
  QCOMPARE (result.toList().at(1).toBool(), false);
  QVERIFY (result.toList().at(2).isNull());
}

void TestParser::testEscapeChars() {
  QByteArray json = "[\"\\b \\f \\n \\r \\t \", \" \\\\ \\/ \\\\\", \"http:\\/\\/foo.com\"]";

  QVariantList list;
  list.append (QLatin1String("\b \f \n \r \t "));
  list.append (QLatin1String(" \\ / \\"));
  list.append (QLatin1String("http://foo.com"));

  QVariant expected (list);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (json, &ok);
  QVERIFY (ok);
  QCOMPARE(result.toList().size(), expected.toList().size() );
  QCOMPARE(result, expected);
}

void TestParser::testNumbers() {
  QFETCH(QByteArray, input);
  QFETCH(QVariant, expected);
  QFETCH(QVariant::Type, type);

  Parser parser;
  bool ok;
  QVariant result = parser.parse ("[" + input +"]", &ok);
  QVERIFY (ok);

  QVariant value = result.toList().at(0);
  QCOMPARE(value, expected);
  QCOMPARE( value.type(), type);
}

void TestParser::testNumbers_data() {
  QTest::addColumn<QByteArray>( "input" );
  QTest::addColumn<QVariant>( "expected" );
  QTest::addColumn<QVariant::Type>( "type" );

  QByteArray input;
  QVariant output;

  // simple ulonglong
  input = QByteArray("1");
  output = QVariant(QVariant::ULongLong);
  output.setValue(1);

  QTest::newRow("simple ulonglong") << input << output << QVariant::ULongLong;

  // big number
  input = QByteArray("128708157440");
  output = QVariant(QVariant::ULongLong);
  output.setValue(128708157440ull);

  QTest::newRow("big number") << input << output << QVariant::ULongLong;

  // simple double
  input = QByteArray("2.4");
  output = QVariant(QVariant::Double);
  output.setValue(2.4);

  QTest::newRow("simple double") << input << output << QVariant::Double;

  // negative int
  input = QByteArray("-100");
  output = QVariant(QVariant::LongLong);
  output.setValue(-100);

  QTest::newRow("negative int") << input << output << QVariant::LongLong;

  // negative double
  input = QByteArray("-3.4");
  output = QVariant(QVariant::Double);
  output.setValue(-3.4);

  QTest::newRow("negative double") << input << output << QVariant::Double;

  // exp1
  input = QByteArray("-5e+");
  output = QVariant(QVariant::ByteArray);
  output.setValue(input);

  QTest::newRow("exp1") << input << output << QVariant::ByteArray;

  // exp2
  input = QByteArray("2e");
  output = QVariant(QVariant::ByteArray);
  output.setValue(input);

  QTest::newRow("exp2") << input << output << QVariant::ByteArray;

  // exp3
  input = QByteArray("3e+");
  output = QVariant(QVariant::ByteArray);
  output.setValue(input);

  QTest::newRow("exp3") << input << output << QVariant::ByteArray;

  // exp4
  input = QByteArray("4.3E");
  output = QVariant(QVariant::ByteArray);
  output.setValue(input);

  QTest::newRow("exp4") << input << output << QVariant::ByteArray;

  // exp5
  input = QByteArray("5.4E-");
  output = QVariant(QVariant::ByteArray);
  output.setValue(input);

  QTest::newRow("exp5") << input << output << QVariant::ByteArray;
}

void TestParser::testTopLevelValues() {
  QFETCH(QByteArray, input);
  QFETCH(QVariant, expected);
  QFETCH(QVariant::Type, type);

  Parser parser;
  bool ok;
  QVariant result = parser.parse (input, &ok);
  QVERIFY (ok);

  QCOMPARE(result, expected);
  QCOMPARE(result.type(), type);
}

void TestParser::testTopLevelValues_data() {
  QTest::addColumn<QByteArray>( "input" );
  QTest::addColumn<QVariant>( "expected" );
  QTest::addColumn<QVariant::Type>( "type" );

  QByteArray input;
  QVariant output;

  // string
  input = QByteArray("\"foo bar\"");
  output = QVariant(QLatin1String("foo bar"));
  QTest::newRow("string") << input << output << QVariant::String;

  // number
  input = QByteArray("2.4");
  output = QVariant(QVariant::Double);
  output.setValue(2.4);
  QTest::newRow("simple double") << input << output << QVariant::Double;

  // boolean
  input = QByteArray("true");
  output = QVariant(QVariant::Bool);
  output.setValue(true);
  QTest::newRow("bool") << input << output << QVariant::Bool;

  // null
  input = QByteArray("null");
  output = QVariant();
  QTest::newRow("null") << input << output << QVariant::Invalid;

  // array
  input = QByteArray("[1,2,3]");
  QVariantList list;
  list << QVariant(1) << QVariant(2) << QVariant(3);
  output = QVariant(QVariant::List);
  output.setValue(list);
  QTest::newRow("array") << input << output << QVariant::List;

  // object
  input = QByteArray("{\"foo\" : \"bar\"}");
  QVariantMap map;
  map.insert(QLatin1String("foo"), QLatin1String("bar"));
  output = QVariant(QVariant::Map);
  output.setValue(map);
  QTest::newRow("object") << input << output << QVariant::Map;
}

QTEST_MAIN(TestParser)

#ifdef QMAKE_BUILD
  #include "testparser.moc"
#else
  #include "moc_testparser.cxx"
#endif
<|endoftext|>


<commit_before>/*  libscratch - Multipurpose objective C++ library.
    Copyright (C) 2012 - 2013  Angelo Geels

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

#include <cstdio> // for printf
#include <iostream> // for std::cin.get

#include <Scratch.h>

static INDEX _ctTests = 0;
static INDEX _ctFailed = 0;

#define TEST(expr) {                            \
  _ctTests++;                                   \
  printf("  Test #%d: (%s) ", _ctTests, #expr); \
  if(!(expr)) {                                 \
    _ctFailed++;                                \
    printf("FAILED!\n");                        \
  } else {                                      \
    printf("OK\n");                             \
  }                                             \
}

/// String testing
void TestString()
{
  printf("Testing strings\n");

  CString strTest;
  strTest += "Lib";
  strTest += "Scratch";
  strTest = strTest.ToLower();
  TEST(strTest == "libscratch");

  strTest += " is great";
  CStackArray<CString> astrParse = strTest.Split(" ");
  TEST(astrParse[2] == "great");
  TEST(astrParse[2][1] == 'r');

  CString strTest2 = strTest.Replace("great", "cool");
  TEST(strTest2 == "libscratch is cool");
}

/// Stack array testing
void TestStackArray()
{
  printf("Testing stack arrays\n");

  CStackArray<INDEX> aiNumbers;
  TEST(aiNumbers.Count() == 0);

  aiNumbers.Push() = 5;
  aiNumbers.Push() = 10;
  aiNumbers.Push() = 15;
  TEST(aiNumbers.Count() == 3);
  TEST(aiNumbers[0] == 5);
  TEST(aiNumbers[1] == 10);
  TEST(aiNumbers[2] + aiNumbers[0] == 20);

  TEST(aiNumbers.Pop() == 15);
  TEST(aiNumbers.Count() == 2);
}

/// Dictionary testing
void TestDictionary()
{
  printf("Testing dictionary\n");

  CDictionary<CString, INDEX> diTest;
  TEST(!diTest.HasKey("Test"));

  diTest["Test"] = 100;
  diTest["Test2"] = 200;
  TEST(diTest.HasKey("Test"));
  TEST(diTest["Test"] == 100);

  diTest.RemoveByKey("Test");
  TEST(diTest.Count() == 1);
  TEST(!diTest.HasKey("Test"));
}

/// Test file stream
void TestFilestream()
{
  printf("Testing file streams\n");

  // this test will create a Test.bin file, containing an integer 5 and the text "Hello!"
  CFileStream fsTest;
  fsTest.Open("Test.bin", "w");
  fsTest << INDEX(5);
  fsTest << "Hello!";
  fsTest.Close();

  // as a follow-up, we will read the same file from a seperate file stream
  CFileStream fsTestRead;
  fsTestRead.Open("Test.bin", "r");

  INDEX iTest = 0;
  fsTestRead >> iTest;
  TEST(iTest == 5);

  CString strTest;
  fsTestRead >> strTest;
  TEST(strTest == "Hello!");

  // note that closing the stream is optional (destructor does it for us), however we need to have it closed for the unlink below
  fsTestRead.Close();

  // remove the test file from the system
  unlink("Test.bin");
}

/// Vector tests
void TestVectors()
{
  printf("Testing vectors\n");

  Vector3f vTest(1, 0, 0);
  TEST(vTest.Length() == 1.0f);

  vTest *= 5.0f;
  TEST(vTest.Length() == 5.0f);

  vTest.x = 3;
  vTest.y = 4;
  TEST(vTest.Length() == 5.0f);

  vTest.Normalize();
  TEST(vTest.Length() == 1.0f);
}

int main()
{
  // perform tests
  TestString();
  TestStackArray();
  TestDictionary();
  TestFilestream();
  TestVectors();

  // report test results
  printf("\n\nResults: %d out of %d went OK.\n\n", _ctTests - _ctFailed, _ctTests);

  // check if all went OK
  if(_ctFailed == 0) {
    // it did! no failures. :)
    printf("All OK!\n");
  } else {
    // oops, there's a bug somewhere. please report!
    printf("Some problems seem to have popped up. Please report a bug.\n");
  }

  std::cin.get();
  return 0;
}
<commit_msg>Changed problems reported to an assertion.<commit_after>/*  libscratch - Multipurpose objective C++ library.
    Copyright (C) 2012 - 2013  Angelo Geels

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

#include <cstdio> // for printf
#include <iostream> // for std::cin.get

#include <Scratch.h>

static INDEX _ctTests = 0;
static INDEX _ctFailed = 0;

#define TEST(expr) {                            \
  _ctTests++;                                   \
  printf("  Test #%d: (%s) ", _ctTests, #expr); \
  if(!(expr)) {                                 \
    _ctFailed++;                                \
    printf("FAILED!\n");                        \
  } else {                                      \
    printf("OK\n");                             \
  }                                             \
}

/// String testing
void TestString()
{
  printf("Testing strings\n");

  CString strTest;
  strTest += "Lib";
  strTest += "Scratch";
  strTest = strTest.ToLower();
  TEST(strTest == "libscratch");

  strTest += " is great";
  CStackArray<CString> astrParse = strTest.Split(" ");
  TEST(astrParse[2] == "great");
  TEST(astrParse[2][1] == 'r');

  CString strTest2 = strTest.Replace("great", "cool");
  TEST(strTest2 == "libscratch is cool");
}

/// Stack array testing
void TestStackArray()
{
  printf("Testing stack arrays\n");

  CStackArray<INDEX> aiNumbers;
  TEST(aiNumbers.Count() == 0);

  aiNumbers.Push() = 5;
  aiNumbers.Push() = 10;
  aiNumbers.Push() = 15;
  TEST(aiNumbers.Count() == 3);
  TEST(aiNumbers[0] == 5);
  TEST(aiNumbers[1] == 10);
  TEST(aiNumbers[2] + aiNumbers[0] == 20);

  TEST(aiNumbers.Pop() == 15);
  TEST(aiNumbers.Count() == 2);
}

/// Dictionary testing
void TestDictionary()
{
  printf("Testing dictionary\n");

  CDictionary<CString, INDEX> diTest;
  TEST(!diTest.HasKey("Test"));

  diTest["Test"] = 100;
  diTest["Test2"] = 200;
  TEST(diTest.HasKey("Test"));
  TEST(diTest["Test"] == 100);

  diTest.RemoveByKey("Test");
  TEST(diTest.Count() == 1);
  TEST(!diTest.HasKey("Test"));
}

/// Test file stream
void TestFilestream()
{
  printf("Testing file streams\n");

  // this test will create a Test.bin file, containing an integer 5 and the text "Hello!"
  CFileStream fsTest;
  fsTest.Open("Test.bin", "w");
  fsTest << INDEX(5);
  fsTest << "Hello!";
  fsTest.Close();

  // as a follow-up, we will read the same file from a seperate file stream
  CFileStream fsTestRead;
  fsTestRead.Open("Test.bin", "r");

  INDEX iTest = 0;
  fsTestRead >> iTest;
  TEST(iTest == 5);

  CString strTest;
  fsTestRead >> strTest;
  TEST(strTest == "Hello!");

  // note that closing the stream is optional (destructor does it for us), however we need to have it closed for the unlink below
  fsTestRead.Close();

  // remove the test file from the system
  unlink("Test.bin");
}

/// Vector tests
void TestVectors()
{
  printf("Testing vectors\n");

  Vector3f vTest(1, 0, 0);
  TEST(vTest.Length() == 1.0f);

  vTest *= 5.0f;
  TEST(vTest.Length() == 5.0f);

  vTest.x = 3;
  vTest.y = 4;
  TEST(vTest.Length() == 5.0f);

  vTest.Normalize();
  TEST(vTest.Length() == 1.0f);
}

int main()
{
  // perform tests
  TestString();
  TestStackArray();
  TestDictionary();
  TestFilestream();
  TestVectors();

  // report test results
  printf("\n\nResults: %d out of %d went OK.\n\n", _ctTests - _ctFailed, _ctTests);

  // check if all went OK
  ASSERT(_ctFailed == 0);
  if(_ctFailed == 0) {
    // it did! no failures. :)
    printf("All OK!\n");
  }

  std::cin.get();
  return 0;
}
<|endoftext|>


<commit_before>#include "Device.h"
#include "DeviceStream.h"
#include "cudafuncs.h"
#include <algorithm>

using namespace sqaod_cuda;

Device::Device(int devNo) {
    devNo_ = -1;
    if (devNo != -1)
        initialize(devNo);
}

Device::~Device() {
    if (devNo_ != -1)
        finalize();
}

void Device::initialize(int devNo){
    if (devNo_ != -1) /* already initialized */
        throwErrorIf(devNo_ != devNo, "Trying to initialize Device that is already initialized.");

    cudaError_t cuerr = cudaSetDevice(devNo);
    throwErrorIf(cuerr != cudaSuccess,
                 "CUDA initialization failed, %s(%d).", cudaGetErrorName(cuerr), (int)cuerr);

    memStore_.initialize();
    devObjAllocator_.set(&memStore_);
    defaultDeviceStream_.set(NULL, memStore_, getNumThreadsToFillDevice());
    devConstScalarsFP64_.initialize(devObjAllocator_, defaultDeviceStream_);
    devConstScalarsFP32_.initialize(devObjAllocator_, defaultDeviceStream_);
    devNo_ = devNo;
}

void Device::finalize() {
    if (devNo_ == -1)
        return;
    synchronize();
    for (Streams::iterator it = streams_.begin(); it != streams_.end(); ++it)
        delete *it;
    defaultDeviceStream_.finalize();
    streams_.clear();
    // devObjAllocator_.finalize();
    memStore_.finalize();
    devNo_ = -1;
}

void Device::useManagedMemory(bool use) {
    throwErrorIf(devNo_ != -1, "Device::useManagedMemory() must be called before initialization.");
    memStore_.useManagedMemory(use);
}

void Device::enableLocalStore(bool enable) {
    throwErrorIf(devNo_ != -1, "Device::enableLocalStore() must be called before initialization.");
    memStore_.enableLocalStore(enable);
}

int Device::getNumThreadsToFillDevice() const {
    cudaDeviceProp prop;
    throwOnError(cudaGetDeviceProperties(&prop, devNo_));
    return prop.maxThreadsPerMultiProcessor * prop.multiProcessorCount;
}

DeviceStream *Device::newStream() {
    cudaStream_t stream;
    throwOnError(cudaStreamCreate(&stream));
    DeviceStream *deviceStream = new DeviceStream(stream, memStore_, getNumThreadsToFillDevice());
    streams_.pushBack(deviceStream);
    return deviceStream;
}

DeviceStream *Device::defaultStream() {
    return &defaultDeviceStream_;
}

void Device::releaseStream(DeviceStream *stream) {
    stream->releaseTempObjects();
    Streams::iterator it = std::find(streams_.begin(), streams_.end(), stream);
    assert(it != streams_.end());
    streams_.erase(it);
    if (stream != &defaultDeviceStream_)
        delete stream;
}

/* sync on device */
void Device::synchronize() {
    throwOnError(cudaDeviceSynchronize());
    for (Streams::iterator it = streams_.begin(); it != streams_.end(); ++it) {
        (*it)->releaseTempObjects();
    }
    defaultDeviceStream_.releaseTempObjects();
}
<commit_msg>Fix regression.  Device initialization fails.<commit_after>#include "Device.h"
#include "DeviceStream.h"
#include "cudafuncs.h"
#include <algorithm>

using namespace sqaod_cuda;

Device::Device(int devNo) {
    devNo_ = -1;
    if (devNo != -1)
        initialize(devNo);
}

Device::~Device() {
    if (devNo_ != -1)
        finalize();
}

void Device::initialize(int devNo){
    if (devNo_ != -1) /* already initialized */
        throwErrorIf(devNo_ != devNo, "Trying to initialize Device that is already initialized.");

    cudaError_t cuerr = cudaSetDevice(devNo);
    throwErrorIf(cuerr != cudaSuccess,
                 "CUDA initialization failed, %s(%d).", cudaGetErrorName(cuerr), (int)cuerr);

    memStore_.initialize();
    devObjAllocator_.set(&memStore_);
    devConstScalarsFP64_.initialize(devObjAllocator_, defaultDeviceStream_);
    devConstScalarsFP32_.initialize(devObjAllocator_, defaultDeviceStream_);
    devNo_ = devNo;
    defaultDeviceStream_.set(NULL, memStore_, getNumThreadsToFillDevice());
}

void Device::finalize() {
    if (devNo_ == -1)
        return;
    synchronize();
    for (Streams::iterator it = streams_.begin(); it != streams_.end(); ++it)
        delete *it;
    defaultDeviceStream_.finalize();
    streams_.clear();
    // devObjAllocator_.finalize();
    memStore_.finalize();
    devNo_ = -1;
}

void Device::useManagedMemory(bool use) {
    throwErrorIf(devNo_ != -1, "Device::useManagedMemory() must be called before initialization.");
    memStore_.useManagedMemory(use);
}

void Device::enableLocalStore(bool enable) {
    throwErrorIf(devNo_ != -1, "Device::enableLocalStore() must be called before initialization.");
    memStore_.enableLocalStore(enable);
}

int Device::getNumThreadsToFillDevice() const {
    cudaDeviceProp prop;
    throwOnError(cudaGetDeviceProperties(&prop, devNo_));
    return prop.maxThreadsPerMultiProcessor * prop.multiProcessorCount;
}

DeviceStream *Device::newStream() {
    cudaStream_t stream;
    throwOnError(cudaStreamCreate(&stream));
    DeviceStream *deviceStream = new DeviceStream(stream, memStore_, getNumThreadsToFillDevice());
    streams_.pushBack(deviceStream);
    return deviceStream;
}

DeviceStream *Device::defaultStream() {
    return &defaultDeviceStream_;
}

void Device::releaseStream(DeviceStream *stream) {
    stream->releaseTempObjects();
    Streams::iterator it = std::find(streams_.begin(), streams_.end(), stream);
    assert(it != streams_.end());
    streams_.erase(it);
    if (stream != &defaultDeviceStream_)
        delete stream;
}

/* sync on device */
void Device::synchronize() {
    throwOnError(cudaDeviceSynchronize());
    for (Streams::iterator it = streams_.begin(); it != streams_.end(); ++it) {
        (*it)->releaseTempObjects();
    }
    defaultDeviceStream_.releaseTempObjects();
}
<|endoftext|>


<commit_before>/*******************************************************************/
/*                               XDMF                              */
/*                   eXtensible Data Model and Format              */
/*                                                                 */
/*  Id : Id  */
/*  Date : $Date$ */
/*  Version : $Revision$ */
/*                                                                 */
/*  Author:                                                        */
/*     Jerry A. Clarke                                             */
/*     clarke@arl.army.mil                                         */
/*     US Army Research Laboratory                                 */
/*     Aberdeen Proving Ground, MD                                 */
/*                                                                 */
/*     Copyright @ 2002 US Army Research Laboratory                */
/*     All Rights Reserved                                         */
/*     See Copyright.txt or http://www.arl.hpc.mil/ice for details */
/*                                                                 */
/*     This software is distributed WITHOUT ANY WARRANTY; without  */
/*     even the implied warranty of MERCHANTABILITY or FITNESS     */
/*     FOR A PARTICULAR PURPOSE.  See the above copyright notice   */
/*     for more information.                                       */
/*                                                                 */
/*******************************************************************/
#include "XdmfAttribute.h"

#include "XdmfDataItem.h"
#include "XdmfDataDesc.h"
#include "XdmfArray.h"
#include "XdmfDOM.h"

XdmfAttribute::XdmfAttribute() {
  this->SetElementName("Attribute");
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_NONE;
  this->ValuesAreMine = 1;
  this->Values = NULL;
  this->ShapeDesc = new XdmfDataDesc();
  this->Active = 0;
  this->LightDataLimit = 100;
  this->Units = NULL;    // Ian Curington, HR Wallingford Ltd.
  }

XdmfAttribute::~XdmfAttribute() {
  if( this->ValuesAreMine && this->Values )  delete this->Values;
  delete this->ShapeDesc;
  if(this->Units) delete [] this->Units;  // Ian Curington, HR Wallingford Ltd.
}

XdmfInt32
XdmfAttribute::Release(){
  if( this->ValuesAreMine && this->Values )  delete this->Values;
  this->Values = NULL;
  return(XDMF_SUCCESS);
}

XdmfInt32
XdmfAttribute::Insert( XdmfElement *Child){
    if(Child && (
        XDMF_WORD_CMP(Child->GetElementName(), "DataItem") ||
        XDMF_WORD_CMP(Child->GetElementName(), "Information")
        )){
        return(XdmfElement::Insert(Child));
    }else{
        XdmfErrorMessage("Attribute can only Insert DataItem or Information elements");
    }
    return(XDMF_FAIL);
}

XdmfDataItem * XdmfAttribute::GetDataItem(){
    XdmfDataItem *di = NULL;
    XdmfXmlNode Node = this->DOM->FindDataElement(0, this->GetElement());

    if(Node) {
        di = (XdmfDataItem *)this->GetCurrentXdmfElement(Node);
    }
    if(!di){
        di = new XdmfDataItem;
        Node = this->DOM->InsertNew(this->GetElement(), "DataItem");
        di->SetDOM(this->DOM);
        di->SetElement(Node);
    }
    return(di);
}

XdmfInt32
XdmfAttribute::Build(){
    if(XdmfElement::Build() != XDMF_SUCCESS) return(XDMF_FAIL);
    if (this->GetActive())
      {
      this->Set("Active", "1");
      }
    this->Set("AttributeType", this->GetAttributeTypeAsString());
    this->Set("Center", this->GetAttributeCenterAsString());
    if(this->BuildFromDataXml() == XDMF_SUCCESS) return(XDMF_SUCCESS);
    if(this->Values){
        XdmfDataItem * di = this->GetDataItem();
        di->SetArray(this->Values);
        if(this->Values->GetNumberOfElements() > this->LightDataLimit) di->SetFormat(XDMF_FORMAT_HDF);
        di->Build();
        this->SetCurrentXdmfElement(di->GetElement(), NULL);
        delete di;
    }
// PATCH September 09, Ian Curington, HR Wallingford Ltd.
  if(this->Units)
  {
    this->Set("Units", this->GetUnits());
  }
// end patch

    return(XDMF_SUCCESS);
}

XdmfConstString
XdmfAttribute::GetAttributeTypeAsString( void ){
  switch ( this->AttributeType ){
    case XDMF_ATTRIBUTE_TYPE_SCALAR  :
      return("Scalar");
    case XDMF_ATTRIBUTE_TYPE_VECTOR  :
      return("Vector");
    case XDMF_ATTRIBUTE_TYPE_TENSOR  :
      return("Tensor");
    case XDMF_ATTRIBUTE_TYPE_MATRIX  :
      return("Matrix");
    case XDMF_ATTRIBUTE_TYPE_TENSOR6 :
      return("Tensor6");
    case XDMF_ATTRIBUTE_TYPE_GLOBALID :
      return("GlobalId");
    default :
      break;
    }
return("None");
}

XdmfInt32
XdmfAttribute::SetAttributeTypeFromString( XdmfConstString attributeType ){
XdmfInt64  Dimensions[3];

XdmfDebug("Setting Type to " << attributeType );
if( XDMF_WORD_CMP( attributeType, "Scalar" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_SCALAR;
  Dimensions[0] = 1;
  this->ShapeDesc->SetShape( 1, Dimensions );
} else if( XDMF_WORD_CMP( attributeType, "Vector" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_VECTOR;
  Dimensions[0] = 3;
  this->ShapeDesc->SetShape( 1, Dimensions );
} else if( XDMF_WORD_CMP( attributeType, "Tensor" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_TENSOR;
  Dimensions[0] = 3;
  Dimensions[1] = 3;
  this->ShapeDesc->SetShape( 2, Dimensions );
} else if( XDMF_WORD_CMP( attributeType, "Matrix" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_MATRIX;
} else if( XDMF_WORD_CMP( attributeType, "Tensor6" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_TENSOR6;
  Dimensions[0] = 6;
} else if( XDMF_WORD_CMP( attributeType, "GlobalId" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_GLOBALID;
  Dimensions[0] = 1;
} else {
  XdmfErrorMessage("Unknown Attribute Type " << attributeType );
  return( XDMF_FAIL );
  }
return( XDMF_SUCCESS );
}

XdmfConstString
XdmfAttribute::GetAttributeCenterAsString( void ){
  switch ( this->AttributeCenter ){
    case XDMF_ATTRIBUTE_CENTER_GRID :
      return( "Grid" );
    case XDMF_ATTRIBUTE_CENTER_CELL :
      return( "Cell" );
    case XDMF_ATTRIBUTE_CENTER_FACE :
      return( "Face" );
    case XDMF_ATTRIBUTE_CENTER_EDGE :
      return( "Edge" );
    case XDMF_ATTRIBUTE_CENTER_NODE :
      return( "Node" );
    default :
      break;
    }
return( "Node" );
}

XdmfInt32
XdmfAttribute::SetAttributeCenterFromString( XdmfConstString attributeCenter ){

if( XDMF_WORD_CMP( attributeCenter, "Grid" ) ) {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_GRID;
} else if( XDMF_WORD_CMP( attributeCenter, "Cell" ) ) {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_CELL;
} else if( XDMF_WORD_CMP( attributeCenter, "Face" ) ) {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_FACE;
} else if( XDMF_WORD_CMP( attributeCenter, "Edge" ) ) {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_EDGE;
} else if( XDMF_WORD_CMP( attributeCenter, "Node" ) ) {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_NODE;
} else {
  XdmfErrorMessage("Unknown Attribute Center " << attributeCenter );
  return( XDMF_FAIL );
  }
return( XDMF_SUCCESS );
}

XdmfInt32
XdmfAttribute::SetValues(XdmfArray *someValues){
    if(someValues == this->Values) return(XDMF_SUCCESS);
    if(this->ValuesAreMine && this->Values) delete this->Values;
    this->ValuesAreMine = 0;
    this->Values = someValues;
    return(XDMF_SUCCESS);
}

XdmfArray *
XdmfAttribute::GetValues(XdmfInt32 Create){
    if(!this->Values && Create){
        this->Values = new XdmfArray;
        this->ValuesAreMine = 1;
    }
    return(this->Values);
}

XdmfInt32
XdmfAttribute::UpdateInformation() {

XdmfConstString  Attribute;

if(XdmfElement::UpdateInformation() != XDMF_SUCCESS) return(XDMF_FAIL);
if( XDMF_WORD_CMP(this->GetElementType(), "Attribute") == 0){
    XdmfErrorMessage("Element type" << this->GetElementType() << " is not of type 'Attribute'");
    return(XDMF_FAIL);
}

Attribute = this->Get( "AttributeType" );
if(!Attribute) Attribute = this->Get( "Type" );
if( Attribute ){
  this->SetAttributeTypeFromString( Attribute );
} else {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_SCALAR;
}
free((void*)Attribute);

// PATCH September 09, Ian Curinton HR Wallingford Ltd.
Attribute = this->Get( "Units" );
if( Attribute ){
  this->SetUnits( Attribute );
} else {
  if(this->Units) delete [] this->Units;
  this->Units = NULL;
}
// end patch
free((void*)Attribute);

Attribute = this->Get( "Active" );
this->Active = 0;
if ( Attribute ){
  if( XDMF_WORD_CMP( Attribute, "1" ) ) {
    this->Active = 1;
  }
}
free((void*)Attribute);

Attribute = this->Get( "Center" );
if( Attribute ){
  this->SetAttributeCenterFromString( Attribute );
} else {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_NODE;
}
free((void*)Attribute);

Attribute = this->Get( "Dimensions" );
if( Attribute ){
  this->ShapeDesc->SetShapeFromString( Attribute );
}else{
    XdmfXmlNode  ValuesNode;
    ValuesNode = this->DOM->FindDataElement( 0, Element );
    if(!ValuesNode){
        XdmfErrorMessage("Dimensions of Attribute not set in XML and no DataItem found");
    }
    Attribute = this->DOM->Get( ValuesNode, "Dimensions" );
    if(!Attribute){
        XdmfErrorMessage("Dimensions of Attribute not set in XML or DataItem");
        free((void*)Attribute);
        return(XDMF_FAIL);
    }else{
        this->ShapeDesc->SetShapeFromString( Attribute );
    }
}
if(!this->Name) this->SetName(GetUnique("Attribute_"));
free((void*)Attribute);
return( XDMF_SUCCESS );
}

XdmfInt32
XdmfAttribute::Update() {

XdmfInt32  Status;
XdmfXmlNode  ValuesNode;
XdmfDataItem ValueReader;

if(XdmfElement::Update() != XDMF_SUCCESS) return(XDMF_FAIL);
if( this->AttributeType == XDMF_ATTRIBUTE_TYPE_NONE ){
  Status = this->UpdateInformation();
  if( Status == XDMF_FAIL ) {
    XdmfErrorMessage("Can't Initialize");
    return( XDMF_FAIL );
    }
  }

ValuesNode = this->DOM->FindDataElement( 0, Element );
if( ValuesNode ){
  ValueReader.SetDOM( this->DOM );
  ValueReader.SetDsmBuffer(this->DsmBuffer);
  if( this->ValuesAreMine && this->Values ){
    delete this->Values;
    this->Values = NULL;
  } else {
  }
  if(ValueReader.SetElement(ValuesNode) == XDMF_FAIL) return(XDMF_FAIL);
  if(ValueReader.UpdateInformation() == XDMF_FAIL) return(XDMF_FAIL);
  if(ValueReader.Update() == XDMF_FAIL) return(XDMF_FAIL);
  // Steal the array
  this->Values = ValueReader.GetArray();
  ValueReader.SetArrayIsMine(0);
  this->ValuesAreMine = 1;
  if( !this->Values ) {
    XdmfErrorMessage("Error Retriving Data Values");
    return( XDMF_FAIL );
    }
} else {
  XdmfErrorMessage("Element has no Data");
  return( XDMF_FAIL );
  }
return( XDMF_SUCCESS );
}
<commit_msg>COMP: Revert changes that were mistakenly checked in from HEAD.<commit_after>/*******************************************************************/
/*                               XDMF                              */
/*                   eXtensible Data Model and Format              */
/*                                                                 */
/*  Id : Id  */
/*  Date : $Date$ */
/*  Version : $Revision$ */
/*                                                                 */
/*  Author:                                                        */
/*     Jerry A. Clarke                                             */
/*     clarke@arl.army.mil                                         */
/*     US Army Research Laboratory                                 */
/*     Aberdeen Proving Ground, MD                                 */
/*                                                                 */
/*     Copyright @ 2002 US Army Research Laboratory                */
/*     All Rights Reserved                                         */
/*     See Copyright.txt or http://www.arl.hpc.mil/ice for details */
/*                                                                 */
/*     This software is distributed WITHOUT ANY WARRANTY; without  */
/*     even the implied warranty of MERCHANTABILITY or FITNESS     */
/*     FOR A PARTICULAR PURPOSE.  See the above copyright notice   */
/*     for more information.                                       */
/*                                                                 */
/*******************************************************************/
#include "XdmfAttribute.h"

#include "XdmfDataItem.h"
#include "XdmfDataDesc.h"
#include "XdmfArray.h"
#include "XdmfDOM.h"

XdmfAttribute::XdmfAttribute() {
  this->SetElementName("Attribute");
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_NONE;
  this->ValuesAreMine = 1;
  this->Values = NULL;
  this->ShapeDesc = new XdmfDataDesc();
  this->Active = 0;
  this->LightDataLimit = 100;
  this->Units = NULL;    // Ian Curington, HR Wallingford Ltd.
  }

XdmfAttribute::~XdmfAttribute() {
  if( this->ValuesAreMine && this->Values )  delete this->Values;
  delete this->ShapeDesc;
  if(this->Units) delete [] this->Units;  // Ian Curington, HR Wallingford Ltd.
}

XdmfInt32
XdmfAttribute::Release(){
  if( this->ValuesAreMine && this->Values )  delete this->Values;
  this->Values = NULL;
  return(XDMF_SUCCESS);
}

XdmfInt32
XdmfAttribute::Insert( XdmfElement *Child){
    if(Child && (
        XDMF_WORD_CMP(Child->GetElementName(), "DataItem") ||
        XDMF_WORD_CMP(Child->GetElementName(), "Information")
        )){
        return(XdmfElement::Insert(Child));
    }else{
        XdmfErrorMessage("Attribute can only Insert DataItem or Information elements");
    }
    return(XDMF_FAIL);
}

XdmfDataItem * XdmfAttribute::GetDataItem(){
    XdmfDataItem *di = NULL;
    XdmfXmlNode Node = this->DOM->FindDataElement(0, this->GetElement());

    if(Node) {
        di = (XdmfDataItem *)this->GetCurrentXdmfElement(Node);
    }
    if(!di){
        di = new XdmfDataItem;
        Node = this->DOM->InsertNew(this->GetElement(), "DataItem");
        di->SetDOM(this->DOM);
        di->SetElement(Node);
    }
    return(di);
}

XdmfInt32
XdmfAttribute::Build(){
    if(XdmfElement::Build() != XDMF_SUCCESS) return(XDMF_FAIL);
    if (this->GetActive())
      {
      this->Set("Active", "1");
      }
    this->Set("AttributeType", this->GetAttributeTypeAsString());
    this->Set("Center", this->GetAttributeCenterAsString());
    if(this->BuildFromDataXml() == XDMF_SUCCESS) return(XDMF_SUCCESS);
    if(this->Values){
        XdmfDataItem * di = this->GetDataItem();
        di->SetArray(this->Values);
        if(this->Values->GetNumberOfElements() > this->LightDataLimit) di->SetFormat(XDMF_FORMAT_HDF);
        di->Build();
        delete di;
    }
// PATCH September 09, Ian Curington, HR Wallingford Ltd.
	if(this->Units)
	{
		this->Set("Units", this->GetUnits());
	}
// end patch

    return(XDMF_SUCCESS);
}

XdmfConstString
XdmfAttribute::GetAttributeTypeAsString( void ){
  switch ( this->AttributeType ){
    case XDMF_ATTRIBUTE_TYPE_SCALAR  :
      return("Scalar");
    case XDMF_ATTRIBUTE_TYPE_VECTOR  :
      return("Vector");
    case XDMF_ATTRIBUTE_TYPE_TENSOR  :
      return("Tensor");
    case XDMF_ATTRIBUTE_TYPE_MATRIX  :
      return("Matrix");
    case XDMF_ATTRIBUTE_TYPE_TENSOR6 :
      return("Tensor6");
    case XDMF_ATTRIBUTE_TYPE_GLOBALID :
      return("GlobalId");
    default :
      break;
    }
return("None");
}

XdmfInt32
XdmfAttribute::SetAttributeTypeFromString( XdmfConstString attributeType ){
XdmfInt64  Dimensions[3];

XdmfDebug("Setting Type to " << attributeType );
if( XDMF_WORD_CMP( attributeType, "Scalar" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_SCALAR;
  Dimensions[0] = 1;
  this->ShapeDesc->SetShape( 1, Dimensions );
} else if( XDMF_WORD_CMP( attributeType, "Vector" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_VECTOR;
  Dimensions[0] = 3;
  this->ShapeDesc->SetShape( 1, Dimensions );
} else if( XDMF_WORD_CMP( attributeType, "Tensor" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_TENSOR;
  Dimensions[0] = 3;
  Dimensions[1] = 3;
  this->ShapeDesc->SetShape( 2, Dimensions );
} else if( XDMF_WORD_CMP( attributeType, "Matrix" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_MATRIX;
} else if( XDMF_WORD_CMP( attributeType, "Tensor6" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_TENSOR6;
  Dimensions[0] = 6;
} else if( XDMF_WORD_CMP( attributeType, "GlobalId" ) ) {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_GLOBALID;
  Dimensions[0] = 1;
} else {
  XdmfErrorMessage("Unknown Attribute Type " << attributeType );
  return( XDMF_FAIL );
  }
return( XDMF_SUCCESS );
}

XdmfConstString
XdmfAttribute::GetAttributeCenterAsString( void ){
  switch ( this->AttributeCenter ){
    case XDMF_ATTRIBUTE_CENTER_GRID :
      return( "Grid" );
    case XDMF_ATTRIBUTE_CENTER_CELL :
      return( "Cell" );
    case XDMF_ATTRIBUTE_CENTER_FACE :
      return( "Face" );
    case XDMF_ATTRIBUTE_CENTER_EDGE :
      return( "Edge" );
    case XDMF_ATTRIBUTE_CENTER_NODE :
      return( "Node" );
    default :
      break;
    }
return( "Node" );
}

XdmfInt32
XdmfAttribute::SetAttributeCenterFromString( XdmfConstString attributeCenter ){

if( XDMF_WORD_CMP( attributeCenter, "Grid" ) ) {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_GRID;
} else if( XDMF_WORD_CMP( attributeCenter, "Cell" ) ) {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_CELL;
} else if( XDMF_WORD_CMP( attributeCenter, "Face" ) ) {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_FACE;
} else if( XDMF_WORD_CMP( attributeCenter, "Edge" ) ) {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_EDGE;
} else if( XDMF_WORD_CMP( attributeCenter, "Node" ) ) {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_NODE;
} else {
  XdmfErrorMessage("Unknown Attribute Center " << attributeCenter );
  return( XDMF_FAIL );
  }
return( XDMF_SUCCESS );
}

XdmfInt32
XdmfAttribute::SetValues(XdmfArray *someValues){
    if(someValues == this->Values) return(XDMF_SUCCESS);
    if(this->ValuesAreMine && this->Values) delete this->Values;
    this->ValuesAreMine = 0;
    this->Values = someValues;
    return(XDMF_SUCCESS);
}

XdmfArray *
XdmfAttribute::GetValues(XdmfInt32 Create){
    if(!this->Values && Create){
        this->Values = new XdmfArray;
        this->ValuesAreMine = 1;
    }
    return(this->Values);
}

XdmfInt32
XdmfAttribute::UpdateInformation() {

XdmfConstString  Attribute;

if(XdmfElement::UpdateInformation() != XDMF_SUCCESS) return(XDMF_FAIL);
if( XDMF_WORD_CMP(this->GetElementType(), "Attribute") == 0){
    XdmfErrorMessage("Element type" << this->GetElementType() << " is not of type 'Attribute'");
    return(XDMF_FAIL);
}

Attribute = this->Get( "AttributeType" );
if(!Attribute) Attribute = this->Get( "Type" );
if( Attribute ){
  this->SetAttributeTypeFromString( Attribute );
} else {
  this->AttributeType = XDMF_ATTRIBUTE_TYPE_SCALAR;
}
free((void*)Attribute);

// PATCH September 09, Ian Curinton HR Wallingford Ltd.
Attribute = this->Get( "Units" );
if( Attribute ){
  this->SetUnits( Attribute );
} else {
  if(this->Units) delete [] this->Units;
  this->Units = NULL;
}
// end patch
free((void*)Attribute);

Attribute = this->Get( "Active" );
this->Active = 0;
if ( Attribute ){
  if( XDMF_WORD_CMP( Attribute, "1" ) ) {
    this->Active = 1;
  }
}
free((void*)Attribute);

Attribute = this->Get( "Center" );
if( Attribute ){
  this->SetAttributeCenterFromString( Attribute );
} else {
  this->AttributeCenter = XDMF_ATTRIBUTE_CENTER_NODE;
}
free((void*)Attribute);

Attribute = this->Get( "Dimensions" );
if( Attribute ){
  this->ShapeDesc->SetShapeFromString( Attribute );
}else{
    XdmfXmlNode  ValuesNode;
    ValuesNode = this->DOM->FindDataElement( 0, Element );
    if(!ValuesNode){
        XdmfErrorMessage("Dimensions of Attribute not set in XML and no DataItem found");
    }
    Attribute = this->DOM->Get( ValuesNode, "Dimensions" );
    if(!Attribute){
        XdmfErrorMessage("Dimensions of Attribute not set in XML or DataItem");
        free((void*)Attribute);
        return(XDMF_FAIL);
    }else{
        this->ShapeDesc->SetShapeFromString( Attribute );
    }
}
if(!this->Name) this->SetName(GetUnique("Attribute_"));
free((void*)Attribute);
return( XDMF_SUCCESS );
}

XdmfInt32
XdmfAttribute::Update() {

XdmfInt32  Status;
XdmfXmlNode  ValuesNode;
XdmfDataItem ValueReader;

if(XdmfElement::Update() != XDMF_SUCCESS) return(XDMF_FAIL);
if( this->AttributeType == XDMF_ATTRIBUTE_TYPE_NONE ){
  Status = this->UpdateInformation();
  if( Status == XDMF_FAIL ) {
    XdmfErrorMessage("Can't Initialize");
    return( XDMF_FAIL );
    }
  }

ValuesNode = this->DOM->FindDataElement( 0, Element );
if( ValuesNode ){
  ValueReader.SetDOM( this->DOM );
  ValueReader.SetDsmBuffer(this->DsmBuffer);
  if( this->ValuesAreMine && this->Values ){
    delete this->Values;
    this->Values = NULL;
  } else {
  }
  if(ValueReader.SetElement(ValuesNode) == XDMF_FAIL) return(XDMF_FAIL);
  if(ValueReader.UpdateInformation() == XDMF_FAIL) return(XDMF_FAIL);
  if(ValueReader.Update() == XDMF_FAIL) return(XDMF_FAIL);
  // Steal the array
  this->Values = ValueReader.GetArray();
  ValueReader.SetArrayIsMine(0);
  this->ValuesAreMine = 1;
  if( !this->Values ) {
    XdmfErrorMessage("Error Retriving Data Values");
    return( XDMF_FAIL );
    }
} else {
  XdmfErrorMessage("Element has no Data");
  return( XDMF_FAIL );
  }
return( XDMF_SUCCESS );
}
<|endoftext|>


<commit_before>/**
 * linklocator.cpp
 *
 * Copyright (c) 2002 Dave Corrie <kde@davecorrie.com>
 *
 *  This file is part of KMail.
 *
 *  KMail 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 2 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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "linklocator.h"
#include "pimemoticons.h"
#include <kglobal.h>
#include <kstandarddirs.h>
#include <kstaticdeleter.h>
#include <kmdcodec.h>
#include <kdebug.h>

#include <qstylesheet.h>
#include <qfile.h>

#include <limits.h>

QMap<QString, QString> *LinkLocator::s_smileyEmoticonNameMap = 0;
QMap<QString, QString> *LinkLocator::s_smileyEmoticonHTMLCache = 0;

static KStaticDeleter< QMap<QString, QString> > smileyMapDeleter;
static KStaticDeleter< QMap<QString, QString> > smileyCacheDeleter;

LinkLocator::LinkLocator(const QString& text, int pos)
  : mText(text), mPos(pos), mMaxUrlLen(4096), mMaxAddressLen(255)
{
  // If you change either of the above values for maxUrlLen or
  // maxAddressLen, then please also update the documentation for
  // setMaxUrlLen()/setMaxAddressLen() in the header file AND the
  // default values used for the maxUrlLen/maxAddressLen parameters
  // of convertToHtml().

  if ( !s_smileyEmoticonNameMap ) {
    smileyMapDeleter.setObject( s_smileyEmoticonNameMap,
                                new QMap<QString, QString>() );
    for ( int i = 0; i < EmotIcons::EnumSindex::COUNT; ++i ) {
      QString imageName( EmotIcons::EnumSindex::enumToString[i] );
      imageName.truncate( imageName.length() - 2 ); //remove the _0 bit
      s_smileyEmoticonNameMap->insert( EmotIcons::smiley(i), imageName );
    }
  }

  if ( !s_smileyEmoticonHTMLCache )
    smileyCacheDeleter.setObject( s_smileyEmoticonHTMLCache,
                                  new QMap<QString, QString>() );
}

void LinkLocator::setMaxUrlLen(int length)
{
  mMaxUrlLen = length;
}

int LinkLocator::maxUrlLen() const
{
  return mMaxUrlLen;
}

void LinkLocator::setMaxAddressLen(int length)
{
  mMaxAddressLen = length;
}

int LinkLocator::maxAddressLen() const
{
  return mMaxAddressLen;
}

QString LinkLocator::getUrl()
{
  QString url;
  if(atUrl())
  {
    // handle cases like this: <link>http://foobar.org/</link>
    int start = mPos;
    while(mPos < (int)mText.length() && mText[mPos] > ' ' && mText[mPos] != '"' &&
      QString("<>()[]").find(mText[mPos]) == -1)
    {
      ++mPos;
    }
    /* some URLs really end with:  # / &     */
    const QString allowedSpecialChars = QString("#/&");
    while(mPos > start && mText[mPos-1].isPunct() &&
		    allowedSpecialChars.find(mText[mPos-1]) == -1 )
    {
      --mPos;
    }

    url = mText.mid(start, mPos - start);
    if(isEmptyUrl(url) || mPos - start > maxUrlLen())
    {
      mPos = start;
      url = "";
    }
    else
    {
      --mPos;
    }
  }
  return url;
}

// keep this in sync with KMMainWin::slotUrlClicked()
bool LinkLocator::atUrl() const
{
  // the following characters are allowed in a dot-atom (RFC 2822):
  // a-z A-Z 0-9 . ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  const QString allowedSpecialChars = QString(".!#$%&'*+-/=?^_`{|}~");

  // the character directly before the URL must not be a letter, a number or
  // any other character allowed in a dot-atom (RFC 2822).
  if( ( mPos > 0 ) && ( mText[mPos-1].isLetterOrNumber() ||
                        ( allowedSpecialChars.find( mText[mPos-1] ) != -1 ) ) )
    return false;

  QChar ch = mText[mPos];
  return (ch=='h' && ( mText.mid(mPos, 7) == "http://" ||
                       mText.mid(mPos, 8) == "https://") ) ||
         (ch=='v' && mText.mid(mPos, 6) == "vnc://") ||
         (ch=='f' && ( mText.mid(mPos, 6) == "ftp://" ||
                       mText.mid(mPos, 7) == "ftps://") ) ||
         (ch=='s' && ( mText.mid(mPos, 7) == "sftp://" ||
                       mText.mid(mPos, 6) == "smb://") ) ||
         (ch=='m' && mText.mid(mPos, 7) == "mailto:") ||
         (ch=='w' && mText.mid(mPos, 4) == "www.") ||
         (ch=='f' && mText.mid(mPos, 4) == "ftp.");
         // note: no "file:" for security reasons
}

bool LinkLocator::isEmptyUrl(const QString& url)
{
  return url.isEmpty() ||
         url == "http://" ||
         url == "https://" ||
         url == "ftp://" ||
         url == "ftps://" ||
         url == "sftp://" ||
         url == "smb://" ||
         url == "vnc://" ||
         url == "mailto" ||
         url == "www" ||
         url == "ftp";
}

QString LinkLocator::getEmailAddress()
{
  QString address;

  if ( mText[mPos] == '@' ) {
    // the following characters are allowed in a dot-atom (RFC 2822):
    // a-z A-Z 0-9 . ! # $ % & ' * + - / = ? ^ _ ` { | } ~
    const QString allowedSpecialChars = QString(".!#$%&'*+-/=?^_`{|}~");

    // determine the local part of the email address
    int start = mPos - 1;
    while ( start >= 0 && mText[start].unicode() < 128 &&
            ( mText[start].isLetterOrNumber() ||
              mText[start] == '@' || // allow @ to find invalid email addresses
              allowedSpecialChars.find( mText[start] ) != -1 ) ) {
      if ( mText[start] == '@' )
        return QString(); // local part contains '@' -> no email address
      --start;
    }
    ++start;
    // we assume that an email address starts with a letter or a digit
    while ( ( start < mPos ) && !mText[start].isLetterOrNumber() )
      ++start;
    if ( start == mPos )
      return QString(); // local part is empty -> no email address

    // determine the domain part of the email address
    int dotPos = INT_MAX;
    int end = mPos + 1;
    while ( end < (int)mText.length() &&
            ( mText[end].isLetterOrNumber() ||
              mText[end] == '@' || // allow @ to find invalid email addresses
              mText[end] == '.' ||
              mText[end] == '-' ) ) {
      if ( mText[end] == '@' )
        return QString(); // domain part contains '@' -> no email address
      if ( mText[end] == '.' )
        dotPos = QMIN( dotPos, end ); // remember index of first dot in domain
      ++end;
    }
    // we assume that an email address ends with a letter or a digit
    while ( ( end > mPos ) && !mText[end - 1].isLetterOrNumber() )
      --end;
    if ( end == mPos )
      return QString(); // domain part is empty -> no email address
    if ( dotPos >= end )
      return QString(); // domain part doesn't contain a dot

    if ( end - start > maxAddressLen() )
      return QString(); // too long -> most likely no email address
    address = mText.mid( start, end - start );

    mPos = end - 1;
  }
  return address;
}

QString LinkLocator::convertToHtml(const QString& plainText, int flags,
  int maxUrlLen, int maxAddressLen)
{
  LinkLocator locator(plainText);
  locator.setMaxUrlLen(maxUrlLen);
  locator.setMaxAddressLen(maxAddressLen);

  QString str;
  QString result((QChar*)0, (int)locator.mText.length() * 2);
  QChar ch;
  int x;
  bool startOfLine = true;
  QString emoticon;

  for (locator.mPos = 0, x = 0; locator.mPos < (int)locator.mText.length(); locator.mPos++, x++)
  {
    ch = locator.mText[locator.mPos];
    if ( flags & PreserveSpaces )
    {
      if (ch==' ')
      {
        if (startOfLine) {
          result += " ";
          locator.mPos++, x++;
          startOfLine = false;
        }
        while (locator.mText[locator.mPos] == ' ')
        {
          result += " ";
          locator.mPos++, x++;
          if (locator.mText[locator.mPos] == ' ') {
            result += " ";
            locator.mPos++, x++;
          }
        }
        locator.mPos--, x--;
        continue;
      }
      else if (ch=='\t')
      {
        do
        {
          result += " ";
          x++;
        }
        while((x&7) != 0);
        x--;
        startOfLine = false;
        continue;
      }
    }
    if (ch=='\n')
    {
      result += "
";
      startOfLine = true;
      x = -1;
      continue;
    }

    startOfLine = false;
    if (ch=='&')
      result += "&";
    else if (ch=='"')
      result += """;
    else if (ch=='<')
      result += "<";
    else if (ch=='>')
      result += ">";
    else
    {
      const int start = locator.mPos;
      str = locator.getUrl();
      if(!str.isEmpty())
      {
        QString hyperlink;
        if(str.left(4) == "www.")
          hyperlink = "http://" + str;
        else if(str.left(4) == "ftp.")
          hyperlink = "ftp://" + str;
        else
          hyperlink = str;

	str = str.replace('&', "&");
        result += "" + str + "";
        x += locator.mPos - start;
      }
      else
      {
        str = locator.getEmailAddress();
        if(!str.isEmpty())
        {
          // len is the length of the local part
          int len = str.find('@');
          QString localPart = str.left(len);

          // remove the local part from the result (as '&'s have been expanded to
          // & we have to take care of the 4 additional characters per '&')
          result.truncate(result.length() - len - (localPart.contains('&')*4));
          x -= len;

          result += "" + str + "";
          x += str.length() - 1;
        }
        else {
          if ( flags & ReplaceSmileys )
            str = locator.getEmoticon();
          if ( ! str.isEmpty() ) {
            result += str;
            x += locator.mPos - start;
          }
          else {
            result += ch;
          }
        }
      }
    }
  }

  return result;
}

static QString pngToDataUrl( const QString & iconPath )
{
  if ( iconPath.isEmpty() )
    return QString::null;

  QFile pngFile( iconPath );
  if ( !pngFile.open( IO_ReadOnly | IO_Raw ) )
    return QString::null;

  QByteArray ba = pngFile.readAll();
  pngFile.close();
  return QString::fromLatin1("data:image/png;base64,%1")
         .arg( KCodecs::base64Encode( ba ) );
}

QString LinkLocator::getEmoticon()
{
  // smileys have to be prepended by whitespace
  if ( ( mPos > 0 ) && !mText[mPos-1].isSpace() )
    return QString::null;

  // since smileys start with ':', ';', '(' or '8' short circuit method
  const QChar ch = mText[mPos];
  if ( ch !=':' && ch != ';' && ch != '(' && ch != '8' )
    return QString::null;

  // find the end of the smiley (a smiley is at most 4 chars long and ends at
  // lineend or whitespace)
  const int MinSmileyLen = 2;
  const int MaxSmileyLen = 4;
  int smileyLen = 1;
  while ( ( smileyLen <= MaxSmileyLen ) &&
          ( mPos+smileyLen < (int)mText.length() ) &&
          !mText[mPos+smileyLen].isSpace() )
    smileyLen++;
  if ( smileyLen < MinSmileyLen || smileyLen > MaxSmileyLen )
    return QString::null;

  const QString smiley = mText.mid( mPos, smileyLen );
  if ( !s_smileyEmoticonNameMap->contains( smiley ) )
    return QString::null; // that's not a (known) smiley

  QString htmlRep;
  if ( s_smileyEmoticonHTMLCache->contains( smiley ) ) {
    htmlRep = (*s_smileyEmoticonHTMLCache)[smiley];
  }
  else {
    const QString imageName = (*s_smileyEmoticonNameMap)[smiley];

#if KDE_IS_VERSION( 3, 3, 91 )
    const QString iconPath = locate( "emoticons",
                                     EmotIcons::theme() +
                                     QString::fromLatin1( "/" ) +
                                     imageName + QString::fromLatin1(".png") );
#else
    const QString iconPath = locate( "data",
                                     QString::fromLatin1( "kopete/pics/emoticons/" )+
                                     EmotIcons::theme() +
                                     QString::fromLatin1( "/" ) +
                                     imageName + QString::fromLatin1(".png") );
#endif

    const QString dataUrl = pngToDataUrl( iconPath );
    if ( dataUrl.isEmpty() ) {
      htmlRep = QString::null;
    }
    else {
      // create an image tag (the text in attribute alt is used
      // for copy & paste) representing the smiley
      htmlRep = QString("")
                .arg( dataUrl,
                      QStyleSheet::escape( smiley ),
                      QStyleSheet::escape( smiley ) );
    }
    s_smileyEmoticonHTMLCache->insert( smiley, htmlRep );
  }

  if ( !htmlRep.isEmpty() )
    mPos += smileyLen - 1;

  return htmlRep;
}

<commit_msg>* Fix argument positions.<commit_after>/**
 * linklocator.cpp
 *
 * Copyright (c) 2002 Dave Corrie <kde@davecorrie.com>
 *
 *  This file is part of KMail.
 *
 *  KMail 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 2 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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "linklocator.h"
#include "pimemoticons.h"
#include <kglobal.h>
#include <kstandarddirs.h>
#include <kstaticdeleter.h>
#include <kmdcodec.h>
#include <kdebug.h>

#include <qstylesheet.h>
#include <qfile.h>

#include <limits.h>

QMap<QString, QString> *LinkLocator::s_smileyEmoticonNameMap = 0;
QMap<QString, QString> *LinkLocator::s_smileyEmoticonHTMLCache = 0;

static KStaticDeleter< QMap<QString, QString> > smileyMapDeleter;
static KStaticDeleter< QMap<QString, QString> > smileyCacheDeleter;

LinkLocator::LinkLocator(const QString& text, int pos)
  : mText(text), mPos(pos), mMaxUrlLen(4096), mMaxAddressLen(255)
{
  // If you change either of the above values for maxUrlLen or
  // maxAddressLen, then please also update the documentation for
  // setMaxUrlLen()/setMaxAddressLen() in the header file AND the
  // default values used for the maxUrlLen/maxAddressLen parameters
  // of convertToHtml().

  if ( !s_smileyEmoticonNameMap ) {
    smileyMapDeleter.setObject( s_smileyEmoticonNameMap,
                                new QMap<QString, QString>() );
    for ( int i = 0; i < EmotIcons::EnumSindex::COUNT; ++i ) {
      QString imageName( EmotIcons::EnumSindex::enumToString[i] );
      imageName.truncate( imageName.length() - 2 ); //remove the _0 bit
      s_smileyEmoticonNameMap->insert( EmotIcons::smiley(i), imageName );
    }
  }

  if ( !s_smileyEmoticonHTMLCache )
    smileyCacheDeleter.setObject( s_smileyEmoticonHTMLCache,
                                  new QMap<QString, QString>() );
}

void LinkLocator::setMaxUrlLen(int length)
{
  mMaxUrlLen = length;
}

int LinkLocator::maxUrlLen() const
{
  return mMaxUrlLen;
}

void LinkLocator::setMaxAddressLen(int length)
{
  mMaxAddressLen = length;
}

int LinkLocator::maxAddressLen() const
{
  return mMaxAddressLen;
}

QString LinkLocator::getUrl()
{
  QString url;
  if(atUrl())
  {
    // handle cases like this: <link>http://foobar.org/</link>
    int start = mPos;
    while(mPos < (int)mText.length() && mText[mPos] > ' ' && mText[mPos] != '"' &&
      QString("<>()[]").find(mText[mPos]) == -1)
    {
      ++mPos;
    }
    /* some URLs really end with:  # / &     */
    const QString allowedSpecialChars = QString("#/&");
    while(mPos > start && mText[mPos-1].isPunct() &&
		    allowedSpecialChars.find(mText[mPos-1]) == -1 )
    {
      --mPos;
    }

    url = mText.mid(start, mPos - start);
    if(isEmptyUrl(url) || mPos - start > maxUrlLen())
    {
      mPos = start;
      url = "";
    }
    else
    {
      --mPos;
    }
  }
  return url;
}

// keep this in sync with KMMainWin::slotUrlClicked()
bool LinkLocator::atUrl() const
{
  // the following characters are allowed in a dot-atom (RFC 2822):
  // a-z A-Z 0-9 . ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  const QString allowedSpecialChars = QString(".!#$%&'*+-/=?^_`{|}~");

  // the character directly before the URL must not be a letter, a number or
  // any other character allowed in a dot-atom (RFC 2822).
  if( ( mPos > 0 ) && ( mText[mPos-1].isLetterOrNumber() ||
                        ( allowedSpecialChars.find( mText[mPos-1] ) != -1 ) ) )
    return false;

  QChar ch = mText[mPos];
  return (ch=='h' && ( mText.mid(mPos, 7) == "http://" ||
                       mText.mid(mPos, 8) == "https://") ) ||
         (ch=='v' && mText.mid(mPos, 6) == "vnc://") ||
         (ch=='f' && ( mText.mid(mPos, 6) == "ftp://" ||
                       mText.mid(mPos, 7) == "ftps://") ) ||
         (ch=='s' && ( mText.mid(mPos, 7) == "sftp://" ||
                       mText.mid(mPos, 6) == "smb://") ) ||
         (ch=='m' && mText.mid(mPos, 7) == "mailto:") ||
         (ch=='w' && mText.mid(mPos, 4) == "www.") ||
         (ch=='f' && mText.mid(mPos, 4) == "ftp.");
         // note: no "file:" for security reasons
}

bool LinkLocator::isEmptyUrl(const QString& url)
{
  return url.isEmpty() ||
         url == "http://" ||
         url == "https://" ||
         url == "ftp://" ||
         url == "ftps://" ||
         url == "sftp://" ||
         url == "smb://" ||
         url == "vnc://" ||
         url == "mailto" ||
         url == "www" ||
         url == "ftp";
}

QString LinkLocator::getEmailAddress()
{
  QString address;

  if ( mText[mPos] == '@' ) {
    // the following characters are allowed in a dot-atom (RFC 2822):
    // a-z A-Z 0-9 . ! # $ % & ' * + - / = ? ^ _ ` { | } ~
    const QString allowedSpecialChars = QString(".!#$%&'*+-/=?^_`{|}~");

    // determine the local part of the email address
    int start = mPos - 1;
    while ( start >= 0 && mText[start].unicode() < 128 &&
            ( mText[start].isLetterOrNumber() ||
              mText[start] == '@' || // allow @ to find invalid email addresses
              allowedSpecialChars.find( mText[start] ) != -1 ) ) {
      if ( mText[start] == '@' )
        return QString(); // local part contains '@' -> no email address
      --start;
    }
    ++start;
    // we assume that an email address starts with a letter or a digit
    while ( ( start < mPos ) && !mText[start].isLetterOrNumber() )
      ++start;
    if ( start == mPos )
      return QString(); // local part is empty -> no email address

    // determine the domain part of the email address
    int dotPos = INT_MAX;
    int end = mPos + 1;
    while ( end < (int)mText.length() &&
            ( mText[end].isLetterOrNumber() ||
              mText[end] == '@' || // allow @ to find invalid email addresses
              mText[end] == '.' ||
              mText[end] == '-' ) ) {
      if ( mText[end] == '@' )
        return QString(); // domain part contains '@' -> no email address
      if ( mText[end] == '.' )
        dotPos = QMIN( dotPos, end ); // remember index of first dot in domain
      ++end;
    }
    // we assume that an email address ends with a letter or a digit
    while ( ( end > mPos ) && !mText[end - 1].isLetterOrNumber() )
      --end;
    if ( end == mPos )
      return QString(); // domain part is empty -> no email address
    if ( dotPos >= end )
      return QString(); // domain part doesn't contain a dot

    if ( end - start > maxAddressLen() )
      return QString(); // too long -> most likely no email address
    address = mText.mid( start, end - start );

    mPos = end - 1;
  }
  return address;
}

QString LinkLocator::convertToHtml(const QString& plainText, int flags,
  int maxUrlLen, int maxAddressLen)
{
  LinkLocator locator(plainText);
  locator.setMaxUrlLen(maxUrlLen);
  locator.setMaxAddressLen(maxAddressLen);

  QString str;
  QString result((QChar*)0, (int)locator.mText.length() * 2);
  QChar ch;
  int x;
  bool startOfLine = true;
  QString emoticon;

  for (locator.mPos = 0, x = 0; locator.mPos < (int)locator.mText.length(); locator.mPos++, x++)
  {
    ch = locator.mText[locator.mPos];
    if ( flags & PreserveSpaces )
    {
      if (ch==' ')
      {
        if (startOfLine) {
          result += " ";
          locator.mPos++, x++;
          startOfLine = false;
        }
        while (locator.mText[locator.mPos] == ' ')
        {
          result += " ";
          locator.mPos++, x++;
          if (locator.mText[locator.mPos] == ' ') {
            result += " ";
            locator.mPos++, x++;
          }
        }
        locator.mPos--, x--;
        continue;
      }
      else if (ch=='\t')
      {
        do
        {
          result += " ";
          x++;
        }
        while((x&7) != 0);
        x--;
        startOfLine = false;
        continue;
      }
    }
    if (ch=='\n')
    {
      result += "
";
      startOfLine = true;
      x = -1;
      continue;
    }

    startOfLine = false;
    if (ch=='&')
      result += "&";
    else if (ch=='"')
      result += """;
    else if (ch=='<')
      result += "<";
    else if (ch=='>')
      result += ">";
    else
    {
      const int start = locator.mPos;
      str = locator.getUrl();
      if(!str.isEmpty())
      {
        QString hyperlink;
        if(str.left(4) == "www.")
          hyperlink = "http://" + str;
        else if(str.left(4) == "ftp.")
          hyperlink = "ftp://" + str;
        else
          hyperlink = str;

	str = str.replace('&', "&");
        result += "" + str + "";
        x += locator.mPos - start;
      }
      else
      {
        str = locator.getEmailAddress();
        if(!str.isEmpty())
        {
          // len is the length of the local part
          int len = str.find('@');
          QString localPart = str.left(len);

          // remove the local part from the result (as '&'s have been expanded to
          // & we have to take care of the 4 additional characters per '&')
          result.truncate(result.length() - len - (localPart.contains('&')*4));
          x -= len;

          result += "" + str + "";
          x += str.length() - 1;
        }
        else {
          if ( flags & ReplaceSmileys )
            str = locator.getEmoticon();
          if ( ! str.isEmpty() ) {
            result += str;
            x += locator.mPos - start;
          }
          else {
            result += ch;
          }
        }
      }
    }
  }

  return result;
}

static QString pngToDataUrl( const QString & iconPath )
{
  if ( iconPath.isEmpty() )
    return QString::null;

  QFile pngFile( iconPath );
  if ( !pngFile.open( IO_ReadOnly | IO_Raw ) )
    return QString::null;

  QByteArray ba = pngFile.readAll();
  pngFile.close();
  return QString::fromLatin1("data:image/png;base64,%1")
         .arg( KCodecs::base64Encode( ba ) );
}

QString LinkLocator::getEmoticon()
{
  // smileys have to be prepended by whitespace
  if ( ( mPos > 0 ) && !mText[mPos-1].isSpace() )
    return QString::null;

  // since smileys start with ':', ';', '(' or '8' short circuit method
  const QChar ch = mText[mPos];
  if ( ch !=':' && ch != ';' && ch != '(' && ch != '8' )
    return QString::null;

  // find the end of the smiley (a smiley is at most 4 chars long and ends at
  // lineend or whitespace)
  const int MinSmileyLen = 2;
  const int MaxSmileyLen = 4;
  int smileyLen = 1;
  while ( ( smileyLen <= MaxSmileyLen ) &&
          ( mPos+smileyLen < (int)mText.length() ) &&
          !mText[mPos+smileyLen].isSpace() )
    smileyLen++;
  if ( smileyLen < MinSmileyLen || smileyLen > MaxSmileyLen )
    return QString::null;

  const QString smiley = mText.mid( mPos, smileyLen );
  if ( !s_smileyEmoticonNameMap->contains( smiley ) )
    return QString::null; // that's not a (known) smiley

  QString htmlRep;
  if ( s_smileyEmoticonHTMLCache->contains( smiley ) ) {
    htmlRep = (*s_smileyEmoticonHTMLCache)[smiley];
  }
  else {
    const QString imageName = (*s_smileyEmoticonNameMap)[smiley];

#if KDE_IS_VERSION( 3, 3, 91 )
    const QString iconPath = locate( "emoticons",
                                     EmotIcons::theme() +
                                     QString::fromLatin1( "/" ) +
                                     imageName + QString::fromLatin1(".png") );
#else
    const QString iconPath = locate( "data",
                                     QString::fromLatin1( "kopete/pics/emoticons/" )+
                                     EmotIcons::theme() +
                                     QString::fromLatin1( "/" ) +
                                     imageName + QString::fromLatin1(".png") );
#endif

    const QString dataUrl = pngToDataUrl( iconPath );
    if ( dataUrl.isEmpty() ) {
      htmlRep = QString::null;
    }
    else {
      // create an image tag (the text in attribute alt is used
      // for copy & paste) representing the smiley
      htmlRep = QString("")
                .arg( dataUrl,
                      QStyleSheet::escape( smiley ),
                      QStyleSheet::escape( smiley ) );
    }
    s_smileyEmoticonHTMLCache->insert( smiley, htmlRep );
  }

  if ( !htmlRep.isEmpty() )
    mPos += smileyLen - 1;

  return htmlRep;
}

<|endoftext|>


<commit_before>#include <boost/algorithm/hex.hpp>
#include <boost/filesystem.hpp>

#include "crypto.h"
#include "secondary.h"

namespace Uptane {
Secondary::Secondary(const SecondaryConfig &config_in, Uptane::Repository *primary)
    : config(config_in), transport(primary) {
  boost::filesystem::create_directories(config.firmware_path.parent_path());
}

Json::Value Secondary::genAndSendManifest() {
  Json::Value manifest;

  // package manager will generate this part in future
  Json::Value installed_image;
  installed_image["filepath"] = config.firmware_path.string();
  std::string content =
      Utils::readFile(config.firmware_path.string());  // FIXME this is bad idea to read all image to memory, we need to
                                                       // implement progressive hash function
  installed_image["fileinfo"]["hashes"]["sha256"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(content)));
  installed_image["fileinfo"]["length"] = static_cast<Json::Int64>(content.size());
  //////////////////

  manifest["attacks_detected"] = "";
  manifest["installed_image"] = installed_image;
  manifest["ecu_serial"] = config.ecu_serial;
  manifest["previous_timeserver_time"] = "1970-01-01T00:00:00Z";
  manifest["timeserver_time"] = "1970-01-01T00:00:00Z";
  Json::Value signed_ecu_version = Crypto::signTuf((config.full_client_dir / config.ecu_private_key).string(),
                                                   (config.full_client_dir / config.ecu_public_key).string(), manifest);
  return signed_ecu_version;
}

void Secondary::newTargetsCallBack(const std::vector<Uptane::Target> &targets) {
  std::cout << "I am " << config.ecu_serial << " and just got a new targets\n";

  std::vector<Uptane::Target>::const_iterator it;
  for (it = targets.begin(); it != targets.end(); ++it) {
    if (it->IsForSecondary(config.ecu_serial)) {
      install(*it);
      break;
    } else {
      std::cout << "Target " << *it << " isn't for this ECU\n";
    }
  }
}

void Secondary::setPrivateKey(const std::string &pkey) {
  Utils::writeFile((config.full_client_dir / config.ecu_private_key).string(), pkey);
}

void Secondary::install(const Uptane::Target &target) {
  std::string image = transport.getImage(target);
  Utils::writeFile(config.firmware_path.string(), image);
}
}
<commit_msg>Log using LOGGER_LOG not std::cout<commit_after>#include <logger.h>
#include <boost/algorithm/hex.hpp>
#include <boost/filesystem.hpp>

#include "crypto.h"
#include "secondary.h"

namespace Uptane {
Secondary::Secondary(const SecondaryConfig &config_in, Uptane::Repository *primary)
    : config(config_in), transport(primary) {
  boost::filesystem::create_directories(config.firmware_path.parent_path());
}

Json::Value Secondary::genAndSendManifest() {
  Json::Value manifest;

  // package manager will generate this part in future
  Json::Value installed_image;
  installed_image["filepath"] = config.firmware_path.string();
  std::string content =
      Utils::readFile(config.firmware_path.string());  // FIXME this is bad idea to read all image to memory, we need to
                                                       // implement progressive hash function
  installed_image["fileinfo"]["hashes"]["sha256"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(content)));
  installed_image["fileinfo"]["length"] = static_cast<Json::Int64>(content.size());
  //////////////////

  manifest["attacks_detected"] = "";
  manifest["installed_image"] = installed_image;
  manifest["ecu_serial"] = config.ecu_serial;
  manifest["previous_timeserver_time"] = "1970-01-01T00:00:00Z";
  manifest["timeserver_time"] = "1970-01-01T00:00:00Z";
  Json::Value signed_ecu_version = Crypto::signTuf((config.full_client_dir / config.ecu_private_key).string(),
                                                   (config.full_client_dir / config.ecu_public_key).string(), manifest);
  return signed_ecu_version;
}

void Secondary::newTargetsCallBack(const std::vector<Uptane::Target> &targets) {
  LOGGER_LOG(LVL_trace, "I am " << config.ecu_serial << " and just got a new targets");

  std::vector<Uptane::Target>::const_iterator it;
  for (it = targets.begin(); it != targets.end(); ++it) {
    if (it->IsForSecondary(config.ecu_serial)) {
      install(*it);
      break;
    } else {
      LOGGER_LOG(LVL_trace, "Target " << *it << " isn't for this ECU");
    }
  }
}

void Secondary::setPrivateKey(const std::string &pkey) {
  Utils::writeFile((config.full_client_dir / config.ecu_private_key).string(), pkey);
}

void Secondary::install(const Uptane::Target &target) {
  std::string image = transport.getImage(target);
  Utils::writeFile(config.firmware_path.string(), image);
}
}
<|endoftext|>