<commit_before>#ifndef _A_STAR_HPP_
#define _A_STAR_HPP_

#include <vector>

#include <boost/none.hpp>
#include <boost/optional.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/unordered_map.hpp>

#include "search/BucketPriorityQueue.hpp"
#include "util/PointerOps.hpp"

template <
  class Domain,
  class Node
  >
class AStar
{
private:
  typedef BucketPriorityQueue<Node> Open;
  typedef boost::unordered_map<
    Node *,
    boost::optional<typename Open::ItemPointer>,
    PointerHash<Node>,
    PointerEq<Node>
    , boost::fast_pool_allocator< std::pair<Node * const,
                                            boost::optional<typename Open::ItemPointer> > >
    > Closed;

public:
  AStar(const Domain &domain)
    : open(*new Open())
    , closed(*new Closed(50000000))  // requested number of hash buckets
    , goal(NULL)
    , domain(domain)
    , num_expanded(0)
    , num_generated(0)
  {
  }

  ~AStar()
  {
    // I don't delete open or closed.  This appears to be acceptable,
    // due to my use of memory pools in key places.  Check for
    // yourself, with valgrind: no memory is leaked.
  }

  void search()
  {
    // TODO: the following check is buggy.  What if there is no goal,
    // and the search has been completed?
    if (goal != NULL)
      return;

    typename std::vector<Node *> succs;    // re-use a stack-allocated
                                           // vector for successor
                                           // nodes, thus avoiding
                                           // repeated heap
                                           // allocation.

    {
      assert(all_closed_item_ptrs_valid());
      Node *start_node = domain.create_start_node();
      boost::optional<typename Open::ItemPointer> open_ptr = open.push(start_node);
      assert(open_ptr);
      closed[start_node] = open_ptr;
      assert(closed.find(start_node) != closed.end());
      assert(open.size() == 1);
      assert(closed.size() == 1);
      assert(all_closed_item_ptrs_valid());
    }

    while (!open.empty())
    {
// #ifndef NDEBUG
//       std::cerr << "open size is " << open.size() << std::endl
//                 << "closed size is " << closed.size() << std::endl;
// #endif

      Node *n = open.top();
      open.pop();
      assert(closed.find(n) != closed.end());
      closed[n] = boost::none;
      assert(all_closed_item_ptrs_valid());

      if (domain.is_goal(n->get_state())) {
        goal = n;
        return;
      }

      domain.expand(*n, succs);
      num_expanded += 1;
      num_generated += succs.size();

      for (unsigned succ_i = 0; succ_i < succs.size(); succ_i += 1)
      {
        Node *succ = succs[succ_i];
        assert(open.size() <= closed.size());
        assert(all_closed_item_ptrs_valid());
        typename Closed::iterator closed_it = closed.find(succ);
        if (closed.find(succ) != closed.end()) {
          boost::optional<typename Open::ItemPointer> &open_ptr = closed_it->second;

          if ( open_ptr ) {
            Node *old_succ = open.lookup(*open_ptr);

            if ( succ->get_f() < old_succ->get_f() ) {
              // A worse copy of succ is in the open list.  Replace it!
              assert(old_succ->get_state() == succ->get_state());
              assert(*old_succ == *succ);

              domain.free_node(old_succ);    // get rid of the old copy
              open.erase(*open_ptr);
              closed.erase(succ);

              open_ptr = open.push(succ);    // insert the new copy
              closed[succ] = open_ptr;

              assert(all_closed_item_ptrs_valid());
            }
          }
          else {
            // succ is not in the open list, but is closed.  Drop it!
            domain.free_node(succ);
          }
        }
        else {
          // succ has not been generated before.
          boost::optional<typename Open::ItemPointer> open_ptr = open.push(succ);
          closed[succ] = open_ptr;
          assert(closed.find(open.lookup(*open_ptr)) != closed.end());
          assert(all_closed_item_ptrs_valid());
        }
      } /* end for */
    } /* end while */
  }

  const Node * get_goal() const
  {
#ifndef NDEBUG
    std::cerr << open.size() << " nodes in open at end of search" << std::endl
              << closed.size() << " nodes in closed at end of search" << std::endl;
#endif
    return goal;
  }

  const Domain & get_domain() const
  {
    return domain;
  }

  unsigned get_num_generated() const
  {
    return num_generated;
  }

  unsigned get_num_expanded() const
  {
    return num_expanded;
  }

private:
  bool all_closed_item_ptrs_valid() const
  {
    return true;
    std::cerr << "checking if item pointers are valid" << std::endl
              << "  " << closed.size() << " pointers to check" << std::endl;
    for (typename Closed::const_iterator closed_it = closed.begin();
         closed_it != closed.end();
         ++closed_it) {
      if ( closed_it->second && !open.valid_item_pointer(*closed_it->second) )
        return false;
    }
    return true;
  }

private:
  Open &open;
  Closed &closed;

  const Node * goal;
  const Domain &domain;

  unsigned num_expanded;
  unsigned num_generated;

private:
  AStar(const AStar<Domain, Node> &);
  AStar<Domain, Node> & operator =(const AStar<Domain, Node> &);
};

#endif /* !_A_STAR_HPP_ */
<commit_msg>Formatting tweak in long Closed typedef.<commit_after>#ifndef _A_STAR_HPP_
#define _A_STAR_HPP_

#include <vector>

#include <boost/none.hpp>
#include <boost/optional.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/unordered_map.hpp>

#include "search/BucketPriorityQueue.hpp"
#include "util/PointerOps.hpp"

template <
  class Domain,
  class Node
  >
class AStar
{
private:
  typedef BucketPriorityQueue<Node> Open;
  typedef boost::unordered_map<
    Node *,
    boost::optional<typename Open::ItemPointer>,
    PointerHash<Node>,
    PointerEq<Node>
    , boost::fast_pool_allocator<
        std::pair<Node * const,
                  boost::optional<typename Open::ItemPointer> > >
    > Closed;

public:
  AStar(const Domain &domain)
    : open(*new Open())
    , closed(*new Closed(50000000))  // requested number of hash buckets
    , goal(NULL)
    , domain(domain)
    , num_expanded(0)
    , num_generated(0)
  {
  }

  ~AStar()
  {
    // I don't delete open or closed.  This appears to be acceptable,
    // due to my use of memory pools in key places.  Check for
    // yourself, with valgrind: no memory is leaked.
  }

  void search()
  {
    // TODO: the following check is buggy.  What if there is no goal,
    // and the search has been completed?
    if (goal != NULL)
      return;

    typename std::vector<Node *> succs;    // re-use a stack-allocated
                                           // vector for successor
                                           // nodes, thus avoiding
                                           // repeated heap
                                           // allocation.

    {
      assert(all_closed_item_ptrs_valid());
      Node *start_node = domain.create_start_node();
      boost::optional<typename Open::ItemPointer> open_ptr = open.push(start_node);
      assert(open_ptr);
      closed[start_node] = open_ptr;
      assert(closed.find(start_node) != closed.end());
      assert(open.size() == 1);
      assert(closed.size() == 1);
      assert(all_closed_item_ptrs_valid());
    }

    while (!open.empty())
    {
// #ifndef NDEBUG
//       std::cerr << "open size is " << open.size() << std::endl
//                 << "closed size is " << closed.size() << std::endl;
// #endif

      Node *n = open.top();
      open.pop();
      assert(closed.find(n) != closed.end());
      closed[n] = boost::none;
      assert(all_closed_item_ptrs_valid());

      if (domain.is_goal(n->get_state())) {
        goal = n;
        return;
      }

      domain.expand(*n, succs);
      num_expanded += 1;
      num_generated += succs.size();

      for (unsigned succ_i = 0; succ_i < succs.size(); succ_i += 1)
      {
        Node *succ = succs[succ_i];
        assert(open.size() <= closed.size());
        assert(all_closed_item_ptrs_valid());
        typename Closed::iterator closed_it = closed.find(succ);
        if (closed.find(succ) != closed.end()) {
          boost::optional<typename Open::ItemPointer> &open_ptr = closed_it->second;

          if ( open_ptr ) {
            Node *old_succ = open.lookup(*open_ptr);

            if ( succ->get_f() < old_succ->get_f() ) {
              // A worse copy of succ is in the open list.  Replace it!
              assert(old_succ->get_state() == succ->get_state());
              assert(*old_succ == *succ);

              domain.free_node(old_succ);    // get rid of the old copy
              open.erase(*open_ptr);
              closed.erase(succ);

              open_ptr = open.push(succ);    // insert the new copy
              closed[succ] = open_ptr;

              assert(all_closed_item_ptrs_valid());
            }
          }
          else {
            // succ is not in the open list, but is closed.  Drop it!
            domain.free_node(succ);
          }
        }
        else {
          // succ has not been generated before.
          boost::optional<typename Open::ItemPointer> open_ptr = open.push(succ);
          closed[succ] = open_ptr;
          assert(closed.find(open.lookup(*open_ptr)) != closed.end());
          assert(all_closed_item_ptrs_valid());
        }
      } /* end for */
    } /* end while */
  }

  const Node * get_goal() const
  {
#ifndef NDEBUG
    std::cerr << open.size() << " nodes in open at end of search" << std::endl
              << closed.size() << " nodes in closed at end of search" << std::endl;
#endif
    return goal;
  }

  const Domain & get_domain() const
  {
    return domain;
  }

  unsigned get_num_generated() const
  {
    return num_generated;
  }

  unsigned get_num_expanded() const
  {
    return num_expanded;
  }

private:
  bool all_closed_item_ptrs_valid() const
  {
    return true;
    std::cerr << "checking if item pointers are valid" << std::endl
              << "  " << closed.size() << " pointers to check" << std::endl;
    for (typename Closed::const_iterator closed_it = closed.begin();
         closed_it != closed.end();
         ++closed_it) {
      if ( closed_it->second && !open.valid_item_pointer(*closed_it->second) )
        return false;
    }
    return true;
  }

private:
  Open &open;
  Closed &closed;

  const Node * goal;
  const Domain &domain;

  unsigned num_expanded;
  unsigned num_generated;

private:
  AStar(const AStar<Domain, Node> &);
  AStar<Domain, Node> & operator =(const AStar<Domain, Node> &);
};

#endif /* !_A_STAR_HPP_ */
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#include "global_notifier.hpp"

#include "impl/realm_coordinator.hpp"
#include "impl/transact_log_handler.hpp"
#include "object_store.hpp"
#include "results.hpp"
#include "object_schema.hpp"
#include "util/event_loop_signal.hpp"

#include "sync/sync_config.hpp"
#include "sync/sync_manager.hpp"
#include "sync/sync_user.hpp"
#include "sync/sync_session.hpp"

#include <realm/util/file.hpp>
#include <realm/util/uri.hpp>
#include <realm/lang_bind_helper.hpp>

#include <regex>
#include <utility>
#include <stdexcept>
#include <vector>

using namespace realm;
using namespace realm::_impl;

AdminRealmListener::AdminRealmListener(std::string local_root, std::string server_base_url, std::shared_ptr<SyncUser> user)
{
    Realm::Config config;
    config.cache = false;
    config.path = util::File::resolve("__admin.realm", local_root);
    config.schema_mode = SchemaMode::Additive;
    config.sync_config = std::shared_ptr<SyncConfig>(
        new SyncConfig{user, server_base_url + "/__admin", SyncSessionStopPolicy::AfterChangesUploaded,
           [&](auto, const auto& config, auto session) {
                session->bind_with_admin_token(config.user->refresh_token(), config.realm_url);

           }}
    );
    config.schema = Schema{
        {"RealmFile", {
            {"path", PropertyType::String, Property::IsPrimary{true}, Property::IsIndexed{false}},
            {"creatorId", PropertyType::String, Property::IsPrimary{false}, Property::IsIndexed{false}},
            {"creationDate", PropertyType::Date, Property::IsPrimary{false}, Property::IsIndexed{false}},
            {"syncLabel", PropertyType::String, Property::IsPrimary{false}, Property::IsIndexed{false}}
        }}
    };
    config.schema_version = 2;
    m_realm = Realm::get_shared_realm(std::move(config));
}

void AdminRealmListener::start(std::function<void(std::vector<RealmInfo>)> callback)
{
    m_results = Results(m_realm, *ObjectStore::table_for_object_type(m_realm->read_group(), "RealmFile"));
    m_notification_token = m_results.add_notification_callback([=](CollectionChangeSet changes, std::exception_ptr) {
        auto& table = *ObjectStore::table_for_object_type(m_realm->read_group(), "RealmFile");
        size_t id_col_ndx   = table.get_column_index("creatorId");
        size_t name_col_ndx = table.get_column_index("path");
        std::vector<RealmInfo> realms;

        auto add_realm = [&](auto index) {
            std::string realm_path = table.get_string(name_col_ndx, index);
            realms.emplace_back(table.get_string(id_col_ndx, index), realm_path);
        };

        if (changes.empty()) {
            for (size_t i = 0, size = table.size(); i < size; ++i) {
                add_realm(i);
            }
        }
        else {
            for (auto i : changes.insertions.as_indexes()) {
                add_realm(i);
            }
        }

        if (realms.size()) {
            callback(std::move(realms));
        }
    });
}

void AdminRealmListener::create_realm(StringData realm_id, StringData realm_name)
{
    m_realm->begin_transaction();
    auto& table = *ObjectStore::table_for_object_type(m_realm->read_group(), "RealmFile");
    size_t row_ndx      = table.add_empty_row();
    size_t id_col_ndx   = table.get_column_index("creatorId");
    size_t name_col_ndx = table.get_column_index("path");
    table.set_string(id_col_ndx, row_ndx, realm_id);
    table.set_string(name_col_ndx, row_ndx, realm_name);
    m_realm->commit_transaction();
}
<commit_msg>Moving schema declaration to latest object store<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#include "global_notifier.hpp"

#include "impl/realm_coordinator.hpp"
#include "impl/transact_log_handler.hpp"
#include "object_store.hpp"
#include "results.hpp"
#include "object_schema.hpp"
#include "util/event_loop_signal.hpp"

#include "sync/sync_config.hpp"
#include "sync/sync_manager.hpp"
#include "sync/sync_user.hpp"
#include "sync/sync_session.hpp"

#include <realm/util/file.hpp>
#include <realm/util/uri.hpp>
#include <realm/lang_bind_helper.hpp>

#include <regex>
#include <utility>
#include <stdexcept>
#include <vector>

using namespace realm;
using namespace realm::_impl;

AdminRealmListener::AdminRealmListener(std::string local_root, std::string server_base_url, std::shared_ptr<SyncUser> user)
{
    Realm::Config config;
    config.cache = false;
    config.path = util::File::resolve("__admin.realm", local_root);
    config.schema_mode = SchemaMode::Additive;
    config.sync_config = std::shared_ptr<SyncConfig>(
        new SyncConfig{user, server_base_url + "/__admin", SyncSessionStopPolicy::AfterChangesUploaded,
           [&](auto, const auto& config, auto session) {
                session->bind_with_admin_token(config.user->refresh_token(), config.realm_url);

           }}
    );
    config.schema = Schema{
        {"RealmFile", {
            {"path", PropertyType::String, Property::IsPrimary{true}}},
            {"creatorId", PropertyType::String},
            {"creationDate", PropertyType::Date},
            {"syncLabel", PropertyType::String}
        }}
    };
    config.schema_version = 2;
    m_realm = Realm::get_shared_realm(std::move(config));
}

void AdminRealmListener::start(std::function<void(std::vector<RealmInfo>)> callback)
{
    m_results = Results(m_realm, *ObjectStore::table_for_object_type(m_realm->read_group(), "RealmFile"));
    m_notification_token = m_results.add_notification_callback([=](CollectionChangeSet changes, std::exception_ptr) {
        auto& table = *ObjectStore::table_for_object_type(m_realm->read_group(), "RealmFile");
        size_t id_col_ndx   = table.get_column_index("creatorId");
        size_t name_col_ndx = table.get_column_index("path");
        std::vector<RealmInfo> realms;

        auto add_realm = [&](auto index) {
            std::string realm_path = table.get_string(name_col_ndx, index);
            realms.emplace_back(table.get_string(id_col_ndx, index), realm_path);
        };

        if (changes.empty()) {
            for (size_t i = 0, size = table.size(); i < size; ++i) {
                add_realm(i);
            }
        }
        else {
            for (auto i : changes.insertions.as_indexes()) {
                add_realm(i);
            }
        }

        if (realms.size()) {
            callback(std::move(realms));
        }
    });
}

void AdminRealmListener::create_realm(StringData realm_id, StringData realm_name)
{
    m_realm->begin_transaction();
    auto& table = *ObjectStore::table_for_object_type(m_realm->read_group(), "RealmFile");
    size_t row_ndx      = table.add_empty_row();
    size_t id_col_ndx   = table.get_column_index("creatorId");
    size_t name_col_ndx = table.get_column_index("path");
    table.set_string(id_col_ndx, row_ndx, realm_id);
    table.set_string(name_col_ndx, row_ndx, realm_name);
    m_realm->commit_transaction();
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <Unittests/unittests_common.hh>

namespace {

class OpenMeshReadWriteOFF : public OpenMeshBase {

    protected:

        // This function is called before each test is run
        virtual void SetUp() {

            // Do some initial stuff with the member data here...
        }

        // This function is called after all tests are through
        virtual void TearDown() {

            // Do some final stuff with the member data here...
        }

    // Member already defined in OpenMeshBase
    //Mesh mesh_;
};

/*
 * ====================================================================
 * Define tests below
 * ====================================================================
 */

/*
 * Just load a simple mesh file in obj format and count whether
 * the right number of entities has been loaded.
 */
TEST_F(OpenMeshReadWriteOFF, LoadSimpleOFFFile) {

    mesh_.clear();

    bool ok = OpenMesh::IO::read_mesh(mesh_, "cube1.off");

    EXPECT_TRUE(ok);

    EXPECT_EQ(7526u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
    EXPECT_EQ(22572u, mesh_.n_edges()) << "The number of loaded edges is not correct!";
    EXPECT_EQ(15048u, mesh_.n_faces()) << "The number of loaded faces is not correct!";
}

TEST_F(OpenMeshReadWriteOFF, WriteAndReadVertexColorsToAndFromOFFFile) {

    mesh_.clear();

    mesh_.request_vertex_colors();

    mesh_.add_vertex( Mesh::Point(0,0,1) );
    mesh_.add_vertex( Mesh::Point(0,1,0) );
    mesh_.add_vertex( Mesh::Point(0,1,1) );
    mesh_.add_vertex( Mesh::Point(1,0,1) );

    // using the default color type Vec3uc from DefaultTraits in Traits.hh
    Mesh::Color testColor(255, 128, 64);

    // setting colors (different from black)
    for (Mesh::VertexIter vit = mesh_.vertices_begin(), vitend = mesh_.vertices_end(); vit != vitend; ++vit)
      mesh_.set_color(*vit, testColor);

    // check if the colors are correctly setted
    int count = 0;
    for (Mesh::VertexIter vit = mesh_.vertices_begin(), vitend = mesh_.vertices_end(); vit != vitend; ++vit) {
      Mesh::Color color = mesh_.color(*vit);
      if ( color[0] != testColor[0] || color[1] != testColor[1] || color[2] != testColor[2] )
        ++ count;
    }

    EXPECT_EQ(0, count) << "Vertices have the wrong color!";

    // write the mesh_
    OpenMesh::IO::Options opt(OpenMesh::IO::Options::VertexColor);
    OpenMesh::IO::write_mesh(mesh_, "temp.off", opt);
    OpenMesh::IO::read_mesh(mesh_, "temp.off", opt);

    // check if vertices still have the same color
    count = 0;
    for (Mesh::VertexIter vit = mesh_.vertices_begin(), vitend = mesh_.vertices_end(); vit != vitend; ++vit) {
      Mesh::Color color = mesh_.color(*vit);
      if ( color[0] != testColor[0] || color[1] != testColor[1] || color[2] != testColor[2] )
        ++ count;
    }

    EXPECT_EQ(0, count) << "Vertices should have the same color after writing and reading the OFF file!";

    mesh_.release_vertex_colors();
}

TEST_F(OpenMeshReadWriteOFF, WriteAndReadFloatVertexColorsToAndFromOFFFile) {

    mesh_.clear();

    mesh_.request_vertex_colors();

    OpenMesh::IO::Options opt(OpenMesh::IO::Options::VertexColor);

    bool ok = OpenMesh::IO::read_mesh(mesh_, "meshlab.ply", opt);

    EXPECT_TRUE(ok) << "meshlab.ply could not be read!";

    opt.clear();
    opt += OpenMesh::IO::Options::VertexColor;
    opt += OpenMesh::IO::Options::ColorFloat;

    // write the mesh_
    ok = OpenMesh::IO::write_mesh(mesh_, "cube_floating.off", opt);
    EXPECT_TRUE(ok) << "cube_floating.off could not be written!";
    mesh_.clear();
    ok = OpenMesh::IO::read_mesh(mesh_, "cube_floating.off", opt);
    EXPECT_TRUE(ok) << "cube_floating.off could not be read!";

    EXPECT_EQ(8u  , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
    EXPECT_EQ(18u , mesh_.n_edges())    << "The number of loaded edges is not correct!";
    EXPECT_EQ(12u , mesh_.n_faces())    << "The number of loaded faces is not correct!";

    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
    EXPECT_EQ(255,   mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";

    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
    EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";

    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
    EXPECT_EQ(255,   mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";

    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
    EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";

    EXPECT_FALSE(opt.vertex_has_normal()) << "Wrong user opt are returned!";
    EXPECT_FALSE(opt.vertex_has_texcoord()) << "Wrong user opt are returned!";
    EXPECT_TRUE(opt.vertex_has_color()) << "Wrong user opt are returned!";
    EXPECT_TRUE(opt.color_is_float()) << "Wrong user opt are returned!";

    mesh_.release_vertex_colors();
}

TEST_F(OpenMeshReadWriteOFF, WriteAndReadBinaryFloatVertexColorsToAndFromOFFFile) {

    mesh_.clear();

    mesh_.request_vertex_colors();

    OpenMesh::IO::Options opt(OpenMesh::IO::Options::VertexColor);

    bool ok = OpenMesh::IO::read_mesh(mesh_, "meshlab.ply", opt);

    EXPECT_TRUE(ok) << "meshlab.ply could not be read!";

    opt.clear();
    opt += OpenMesh::IO::Options::VertexColor;
    opt += OpenMesh::IO::Options::Binary;
    opt += OpenMesh::IO::Options::ColorFloat;

    // write the mesh_
    ok = OpenMesh::IO::write_mesh(mesh_, "cube_floating_binary.off", opt);
    EXPECT_TRUE(ok) << "cube_floating_binary.off could not be written!";
    mesh_.clear();
    opt.clear();
    opt += OpenMesh::IO::Options::VertexColor;
    opt += OpenMesh::IO::Options::Binary;
    opt += OpenMesh::IO::Options::ColorFloat;
    ok = OpenMesh::IO::read_mesh(mesh_, "cube_floating_binary.off", opt);
    EXPECT_TRUE(ok) << "cube_floating_binary.off could not be read!";

    EXPECT_EQ(8u  , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
    EXPECT_EQ(18u , mesh_.n_edges())    << "The number of loaded edges is not correct!";
    EXPECT_EQ(12u , mesh_.n_faces())    << "The number of loaded faces is not correct!";

    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
    EXPECT_EQ(255,   mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";

    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
    EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";

    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
    EXPECT_EQ(255,   mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";

    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
    EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";

    EXPECT_FALSE(opt.vertex_has_normal()) << "Wrong user opt are returned!";
    EXPECT_FALSE(opt.vertex_has_texcoord()) << "Wrong user opt are returned!";
    EXPECT_FALSE(opt.face_has_color()) << "Wrong user opt are returned!";
    EXPECT_TRUE(opt.vertex_has_color()) << "Wrong user opt are returned!";
    EXPECT_TRUE(opt.color_is_float()) << "Wrong user opt are returned!";
    EXPECT_TRUE(opt.is_binary()) << "Wrong user opt are returned!";

    mesh_.release_vertex_colors();
}
}
<commit_msg>cleanup off writer output file<commit_after>#include <gtest/gtest.h>
#include <Unittests/unittests_common.hh>
#include <cstdio>

namespace {

class OpenMeshReadWriteOFF : public OpenMeshBase {

    protected:

        // This function is called before each test is run
        virtual void SetUp() {

            // Do some initial stuff with the member data here...
        }

        // This function is called after all tests are through
        virtual void TearDown() {

            // Do some final stuff with the member data here...
        }

    // Member already defined in OpenMeshBase
    //Mesh mesh_;
};

/*
 * ====================================================================
 * Define tests below
 * ====================================================================
 */

/*
 * Just load a simple mesh file in obj format and count whether
 * the right number of entities has been loaded.
 */
TEST_F(OpenMeshReadWriteOFF, LoadSimpleOFFFile) {

    mesh_.clear();

    bool ok = OpenMesh::IO::read_mesh(mesh_, "cube1.off");

    EXPECT_TRUE(ok);

    EXPECT_EQ(7526u , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
    EXPECT_EQ(22572u, mesh_.n_edges()) << "The number of loaded edges is not correct!";
    EXPECT_EQ(15048u, mesh_.n_faces()) << "The number of loaded faces is not correct!";
}

TEST_F(OpenMeshReadWriteOFF, WriteAndReadVertexColorsToAndFromOFFFile) {

    mesh_.clear();

    mesh_.request_vertex_colors();

    mesh_.add_vertex( Mesh::Point(0,0,1) );
    mesh_.add_vertex( Mesh::Point(0,1,0) );
    mesh_.add_vertex( Mesh::Point(0,1,1) );
    mesh_.add_vertex( Mesh::Point(1,0,1) );

    // using the default color type Vec3uc from DefaultTraits in Traits.hh
    Mesh::Color testColor(255, 128, 64);

    // setting colors (different from black)
    for (Mesh::VertexIter vit = mesh_.vertices_begin(), vitend = mesh_.vertices_end(); vit != vitend; ++vit)
      mesh_.set_color(*vit, testColor);

    // check if the colors are correctly setted
    int count = 0;
    for (Mesh::VertexIter vit = mesh_.vertices_begin(), vitend = mesh_.vertices_end(); vit != vitend; ++vit) {
      Mesh::Color color = mesh_.color(*vit);
      if ( color[0] != testColor[0] || color[1] != testColor[1] || color[2] != testColor[2] )
        ++ count;
    }

    EXPECT_EQ(0, count) << "Vertices have the wrong color!";

    // write the mesh_
    OpenMesh::IO::Options opt(OpenMesh::IO::Options::VertexColor);
    OpenMesh::IO::write_mesh(mesh_, "temp.off", opt);
    OpenMesh::IO::read_mesh(mesh_, "temp.off", opt);
    remove("temp.off");

    // check if vertices still have the same color
    count = 0;
    for (Mesh::VertexIter vit = mesh_.vertices_begin(), vitend = mesh_.vertices_end(); vit != vitend; ++vit) {
      Mesh::Color color = mesh_.color(*vit);
      if ( color[0] != testColor[0] || color[1] != testColor[1] || color[2] != testColor[2] )
        ++ count;
    }

    EXPECT_EQ(0, count) << "Vertices should have the same color after writing and reading the OFF file!";

    mesh_.release_vertex_colors();
}

TEST_F(OpenMeshReadWriteOFF, WriteAndReadFloatVertexColorsToAndFromOFFFile) {

    mesh_.clear();

    mesh_.request_vertex_colors();

    OpenMesh::IO::Options opt(OpenMesh::IO::Options::VertexColor);

    bool ok = OpenMesh::IO::read_mesh(mesh_, "meshlab.ply", opt);

    EXPECT_TRUE(ok) << "meshlab.ply could not be read!";

    opt.clear();
    opt += OpenMesh::IO::Options::VertexColor;
    opt += OpenMesh::IO::Options::ColorFloat;

    // write the mesh_
    ok = OpenMesh::IO::write_mesh(mesh_, "cube_floating.off", opt);
    EXPECT_TRUE(ok) << "cube_floating.off could not be written!";
    mesh_.clear();
    ok = OpenMesh::IO::read_mesh(mesh_, "cube_floating.off", opt);
    EXPECT_TRUE(ok) << "cube_floating.off could not be read!";

    EXPECT_EQ(8u  , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
    EXPECT_EQ(18u , mesh_.n_edges())    << "The number of loaded edges is not correct!";
    EXPECT_EQ(12u , mesh_.n_faces())    << "The number of loaded faces is not correct!";

    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
    EXPECT_EQ(255,   mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";

    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
    EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";

    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
    EXPECT_EQ(255,   mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";

    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
    EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";

    EXPECT_FALSE(opt.vertex_has_normal()) << "Wrong user opt are returned!";
    EXPECT_FALSE(opt.vertex_has_texcoord()) << "Wrong user opt are returned!";
    EXPECT_TRUE(opt.vertex_has_color()) << "Wrong user opt are returned!";
    EXPECT_TRUE(opt.color_is_float()) << "Wrong user opt are returned!";

    mesh_.release_vertex_colors();
}

TEST_F(OpenMeshReadWriteOFF, WriteAndReadBinaryFloatVertexColorsToAndFromOFFFile) {

    mesh_.clear();

    mesh_.request_vertex_colors();

    OpenMesh::IO::Options opt(OpenMesh::IO::Options::VertexColor);

    bool ok = OpenMesh::IO::read_mesh(mesh_, "meshlab.ply", opt);

    EXPECT_TRUE(ok) << "meshlab.ply could not be read!";

    opt.clear();
    opt += OpenMesh::IO::Options::VertexColor;
    opt += OpenMesh::IO::Options::Binary;
    opt += OpenMesh::IO::Options::ColorFloat;

    // write the mesh_
    ok = OpenMesh::IO::write_mesh(mesh_, "cube_floating_binary.off", opt);
    EXPECT_TRUE(ok) << "cube_floating_binary.off could not be written!";
    mesh_.clear();
    opt.clear();
    opt += OpenMesh::IO::Options::VertexColor;
    opt += OpenMesh::IO::Options::Binary;
    opt += OpenMesh::IO::Options::ColorFloat;
    ok = OpenMesh::IO::read_mesh(mesh_, "cube_floating_binary.off", opt);
    EXPECT_TRUE(ok) << "cube_floating_binary.off could not be read!";

    EXPECT_EQ(8u  , mesh_.n_vertices()) << "The number of loaded vertices is not correct!";
    EXPECT_EQ(18u , mesh_.n_edges())    << "The number of loaded edges is not correct!";
    EXPECT_EQ(12u , mesh_.n_faces())    << "The number of loaded faces is not correct!";

    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(0))[0] ) << "Wrong vertex color at vertex 0 component 0";
    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(0))[1] ) << "Wrong vertex color at vertex 0 component 1";
    EXPECT_EQ(255,   mesh_.color(mesh_.vertex_handle(0))[2] ) << "Wrong vertex color at vertex 0 component 2";

    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(3))[0] ) << "Wrong vertex color at vertex 3 component 0";
    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(3))[1] ) << "Wrong vertex color at vertex 3 component 1";
    EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(3))[2] ) << "Wrong vertex color at vertex 3 component 2";

    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(4))[0] ) << "Wrong vertex color at vertex 4 component 0";
    EXPECT_EQ(0,   mesh_.color(mesh_.vertex_handle(4))[1] ) << "Wrong vertex color at vertex 4 component 1";
    EXPECT_EQ(255,   mesh_.color(mesh_.vertex_handle(4))[2] ) << "Wrong vertex color at vertex 4 component 2";

    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[0] ) << "Wrong vertex color at vertex 7 component 0";
    EXPECT_EQ(0, mesh_.color(mesh_.vertex_handle(7))[1] ) << "Wrong vertex color at vertex 7 component 1";
    EXPECT_EQ(255, mesh_.color(mesh_.vertex_handle(7))[2] ) << "Wrong vertex color at vertex 7 component 2";

    EXPECT_FALSE(opt.vertex_has_normal()) << "Wrong user opt are returned!";
    EXPECT_FALSE(opt.vertex_has_texcoord()) << "Wrong user opt are returned!";
    EXPECT_FALSE(opt.face_has_color()) << "Wrong user opt are returned!";
    EXPECT_TRUE(opt.vertex_has_color()) << "Wrong user opt are returned!";
    EXPECT_TRUE(opt.color_is_float()) << "Wrong user opt are returned!";
    EXPECT_TRUE(opt.is_binary()) << "Wrong user opt are returned!";

    mesh_.release_vertex_colors();
}
}
<|endoftext|>


<commit_before><commit_msg>fixed filesystem unit tests<commit_after><|endoftext|>


<commit_before>#include "Button.hpp"
#include "Utils/Math.hpp"

av::ui::Button::Button(const sf::Vector2f l_size, const sf::Vector2f l_position)
	: m_click_callback_(nullptr),
	m_enter_callback_(nullptr), m_exit_callback_(nullptr), m_background_(l_size)
{
	m_inited_ = false;
	Init(l_size, l_position, 30, sf::Color::Green, sf::Color::White, "Button");
}

av::ui::Button::Button(const sf::Vector2f l_size, const sf::Vector2f l_position,
                       const sf::Color l_button_color, const sf::Color l_text_color,
                       const sf::String l_title, const sf::Uint32 l_text_size)
	: m_click_callback_(nullptr),
	m_enter_callback_(nullptr), m_exit_callback_(nullptr), m_background_(l_size)
{
	m_inited_ = false;
	Init(l_size, l_position, l_text_size, l_button_color, l_text_color, l_title);
}

void av::ui::Button::Init(const sf::Vector2f l_size,
						  const sf::Vector2f l_position,
                          const sf::Uint32 l_text_size,
						  const sf::Color l_button_color,
						  const sf::Color l_text_color,
                          const sf::String l_text)
{
	this->m_font_.loadFromFile("titillium.otf");

	this->m_text_.setFont(this->m_font_);
	this->m_text_.setString(l_text);
	this->m_text_.setCharacterSize(l_text_size);
	this->m_text_.setFillColor(l_text_color);
	this->m_text_.setPosition(utils::Math::getCenterCoordinates(l_position, l_size, m_text_.getLocalBounds()));

	this->m_background_.setFillColor(l_button_color);
	this->m_background_.setPosition(l_position);
	this->m_inited_ = true;
}

void av::ui::Button::setFont(const sf::Font l_font)
{
	this->m_text_.setFont(l_font);
}

void av::ui::Button::setTextSize(const sf::Uint32 l_size)
{
	this->m_text_.setCharacterSize(l_size);
}

void av::ui::Button::setText(const sf::String l_text)
{
	this->m_text_.setString(l_text);
}

void av::ui::Button::setTextColor(const sf::Color l_color)
{
	this->m_text_.setFillColor(l_color);
}

void av::ui::Button::setTextBackgroundColor(const sf::Color l_color)
{
	this->m_text_.setOutlineColor(l_color);
}

void av::ui::Button::setTextAlignment(enums::TextAlignment l_alignment)
{
	//TODO(Nuno): Think about how to implement this

	//auto position = utils::Math::getCenterCoordinates();

	//this->m_text_.setPosition(position);
}

void av::ui::Button::setBackgroundColor(const sf::Color l_color)
{
	this->m_background_.setFillColor(l_color);
}

void av::ui::Button::setBackgroundOutlineColor(const sf::Color l_color)
{
	this->m_background_.setOutlineColor(l_color);
}

void av::ui::Button::setBackgroundOutlineThickness(const float l_tickness)
{
	this->m_background_.setOutlineThickness(l_tickness);
}

void av::ui::Button::setOnClick(events::MouseClickCallback* l_callback)
{
	this->m_click_callback_ = l_callback;
}

void av::ui::Button::setOnMouseEnter(events::MouseOverEnterCallback* l_callback)
{
	this->m_enter_callback_ = l_callback;
}

void av::ui::Button::setOnMouseExit(events::MouseOverExitCallback* l_callback)
{
	this->m_exit_callback_ = l_callback;
}

void av::ui::Button::onClick() const
{
	if(this->m_click_callback_ != nullptr)
	{
		this->m_click_callback_->Execute();
	}
	else
	{
		throw "callback is nullptr";
	}
}

void av::ui::Button::Update(float timestep)
{
	if(this->m_inited_)
	{

	}
}

void av::ui::Button::Render(sf::RenderWindow& l_window)
{
	if(this->m_inited_)
	{
		l_window.draw(this->m_background_);
		l_window.draw(this->m_text_);
	}
}

sf::FloatRect av::ui::Button::GetGlobalBounds()
{
	return this->m_background_.getGlobalBounds();
}

<commit_msg>Fixed button not centering after text changed<commit_after>#include "Button.hpp"
#include "Utils/Math.hpp"

av::ui::Button::Button(const sf::Vector2f l_size, const sf::Vector2f l_position)
	: m_click_callback_(nullptr),
	m_enter_callback_(nullptr), m_exit_callback_(nullptr), m_background_(l_size)
{
	m_inited_ = false;
	Init(l_size, l_position, 30, sf::Color::Green, sf::Color::White, "Button");
}

av::ui::Button::Button(const sf::Vector2f l_size, const sf::Vector2f l_position,
                       const sf::Color l_button_color, const sf::Color l_text_color,
                       const sf::String l_title, const sf::Uint32 l_text_size)
	: m_click_callback_(nullptr),
	m_enter_callback_(nullptr), m_exit_callback_(nullptr), m_background_(l_size)
{
	m_inited_ = false;
	Init(l_size, l_position, l_text_size, l_button_color, l_text_color, l_title);
}

void av::ui::Button::Init(const sf::Vector2f l_size,
						  const sf::Vector2f l_position,
                          const sf::Uint32 l_text_size,
						  const sf::Color l_button_color,
						  const sf::Color l_text_color,
                          const sf::String l_text)
{
	this->m_font_.loadFromFile("titillium.otf");

	this->m_text_.setFont(this->m_font_);
	this->m_text_.setString(l_text);
	this->m_text_.setCharacterSize(l_text_size);
	this->m_text_.setFillColor(l_text_color);
	this->m_text_.setPosition(utils::Math::getCenterCoordinates(l_position, l_size, m_text_.getLocalBounds()));

	this->m_background_.setFillColor(l_button_color);
	this->m_background_.setPosition(l_position);
	this->m_inited_ = true;
}

void av::ui::Button::setFont(const sf::Font l_font)
{
	this->m_text_.setFont(l_font);
}

void av::ui::Button::setTextSize(const sf::Uint32 l_size)
{
	this->m_text_.setCharacterSize(l_size);
}

void av::ui::Button::setText(const sf::String l_text)
{
	this->m_text_.setString(l_text);
	//Experimenting
	this->m_text_.setPosition(utils::Math::getCenterCoordinates(this->m_background_.getPosition(),
		this->m_background_.getSize(), this->m_text_.getLocalBounds()));
}

void av::ui::Button::setTextColor(const sf::Color l_color)
{
	this->m_text_.setFillColor(l_color);
}

void av::ui::Button::setTextBackgroundColor(const sf::Color l_color)
{
	this->m_text_.setOutlineColor(l_color);
}

void av::ui::Button::setTextAlignment(enums::TextAlignment l_alignment)
{
	//TODO(Nuno): Think about how to implement this

	//auto position = utils::Math::getCenterCoordinates();

	//this->m_text_.setPosition(position);
}

void av::ui::Button::setBackgroundColor(const sf::Color l_color)
{
	this->m_background_.setFillColor(l_color);
}

void av::ui::Button::setBackgroundOutlineColor(const sf::Color l_color)
{
	this->m_background_.setOutlineColor(l_color);
}

void av::ui::Button::setBackgroundOutlineThickness(const float l_tickness)
{
	this->m_background_.setOutlineThickness(l_tickness);
}

void av::ui::Button::setOnClick(events::MouseClickCallback* l_callback)
{
	this->m_click_callback_ = l_callback;
}

void av::ui::Button::setOnMouseEnter(events::MouseOverEnterCallback* l_callback)
{
	this->m_enter_callback_ = l_callback;
}

void av::ui::Button::setOnMouseExit(events::MouseOverExitCallback* l_callback)
{
	this->m_exit_callback_ = l_callback;
}

void av::ui::Button::onClick() const
{
	if(this->m_click_callback_ != nullptr)
	{
		this->m_click_callback_->Execute();
	}
	else
	{
		throw "callback is nullptr";
	}
}

void av::ui::Button::Update(float timestep)
{
	if(this->m_inited_)
	{

	}
}

void av::ui::Button::Render(sf::RenderWindow& l_window)
{
	if(this->m_inited_)
	{
		l_window.draw(this->m_background_);
		l_window.draw(this->m_text_);
	}
}

sf::FloatRect av::ui::Button::GetGlobalBounds()
{
	return this->m_background_.getGlobalBounds();
}

<|endoftext|>


<commit_before>#include "parlex/details/wirth.hpp"

#include "parlex/builtins.hpp"
#include "parlex/parser.hpp"

#include "utils.hpp"
#include "parlex/builder.hpp"
#include "utf.hpp"
#include <iostream>

namespace parlex {
namespace details {

erased<builder::node> wirth_t::process_factor2(std::u32string const & document, match const & factor, abstract_syntax_graph const & asg) {
	permutation const & p = *asg.permutations.find(factor)->second.begin();
	auto i = p.begin();
	std::string tag;
	if (&i->r == &dollarSign) {
		++i;
		if (&i->r == &identifierDfa) {
			tag = to_utf8(document.substr(i->document_position, i->consumed_character_count));
		} else if (&i->r == &builtins.c_string) {
			tag = to_utf8(builtins.c_string.extract(document, *i, asg));
		} else {
			throw;
		}
	}

	if (&i->r == &tagDfa) {
		permutation const & q = *asg.permutations.find(*i)->second.begin();
		match const & j = q[1];
		++i;
		throw_assert(&j.r == &identifierDfa);
		tag = to_utf8(document.substr(j.document_position, j.consumed_character_count));
	}

	std::unique_ptr<erased<builder::node>> result;
	auto set = [&result](erased<builder::node> const & node) { result.reset(new erased<builder::node>(node)); };
	if (&i->r == &identifierDfa) {
		std::string name = to_utf8(document.substr(i->document_position, i->consumed_character_count));
		set(builder::reference(name));
	} else if (&i->r == &builtins.c_string) {
		std::u32string text = builtins.c_string.extract(document, *i, asg);
		set(builder::literal(text));
	} else if (&i->r == &parentheticalDfa) {
		permutation const & q = *asg.permutations.find(*i)->second.begin();
		auto j = q.begin();
		auto parenthetical_type = &j->r;
		while (&j->r != &expressionDfa) {
			++j;
		}
		if (parenthetical_type == &openSquare) {
			set(builder::optional_t(process_expression2(document, *j, asg)));
		} else if (parenthetical_type == &openCurly) {
			set(builder::repetition_t(process_expression2(document, *j, asg)));
		} else if (parenthetical_type == &openParen) {
			set(process_expression2(document, *j, asg));
		} else {
			throw;
		}
	} else {
		throw;
	}

	if (tag != "") {
		(*result)->tag = tag;
	}
	return *result;
}

erased<builder::node> wirth_t::process_term2(std::u32string const & document, match const & term, abstract_syntax_graph const & asg) {
	std::vector<match> factors;

	permutation const & p = *(*asg.permutations.find(term)).second.begin();
	for (match const & entry : p) {
		if (&entry.r == &factorDfa) {
			factors.push_back(entry);
		}
	}
	if (factors.size() == 1) {
		return process_factor2(document, factors[0], asg);
	}
	builder::sequence_t result;
	for (match const & factor : factors) {
		result.children.push_back(process_factor2(document, factor, asg));
	}
	return result;
}

erased<builder::node> wirth_t::process_expression2(std::u32string const & document, match const & expression, abstract_syntax_graph const & asg) {
	std::vector<match> terms;

	permutation const & p = *(*asg.permutations.find(expression)).second.begin();
	for (match const & entry : p) {
		if (&entry.r == &termDfa) {
			terms.push_back(entry);
		}
	}
	if (terms.size() == 1) {
		return process_term2(document, terms[0], asg);
	}
	builder::choice_t result;
	for (match const & term : terms) {
		result.children.push_back(process_term2(document, term, asg));
	}
	return result;
}

erased<builder::node> wirth_t::compile_expression(std::u32string const & source) {
	auto progressHandler = [](size_t completed, size_t total) {
		std::cout << completed << "/" << total << std::endl;
	};
	auto asg = p.parse(*this, expressionDfa, source, progressHandler);
	if (!asg.is_rooted()) {
		throw std::runtime_error("could not parse expression");
	}
	if (asg.variation_count() > 1) {
		throw std::runtime_error("more than one interpretation of the source");
	}
	//auto test = asg.to_dot(); //TODO: Make sure this is commented out
	return process_expression2(source, asg.root, asg);
}

#if 0 //to move
builder::grammar wirth_t::load_grammar(std::string const & rootId, std::map<std::string, production> const & definitions) {

	std::set<std::string> names;
	std::vector<correlated_state_machine_info> infos;
	for (auto const & definitionEntry : definitions) {
		std::string const & name = definitionEntry.first;
		production const & def = definitionEntry.second;
		auto res = names.insert(name);
		if (!res.second) {
			throw std::exception(("duplicate reference ID " + name).c_str());
		}
		infos.emplace_back(name, def.filter, def.assoc);
	}
	std::unique_ptr<correlated_grammar> result(new correlated_grammar(p.builtins, rootId, infos, [this, &definitions](std::string const & id, correlated_grammar & g) {
	                                              return compile_expression(definitions.find(id)->second.source, g);
                                              }));
	return result;
}
#endif

builder::grammar wirth_t::load_grammar(std::string const & rootId, std::map<std::string, production> const & definitions) {
	std::set<std::string> names;
	builder::grammar result;
	result.root_id = rootId;
	for (auto const & entry : definitions) {
		auto const & id = entry.first;
		auto const & definition = entry.second;
		auto res = names.insert(entry.first);
		if (!res.second) {
			throw std::runtime_error(("duplicate reference ID " + id).c_str());
		}
		std::cout << id << "\n";
		builder::production resultDefinition(id, compile_expression(definition.source), definition.assoc, definition.filter, definition.precedences);
		resultDefinition.id = id;
		resultDefinition.behavior = compile_expression(definition.source);
		resultDefinition.assoc = definition.assoc;
		resultDefinition.filter = definition.filter;
		result.productions.push_back(resultDefinition);
	}
	return result;
}

builder::grammar wirth_t::load_grammar(std::string const & rootId, std::u32string const & document, std::map<std::string, associativity> const & associativities, std::set<std::string> const & longestNames) {
	std::set<std::u32string> names;
	abstract_syntax_graph asg = p.parse(*this, document);
	throw_assert(asg.is_rooted());
	std::map<std::string, production> definitions;
	//std::string check = asg.to_dot();
	permutation const & top = *asg.permutations[asg.root].begin();
	for (match const & entry : top) {
		if (&entry.r == &productionDfa) {
			match const & namePart = (*asg.permutations[entry].begin())[0];
			std::u32string const u32Name = document.substr(namePart.document_position, namePart.consumed_character_count);
			std::string const name = to_utf8(u32Name);
			auto res = names.insert(u32Name);
			if (!res.second) {
				throw std::runtime_error(("duplicate reference ID " + name).c_str());
			}
			std::u32string source;
			for (match const & entry2 : *(*asg.permutations.find(entry)).second.begin()) {
				if (&entry2.r == &expressionDfa) {
					source = document.substr(entry2.document_position, entry2.consumed_character_count);
					break;
				}
			}
			auto assoc = associativities.count(name) > 0 ? associativities.find(name)->second : associativity::none;
			auto filter = longestNames.count(name) > 0 ? builtins.longest : filter_function();
			definitions.emplace(std::piecewise_construct, forward_as_tuple(name), forward_as_tuple(source, assoc, filter, std::set<std::string>()));
		}
	}
	return load_grammar(rootId, definitions);
}

wirth_t::production::production(std::u32string const & source, associativity assoc, filter_function filter, std::set<std::string> const & precedences) : source(source), assoc(assoc), filter(filter), precedences(precedences) {
}

builder::grammar generate_wirth(builtins_t const & builtins) {
	using namespace builder;
	return grammar("root", {
		               production("whiteSpace", sequence({
			                          reference("white_space"),
			                          repetition(reference("white_space"))}),
		                          associativity::none, builtins.longest
		               ),

		               production("comment", sequence({
			                          literal("#"),
			                          repetition(reference("not_newline")),
			                          literal("\n")
		                          })),

		               production("identifier", sequence({
			                          choice({reference("letter"), literal("_")}),
			                          repetition(choice({reference("letter"), literal("_"), reference("decimal_digit")}))
		                          }),
		                          associativity::none, builtins.longest),

		               production("production", sequence({
			                          reference("identifier"),
			                          optional(reference("whiteSpace")),
			                          literal(U"="),
			                          optional(reference("whiteSpace")),
			                          reference("expression"),
			                          optional(reference("whiteSpace")),
			                          literal(U".")
		                          })),

		               production("expression", sequence({
			                          reference("term"),
			                          repetition(sequence({
				                          optional(reference("whiteSpace")),
				                          literal("|"),
				                          optional(reference("whiteSpace")),
				                          reference("term")
			                          }))
		                          })),

		               production("term", sequence({
			                          reference("factor"),
			                          repetition(sequence({
				                          optional(reference("whiteSpace")),
				                          reference("factor")
			                          }))
		                          })),

		               production("parenthetical", choice({
			                          sequence({
				                          literal("["), optional(reference("whiteSpace")), reference("expression"), optional(reference("whiteSpace")), literal("]")
			                          }),
			                          sequence({
				                          literal("("), optional(reference("whiteSpace")), reference("expression"), optional(reference("whiteSpace")), literal(")")
			                          }),
			                          sequence({
				                          literal("{"), optional(reference("whiteSpace")), reference("expression"), optional(reference("whiteSpace")), literal("}")
			                          })
		                          })),

		               production("tag", sequence({literal("%"), reference("identifier")})),

		               production("factor", choice({
			                          sequence({optional(literal("$")), reference("identifier")}),
			                          sequence({optional(literal("$")), reference("c_string")}),
			                          sequence({optional(reference("tag")), reference("parenthetical")})
		                          }), associativity::none, filter_function(), {"factor"}),

		               production("root", repetition(choice({
			                          reference("production"),
			                          reference("comment"),
			                          reference("whiteSpace")
		                          })))
	               });

}

static correlated_state_machine const & convert(state_machine_base const & s) {
	return *static_cast<correlated_state_machine const *>(&s);
}

wirth_t::wirth_t(parser & p) : correlated_grammar(p.builtins, generate_wirth(p.builtins)), p(p),
                               openSquare(get_literal("[")),
                               openParen(get_literal("(")),
                               openCurly(get_literal("{")),
                               dollarSign(get_literal("$")),

                               productionDfa(convert(get_state_machine("production"))),
                               expressionDfa(convert(get_state_machine("expression"))),
                               termDfa(convert(get_state_machine("term"))),
                               parentheticalDfa(convert(get_state_machine("parenthetical"))),
                               tagDfa(convert(get_state_machine("tag"))),
                               factorDfa(convert(get_state_machine("factor"))),
                               identifierDfa(convert(get_state_machine("identifier"))) {
	std::string check = termDfa.to_dot();

}

erased<builder::node> wirth_t::process_production2(std::u32string const & document, match const & production, abstract_syntax_graph const & asg) {
	for (match const & entry : *(*asg.permutations.find(production)).second.begin()) {
		if (&entry.r == &expressionDfa) {
			return process_expression2(document, entry, asg);
		}
	}
	throw;
}

} //namespace details
} //namespace parlex
<commit_msg>use builtins::progress_bar in wirth_t::compile_expression<commit_after>#include "parlex/details/wirth.hpp"

#include "parlex/builtins.hpp"
#include "parlex/parser.hpp"

#include "utils.hpp"
#include "parlex/builder.hpp"
#include "utf.hpp"
#include <iostream>

namespace parlex {
namespace details {

erased<builder::node> wirth_t::process_factor2(std::u32string const & document, match const & factor, abstract_syntax_graph const & asg) {
	permutation const & p = *asg.permutations.find(factor)->second.begin();
	auto i = p.begin();
	std::string tag;
	if (&i->r == &dollarSign) {
		++i;
		if (&i->r == &identifierDfa) {
			tag = to_utf8(document.substr(i->document_position, i->consumed_character_count));
		} else if (&i->r == &builtins.c_string) {
			tag = to_utf8(builtins.c_string.extract(document, *i, asg));
		} else {
			throw;
		}
	}

	if (&i->r == &tagDfa) {
		permutation const & q = *asg.permutations.find(*i)->second.begin();
		match const & j = q[1];
		++i;
		throw_assert(&j.r == &identifierDfa);
		tag = to_utf8(document.substr(j.document_position, j.consumed_character_count));
	}

	std::unique_ptr<erased<builder::node>> result;
	auto set = [&result](erased<builder::node> const & node) { result.reset(new erased<builder::node>(node)); };
	if (&i->r == &identifierDfa) {
		std::string name = to_utf8(document.substr(i->document_position, i->consumed_character_count));
		set(builder::reference(name));
	} else if (&i->r == &builtins.c_string) {
		std::u32string text = builtins.c_string.extract(document, *i, asg);
		set(builder::literal(text));
	} else if (&i->r == &parentheticalDfa) {
		permutation const & q = *asg.permutations.find(*i)->second.begin();
		auto j = q.begin();
		auto parenthetical_type = &j->r;
		while (&j->r != &expressionDfa) {
			++j;
		}
		if (parenthetical_type == &openSquare) {
			set(builder::optional_t(process_expression2(document, *j, asg)));
		} else if (parenthetical_type == &openCurly) {
			set(builder::repetition_t(process_expression2(document, *j, asg)));
		} else if (parenthetical_type == &openParen) {
			set(process_expression2(document, *j, asg));
		} else {
			throw;
		}
	} else {
		throw;
	}

	if (tag != "") {
		(*result)->tag = tag;
	}
	return *result;
}

erased<builder::node> wirth_t::process_term2(std::u32string const & document, match const & term, abstract_syntax_graph const & asg) {
	std::vector<match> factors;

	permutation const & p = *(*asg.permutations.find(term)).second.begin();
	for (match const & entry : p) {
		if (&entry.r == &factorDfa) {
			factors.push_back(entry);
		}
	}
	if (factors.size() == 1) {
		return process_factor2(document, factors[0], asg);
	}
	builder::sequence_t result;
	for (match const & factor : factors) {
		result.children.push_back(process_factor2(document, factor, asg));
	}
	return result;
}

erased<builder::node> wirth_t::process_expression2(std::u32string const & document, match const & expression, abstract_syntax_graph const & asg) {
	std::vector<match> terms;

	permutation const & p = *(*asg.permutations.find(expression)).second.begin();
	for (match const & entry : p) {
		if (&entry.r == &termDfa) {
			terms.push_back(entry);
		}
	}
	if (terms.size() == 1) {
		return process_term2(document, terms[0], asg);
	}
	builder::choice_t result;
	for (match const & term : terms) {
		result.children.push_back(process_term2(document, term, asg));
	}
	return result;
}

erased<builder::node> wirth_t::compile_expression(std::u32string const & source) {
	auto asg = p.parse(*this, expressionDfa, source, p.builtins.progress_bar);
	if (!asg.is_rooted()) {
		throw std::runtime_error("could not parse expression");
	}
	if (asg.variation_count() > 1) {
		throw std::runtime_error("more than one interpretation of the source");
	}
	//auto test = asg.to_dot(); //TODO: Make sure this is commented out
	return process_expression2(source, asg.root, asg);
}

#if 0 //to move
builder::grammar wirth_t::load_grammar(std::string const & rootId, std::map<std::string, production> const & definitions) {

	std::set<std::string> names;
	std::vector<correlated_state_machine_info> infos;
	for (auto const & definitionEntry : definitions) {
		std::string const & name = definitionEntry.first;
		production const & def = definitionEntry.second;
		auto res = names.insert(name);
		if (!res.second) {
			throw std::exception(("duplicate reference ID " + name).c_str());
		}
		infos.emplace_back(name, def.filter, def.assoc);
	}
	std::unique_ptr<correlated_grammar> result(new correlated_grammar(p.builtins, rootId, infos, [this, &definitions](std::string const & id, correlated_grammar & g) {
	                                              return compile_expression(definitions.find(id)->second.source, g);
                                              }));
	return result;
}
#endif

builder::grammar wirth_t::load_grammar(std::string const & rootId, std::map<std::string, production> const & definitions) {
	std::set<std::string> names;
	builder::grammar result;
	result.root_id = rootId;
	for (auto const & entry : definitions) {
		auto const & id = entry.first;
		auto const & definition = entry.second;
		auto res = names.insert(entry.first);
		if (!res.second) {
			throw std::runtime_error(("duplicate reference ID " + id).c_str());
		}
		std::cout << "\n" << id << "\n";
		builder::production resultDefinition(id, compile_expression(definition.source), definition.assoc, definition.filter, definition.precedences);
		resultDefinition.id = id;
		resultDefinition.assoc = definition.assoc;
		resultDefinition.filter = definition.filter;
		result.productions.push_back(resultDefinition);
	}
	return result;
}

builder::grammar wirth_t::load_grammar(std::string const & rootId, std::u32string const & document, std::map<std::string, associativity> const & associativities, std::set<std::string> const & longestNames) {
	std::set<std::u32string> names;
	abstract_syntax_graph asg = p.parse(*this, document);
	throw_assert(asg.is_rooted());
	std::map<std::string, production> definitions;
	//std::string check = asg.to_dot();
	permutation const & top = *asg.permutations[asg.root].begin();
	for (match const & entry : top) {
		if (&entry.r == &productionDfa) {
			match const & namePart = (*asg.permutations[entry].begin())[0];
			std::u32string const u32Name = document.substr(namePart.document_position, namePart.consumed_character_count);
			std::string const name = to_utf8(u32Name);
			auto res = names.insert(u32Name);
			if (!res.second) {
				throw std::runtime_error(("duplicate reference ID " + name).c_str());
			}
			std::u32string source;
			for (match const & entry2 : *(*asg.permutations.find(entry)).second.begin()) {
				if (&entry2.r == &expressionDfa) {
					source = document.substr(entry2.document_position, entry2.consumed_character_count);
					break;
				}
			}
			auto assoc = associativities.count(name) > 0 ? associativities.find(name)->second : associativity::none;
			auto filter = longestNames.count(name) > 0 ? builtins.longest : filter_function();
			definitions.emplace(std::piecewise_construct, forward_as_tuple(name), forward_as_tuple(source, assoc, filter, std::set<std::string>()));
		}
	}
	return load_grammar(rootId, definitions);
}

wirth_t::production::production(std::u32string const & source, associativity assoc, filter_function filter, std::set<std::string> const & precedences) : source(source), assoc(assoc), filter(filter), precedences(precedences) {
}

builder::grammar generate_wirth(builtins_t const & builtins) {
	using namespace builder;
	return grammar("root", {
		               production("whiteSpace", sequence({
			                          reference("white_space"),
			                          repetition(reference("white_space"))}),
		                          associativity::none, builtins.longest
		               ),

		               production("comment", sequence({
			                          literal("#"),
			                          repetition(reference("not_newline")),
			                          literal("\n")
		                          })),

		               production("identifier", sequence({
			                          choice({reference("letter"), literal("_")}),
			                          repetition(choice({reference("letter"), literal("_"), reference("decimal_digit")}))
		                          }),
		                          associativity::none, builtins.longest),

		               production("production", sequence({
			                          reference("identifier"),
			                          optional(reference("whiteSpace")),
			                          literal(U"="),
			                          optional(reference("whiteSpace")),
			                          reference("expression"),
			                          optional(reference("whiteSpace")),
			                          literal(U".")
		                          })),

		               production("expression", sequence({
			                          reference("term"),
			                          repetition(sequence({
				                          optional(reference("whiteSpace")),
				                          literal("|"),
				                          optional(reference("whiteSpace")),
				                          reference("term")
			                          }))
		                          })),

		               production("term", sequence({
			                          reference("factor"),
			                          repetition(sequence({
				                          optional(reference("whiteSpace")),
				                          reference("factor")
			                          }))
		                          })),

		               production("parenthetical", choice({
			                          sequence({
				                          literal("["), optional(reference("whiteSpace")), reference("expression"), optional(reference("whiteSpace")), literal("]")
			                          }),
			                          sequence({
				                          literal("("), optional(reference("whiteSpace")), reference("expression"), optional(reference("whiteSpace")), literal(")")
			                          }),
			                          sequence({
				                          literal("{"), optional(reference("whiteSpace")), reference("expression"), optional(reference("whiteSpace")), literal("}")
			                          })
		                          })),

		               production("tag", sequence({literal("%"), reference("identifier")})),

		               production("factor", choice({
			                          sequence({optional(literal("$")), reference("identifier")}),
			                          sequence({optional(literal("$")), reference("c_string")}),
			                          sequence({optional(reference("tag")), reference("parenthetical")})
		                          }), associativity::none, filter_function(), {"factor"}),

		               production("root", repetition(choice({
			                          reference("production"),
			                          reference("comment"),
			                          reference("whiteSpace")
		                          })))
	               });

}

static correlated_state_machine const & convert(state_machine_base const & s) {
	return *static_cast<correlated_state_machine const *>(&s);
}

wirth_t::wirth_t(parser & p) : correlated_grammar(p.builtins, generate_wirth(p.builtins)), p(p),
                               openSquare(get_literal("[")),
                               openParen(get_literal("(")),
                               openCurly(get_literal("{")),
                               dollarSign(get_literal("$")),

                               productionDfa(convert(get_state_machine("production"))),
                               expressionDfa(convert(get_state_machine("expression"))),
                               termDfa(convert(get_state_machine("term"))),
                               parentheticalDfa(convert(get_state_machine("parenthetical"))),
                               tagDfa(convert(get_state_machine("tag"))),
                               factorDfa(convert(get_state_machine("factor"))),
                               identifierDfa(convert(get_state_machine("identifier"))) {
	std::string check = termDfa.to_dot();

}

erased<builder::node> wirth_t::process_production2(std::u32string const & document, match const & production, abstract_syntax_graph const & asg) {
	for (match const & entry : *(*asg.permutations.find(production)).second.begin()) {
		if (&entry.r == &expressionDfa) {
			return process_expression2(document, entry, asg);
		}
	}
	throw;
}

} //namespace details
} //namespace parlex
<|endoftext|>


<commit_before>/* Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>

   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   - Neither the name of the Mumble Developers nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "mumble_pch.hpp"

#include "ConfigDialog.h"

#include "AudioInput.h"
#include "AudioOutput.h"
#include "Global.h"
#include "Overlay.h"

ConfigDialog::ConfigDialog(QWidget *p) : QDialog(p) {
	setupUi(this);

	s = g.s;

	unsigned int idx = 0;
	ConfigWidgetNew cwn;
	foreach(cwn, *ConfigRegistrar::c_qmNew) {
		addPage(cwn(s), ++idx);
	}

	qcbExpert->setChecked(g.s.bExpert);
	on_qcbExpert_clicked(g.s.bExpert);

	QPushButton *okButton = dialogButtonBox->button(QDialogButtonBox::Ok);
	okButton->setToolTip(tr("Accept changes"));
	okButton->setWhatsThis(tr("This button will accept current settings and return to the application.
"
	                          "The settings will be stored to disk when you leave the application."));

	QPushButton *cancelButton = dialogButtonBox->button(QDialogButtonBox::Cancel);
	cancelButton->setToolTip(tr("Reject changes"));
	cancelButton->setWhatsThis(tr("This button will reject all changes and return to the application.
"
	                              "The settings will be reset to the previous positions."));

	QPushButton *applyButton = dialogButtonBox->button(QDialogButtonBox::Apply);
	applyButton->setToolTip(tr("Apply changes"));
	applyButton->setWhatsThis(tr("This button will immediately apply all changes."));

	QPushButton *resetButton = pageButtonBox->button(QDialogButtonBox::Reset);
	resetButton->setToolTip(tr("Undo changes for current page"));
	resetButton->setWhatsThis(tr("This button will revert any changes done on the current page to the most recent applied settings."));

	QPushButton *restoreButton = pageButtonBox->button(QDialogButtonBox::RestoreDefaults);
	restoreButton->setToolTip(tr("Restore defaults for current page"));
	restoreButton->setWhatsThis(tr("This button will restore the defaults for the settings on the current page. Other pages will not be changed.
"
	                               "To restore all settings to their defaults, you will have to use this button on every page."
	                              ));

	if (! g.s.qbaConfigGeometry.isEmpty()) {
		if (! g.ocIntercept)
			restoreGeometry(g.s.qbaConfigGeometry);
	}
}

void ConfigDialog::addPage(ConfigWidget *cw, unsigned int idx) {
	QDesktopWidget dw;

	int w = INT_MAX, h = INT_MAX;

	for (int i=0;i<dw.numScreens();++i) {
		QRect ds=dw.availableGeometry(i);
		if (ds.isValid()) {
			w = qMin(w, ds.width());
			h = qMin(h, ds.height());
		}
	}

	QSize ms=cw->minimumSizeHint();
	cw->resize(ms);
	cw->setMinimumSize(ms);

	ms.rwidth() += 128;
	ms.rheight() += 192;
	if ((ms.width() > w) || (ms.height() > h)) {
		QScrollArea *qsa=new QScrollArea();
		qsa->setFrameShape(QFrame::NoFrame);
		qsa->setWidgetResizable(true);
		qsa->setWidget(cw);
		qhPages.insert(cw, qsa);
		qswPages->addWidget(qsa);
	} else {
		qhPages.insert(cw, cw);
		qswPages->addWidget(cw);
	}
	qmWidgets.insert(idx, cw);
	cw->load(g.s);
}

ConfigDialog::~ConfigDialog() {
	foreach(QWidget *qw, qhPages)
		delete qw;
}

void ConfigDialog::on_pageButtonBox_clicked(QAbstractButton *b) {
	ConfigWidget *conf = qobject_cast<ConfigWidget *>(qswPages->currentWidget());
	if (! conf) {
		QScrollArea *qsa = qobject_cast<QScrollArea *>(qswPages->currentWidget());
		if (qsa)
			conf = qobject_cast<ConfigWidget *>(qsa->widget());
	}
	if (! conf)
		return;
	switch (pageButtonBox->standardButton(b)) {
		case QDialogButtonBox::RestoreDefaults: {
				Settings def;
				def.bExpert = g.s.bExpert;
				conf->load(def);
				break;
			}
		case QDialogButtonBox::Reset: {
				conf->load(g.s);
				break;
			}
		default:
			break;
	}
}

void ConfigDialog::on_dialogButtonBox_clicked(QAbstractButton *b) {
	switch (dialogButtonBox->standardButton(b)) {
		case QDialogButtonBox::Apply: {
				apply();
				break;
			}
		default:
			break;
	}
}

void ConfigDialog::on_qlwIcons_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous) {
	if (!current)
		current = previous;

	if (current) {
		QWidget *w = qhPages.value(qmIconWidgets.value(current));
		if (w)
			qswPages->setCurrentWidget(w);
	}
}

void ConfigDialog::on_qcbExpert_clicked(bool b) {
	QWidget *ccw = qmIconWidgets.value(qlwIcons->currentItem());
	QListWidgetItem *sel = NULL;

	qmIconWidgets.clear();
	qlwIcons->clear();

	QFontMetrics qfm(qlwIcons->font());
	int width = 0;

	foreach(ConfigWidget *cw, qmWidgets) {
		bool showit = cw->expert(b);
		width = qMax(width, qfm.width(cw->title()));
		if (showit || b)  {
			QListWidgetItem *i = new QListWidgetItem(qlwIcons);
			i->setIcon(cw->icon());
			i->setText(cw->title());
			i->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);

			qmIconWidgets.insert(i, cw);
			if (cw == ccw)
				sel = i;
		}
	}

	// Add space for icon and some padding.
	width += qlwIcons->iconSize().width() + 25;

	qlwIcons->setMinimumWidth(width);
	qlwIcons->setMaximumWidth(width);

	if (sel)
		qlwIcons->setCurrentItem(sel);
	else
		qlwIcons->setCurrentRow(0);
}

void ConfigDialog::apply() {
	Audio::stop();

	foreach(ConfigWidget *cw, qmWidgets)
		cw->save();

	g.s = s;

	foreach(ConfigWidget *cw, qmWidgets)
		cw->accept();

	if (g.s.requireRestartToApply && QMessageBox::question(
		        this,
		        tr("Restart Mumble?"),
		        tr("Some settings will only apply after a restart of Mumble. Restart Mumble now?"),
		        QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {

		qApp->exit(MUMBLE_EXIT_CODE_RESTART);
	}

	if (!g.s.bAttenuateOthersOnTalk)
		g.bAttenuateOthers = false;

	// They might have changed their keys.
	g.iPushToTalk = 0;
	g.s.bExpert = qcbExpert->isChecked();

	Audio::start();
}

void ConfigDialog::accept() {
	apply();

	if (! g.ocIntercept)
		g.s.qbaConfigGeometry=saveGeometry();

	QDialog::accept();
}
<commit_msg>Enable audio to be played during config restart query<commit_after>/* Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>

   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   - Neither the name of the Mumble Developers nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "mumble_pch.hpp"

#include "ConfigDialog.h"

#include "AudioInput.h"
#include "AudioOutput.h"
#include "Global.h"
#include "Overlay.h"

ConfigDialog::ConfigDialog(QWidget *p) : QDialog(p) {
	setupUi(this);

	s = g.s;

	unsigned int idx = 0;
	ConfigWidgetNew cwn;
	foreach(cwn, *ConfigRegistrar::c_qmNew) {
		addPage(cwn(s), ++idx);
	}

	qcbExpert->setChecked(g.s.bExpert);
	on_qcbExpert_clicked(g.s.bExpert);

	QPushButton *okButton = dialogButtonBox->button(QDialogButtonBox::Ok);
	okButton->setToolTip(tr("Accept changes"));
	okButton->setWhatsThis(tr("This button will accept current settings and return to the application.
"
	                          "The settings will be stored to disk when you leave the application."));

	QPushButton *cancelButton = dialogButtonBox->button(QDialogButtonBox::Cancel);
	cancelButton->setToolTip(tr("Reject changes"));
	cancelButton->setWhatsThis(tr("This button will reject all changes and return to the application.
"
	                              "The settings will be reset to the previous positions."));

	QPushButton *applyButton = dialogButtonBox->button(QDialogButtonBox::Apply);
	applyButton->setToolTip(tr("Apply changes"));
	applyButton->setWhatsThis(tr("This button will immediately apply all changes."));

	QPushButton *resetButton = pageButtonBox->button(QDialogButtonBox::Reset);
	resetButton->setToolTip(tr("Undo changes for current page"));
	resetButton->setWhatsThis(tr("This button will revert any changes done on the current page to the most recent applied settings."));

	QPushButton *restoreButton = pageButtonBox->button(QDialogButtonBox::RestoreDefaults);
	restoreButton->setToolTip(tr("Restore defaults for current page"));
	restoreButton->setWhatsThis(tr("This button will restore the defaults for the settings on the current page. Other pages will not be changed.
"
	                               "To restore all settings to their defaults, you will have to use this button on every page."
	                              ));

	if (! g.s.qbaConfigGeometry.isEmpty()) {
		if (! g.ocIntercept)
			restoreGeometry(g.s.qbaConfigGeometry);
	}
}

void ConfigDialog::addPage(ConfigWidget *cw, unsigned int idx) {
	QDesktopWidget dw;

	int w = INT_MAX, h = INT_MAX;

	for (int i=0;i<dw.numScreens();++i) {
		QRect ds=dw.availableGeometry(i);
		if (ds.isValid()) {
			w = qMin(w, ds.width());
			h = qMin(h, ds.height());
		}
	}

	QSize ms=cw->minimumSizeHint();
	cw->resize(ms);
	cw->setMinimumSize(ms);

	ms.rwidth() += 128;
	ms.rheight() += 192;
	if ((ms.width() > w) || (ms.height() > h)) {
		QScrollArea *qsa=new QScrollArea();
		qsa->setFrameShape(QFrame::NoFrame);
		qsa->setWidgetResizable(true);
		qsa->setWidget(cw);
		qhPages.insert(cw, qsa);
		qswPages->addWidget(qsa);
	} else {
		qhPages.insert(cw, cw);
		qswPages->addWidget(cw);
	}
	qmWidgets.insert(idx, cw);
	cw->load(g.s);
}

ConfigDialog::~ConfigDialog() {
	foreach(QWidget *qw, qhPages)
		delete qw;
}

void ConfigDialog::on_pageButtonBox_clicked(QAbstractButton *b) {
	ConfigWidget *conf = qobject_cast<ConfigWidget *>(qswPages->currentWidget());
	if (! conf) {
		QScrollArea *qsa = qobject_cast<QScrollArea *>(qswPages->currentWidget());
		if (qsa)
			conf = qobject_cast<ConfigWidget *>(qsa->widget());
	}
	if (! conf)
		return;
	switch (pageButtonBox->standardButton(b)) {
		case QDialogButtonBox::RestoreDefaults: {
				Settings def;
				def.bExpert = g.s.bExpert;
				conf->load(def);
				break;
			}
		case QDialogButtonBox::Reset: {
				conf->load(g.s);
				break;
			}
		default:
			break;
	}
}

void ConfigDialog::on_dialogButtonBox_clicked(QAbstractButton *b) {
	switch (dialogButtonBox->standardButton(b)) {
		case QDialogButtonBox::Apply: {
				apply();
				break;
			}
		default:
			break;
	}
}

void ConfigDialog::on_qlwIcons_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous) {
	if (!current)
		current = previous;

	if (current) {
		QWidget *w = qhPages.value(qmIconWidgets.value(current));
		if (w)
			qswPages->setCurrentWidget(w);
	}
}

void ConfigDialog::on_qcbExpert_clicked(bool b) {
	QWidget *ccw = qmIconWidgets.value(qlwIcons->currentItem());
	QListWidgetItem *sel = NULL;

	qmIconWidgets.clear();
	qlwIcons->clear();

	QFontMetrics qfm(qlwIcons->font());
	int width = 0;

	foreach(ConfigWidget *cw, qmWidgets) {
		bool showit = cw->expert(b);
		width = qMax(width, qfm.width(cw->title()));
		if (showit || b)  {
			QListWidgetItem *i = new QListWidgetItem(qlwIcons);
			i->setIcon(cw->icon());
			i->setText(cw->title());
			i->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);

			qmIconWidgets.insert(i, cw);
			if (cw == ccw)
				sel = i;
		}
	}

	// Add space for icon and some padding.
	width += qlwIcons->iconSize().width() + 25;

	qlwIcons->setMinimumWidth(width);
	qlwIcons->setMaximumWidth(width);

	if (sel)
		qlwIcons->setCurrentItem(sel);
	else
		qlwIcons->setCurrentRow(0);
}

void ConfigDialog::apply() {
	Audio::stop();

	foreach(ConfigWidget *cw, qmWidgets)
		cw->save();

	g.s = s;

	foreach(ConfigWidget *cw, qmWidgets)
		cw->accept();

	if (!g.s.bAttenuateOthersOnTalk)
		g.bAttenuateOthers = false;

	// They might have changed their keys.
	g.iPushToTalk = 0;
	g.s.bExpert = qcbExpert->isChecked();

	Audio::start();

	if (g.s.requireRestartToApply && QMessageBox::question(
		        this,
		        tr("Restart Mumble?"),
		        tr("Some settings will only apply after a restart of Mumble. Restart Mumble now?"),
		        QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {

		qApp->exit(MUMBLE_EXIT_CODE_RESTART);
	}
}

void ConfigDialog::accept() {
	apply();

	if (! g.ocIntercept)
		g.s.qbaConfigGeometry=saveGeometry();

	QDialog::accept();
}
<|endoftext|>


<commit_before>/**
 * @file
 * @author Jason Lingle
 * @date 2012.02.06
 * @brief Implementation of the GameDiscoverer class
 */

#include <cstring>
#include <iostream>
#include <algorithm>

#include <SDL.h>

#include "game_discoverer.hxx"
#include "antenna.hxx"
#include "tuner.hxx"
#include "io.hxx"
#include "src/globals.hxx"

using namespace std;

#define BROADCAST_INTERVAL 128
#define CYCLE_COUNT 8
static const byte trigger[] = {
  'A', 'b', 'e', 'n', 'd', 's', 'p', 'i', 'e', 'l',
};

static bool resultLessThan(const GameDiscoverer::Result& a,
                           const GameDiscoverer::Result& b) {
  return a.peerCount > b.peerCount;
}

GameDiscoverer::GameDiscoverer(Tuner* tuner_)
: tuner(tuner_),  nextBroadcast(-1 /* max value */), currentTry(CYCLE_COUNT)
{
  tuner->trigger(trigger, sizeof(trigger), this);
}

GameDiscoverer::~GameDiscoverer() {
  tuner->untrigger(trigger, sizeof(trigger));
}

void GameDiscoverer::start() noth {
  nextBroadcast = SDL_GetTicks();
  currentTry = 0;
  results.clear();
}

void GameDiscoverer::poll(Antenna* antenna) noth {
  if (SDL_GetTicks() >= nextBroadcast && currentTry < CYCLE_COUNT) {
    ++currentTry;
    static const byte pack[] = {
      'A', 'b', 'e', 'n', 'd', 's', 'u', 'c', 'h'
    };
    static const asio::ip::address v4addr(
      asio::ip::address_v4::from_string("255.255.255.255"));
    static const asio::ip::address v6addr(
      asio::ip::address_v6::from_string("ff02::1"));
    for (unsigned isV6=0; isV6 < 2; ++isV6) {
      for (unsigned port=0; port < lenof(Antenna::wellKnownPorts); ++port) {
        try {
          if (isV6) {
            //IPv6
            if (antenna->hasV6()) {
              asio::ip::udp::endpoint dest(v6addr,
                                           Antenna::wellKnownPorts[port]);
              antenna->send(dest, pack, sizeof(pack));
            }
          } else {
            if (antenna->hasV4()) {
              asio::ip::udp::endpoint dest(v4addr,
                                           Antenna::wellKnownPorts[port]);
              antenna->send(dest, pack, sizeof(pack));
            }
          }
        } catch (asio::system_error e) {
          cerr << "Unable to broadcast to port "
               << Antenna::wellKnownPorts[port]
               << " with protocol " << (isV6? "IPv6" : "IPv4")
               << ": " << e.what() << endl;
        }
      }
    }

    nextBroadcast = SDL_GetTicks() + BROADCAST_INTERVAL;
  }
}

float GameDiscoverer::progress() const noth {
  if (currentTry == 0) return 0;
  if (currentTry == CYCLE_COUNT && SDL_GetTicks() >= nextBroadcast)
    return 1;

  return (currentTry +
          (SDL_GetTicks()-nextBroadcast)/(float)BROADCAST_INTERVAL)/
         (float)CYCLE_COUNT;
}

void GameDiscoverer::process(const Antenna::endpoint& source,
                             Antenna* antenna, Tuner* tuner,
                             const byte* data, unsigned len)
noth {
  //Past trigger
  data += sizeof(trigger);
  len -= sizeof(trigger);
  Antenna::endpoint defaultEndpoint;
  if (source != defaultEndpoint) {
    //LAN advert
    if (len != 4+1+1+4) {
#ifdef DEBUG
      cerr << "Warning: Ignoring Abendspiel of unexpected length: "
           << len << ", from " << source << endl;
#endif
      return;
    }

    Uint32 oid;
    byte peercnt, pwprot;
    char mode[4];
    io::read(data, oid);
    io::read(data, peercnt);
    io::read(data, pwprot);
    strncpy((char*)mode, (const char*)data, 4);

    //Don't add result if the overseer has the same ID as another
    for (unsigned i=0; i<results.size(); ++i)
      if (results[i].overseer == oid)
        return;

    //OK, add result
    Result res;
    res.connectByEndpoint = true;
    res.peer = source;
    res.overseer = oid;
    res.passwordProtected = pwprot;
    res.peerCount = peercnt;
    memcpy(res.gameMode, mode, sizeof(mode));
    results.push_back(res);
    sort(results.begin(), results.end(), resultLessThan);
  } else {
    //Abuhops advert
    if (len < 4+1+1+4) {
#ifdef DEBUG
      cerr << "Warning: Ignoring Abendspiel ADVERT of bad length: "
           << len << endl;
#endif
      return;
    }

    bool v6 = data[4+1];
    if (len != 4+1+1+4 + 2*(v6? 2+8*2 : 2+4)) {
#ifdef DEBUG
      cerr << "Warning: Ignoring Abendspiel ADVERT of unexpected length: "
           << len << endl;
#endif
      return;
    }

    unsigned oid;
    byte peercnt;
    io::read(data, oid);
    io::read(data, peercnt);
    ++data; //IP version

    //Don't add result if the overseer has the same ID as another
    for (unsigned i=0; i<results.size(); ++i)
      if (results[i].overseer == oid)
        return;

    //OK
    Result res;
    res.connectByEndpoint = false;
    res.peergid.ipv = v6? GlobalID::IPv6 : GlobalID::IPv4;
    res.overseer = oid;
    res.passwordProtected = false;
    res.peerCount = peercnt;
    if (v6) {
      io::a6tohbo(res.peergid.la6, data);
      data += 2*8;
      io::read(data, res.peergid.lport);
      io::a6tohbo(res.peergid.ia6, data);
      data += 2*8;
      io::read(data, res.peergid.iport);
    } else {
      memcpy(res.peergid.la4, data, 4);
      data += 4;
      io::read(data, res.peergid.lport);
      memcpy(res.peergid.ia4, data, 4);
      data += 4;
      io::read(data, res.peergid.iport);
    }
    strncpy((char*)res.gameMode, (char*)data, sizeof(res.gameMode));
    results.push_back(res);
  }
}
<commit_msg>Call abuhops::list() when game discovery is to start.<commit_after>/**
 * @file
 * @author Jason Lingle
 * @date 2012.02.06
 * @brief Implementation of the GameDiscoverer class
 */

#include <cstring>
#include <iostream>
#include <algorithm>

#include <SDL.h>

#include "game_discoverer.hxx"
#include "antenna.hxx"
#include "tuner.hxx"
#include "io.hxx"
#include "abuhops.hxx"
#include "src/globals.hxx"

using namespace std;

#define BROADCAST_INTERVAL 128
#define CYCLE_COUNT 8
static const byte trigger[] = {
  'A', 'b', 'e', 'n', 'd', 's', 'p', 'i', 'e', 'l',
};

static bool resultLessThan(const GameDiscoverer::Result& a,
                           const GameDiscoverer::Result& b) {
  return a.peerCount > b.peerCount;
}

GameDiscoverer::GameDiscoverer(Tuner* tuner_)
: tuner(tuner_),  nextBroadcast(-1 /* max value */), currentTry(CYCLE_COUNT)
{
  tuner->trigger(trigger, sizeof(trigger), this);
}

GameDiscoverer::~GameDiscoverer() {
  tuner->untrigger(trigger, sizeof(trigger));
}

void GameDiscoverer::start() noth {
  nextBroadcast = SDL_GetTicks();
  currentTry = 0;
  results.clear();
  abuhops::list();
}

void GameDiscoverer::poll(Antenna* antenna) noth {
  if (SDL_GetTicks() >= nextBroadcast && currentTry < CYCLE_COUNT) {
    ++currentTry;
    static const byte pack[] = {
      'A', 'b', 'e', 'n', 'd', 's', 'u', 'c', 'h'
    };
    static const asio::ip::address v4addr(
      asio::ip::address_v4::from_string("255.255.255.255"));
    static const asio::ip::address v6addr(
      asio::ip::address_v6::from_string("ff02::1"));
    for (unsigned isV6=0; isV6 < 2; ++isV6) {
      for (unsigned port=0; port < lenof(Antenna::wellKnownPorts); ++port) {
        try {
          if (isV6) {
            //IPv6
            if (antenna->hasV6()) {
              asio::ip::udp::endpoint dest(v6addr,
                                           Antenna::wellKnownPorts[port]);
              antenna->send(dest, pack, sizeof(pack));
            }
          } else {
            if (antenna->hasV4()) {
              asio::ip::udp::endpoint dest(v4addr,
                                           Antenna::wellKnownPorts[port]);
              antenna->send(dest, pack, sizeof(pack));
            }
          }
        } catch (asio::system_error e) {
          cerr << "Unable to broadcast to port "
               << Antenna::wellKnownPorts[port]
               << " with protocol " << (isV6? "IPv6" : "IPv4")
               << ": " << e.what() << endl;
        }
      }
    }

    nextBroadcast = SDL_GetTicks() + BROADCAST_INTERVAL;
  }
}

float GameDiscoverer::progress() const noth {
  if (currentTry == 0) return 0;
  if (currentTry == CYCLE_COUNT && SDL_GetTicks() >= nextBroadcast)
    return 1;

  return (currentTry +
          (SDL_GetTicks()-nextBroadcast)/(float)BROADCAST_INTERVAL)/
         (float)CYCLE_COUNT;
}

void GameDiscoverer::process(const Antenna::endpoint& source,
                             Antenna* antenna, Tuner* tuner,
                             const byte* data, unsigned len)
noth {
  //Past trigger
  data += sizeof(trigger);
  len -= sizeof(trigger);
  Antenna::endpoint defaultEndpoint;
  if (source != defaultEndpoint) {
    //LAN advert
    if (len != 4+1+1+4) {
#ifdef DEBUG
      cerr << "Warning: Ignoring Abendspiel of unexpected length: "
           << len << ", from " << source << endl;
#endif
      return;
    }

    Uint32 oid;
    byte peercnt, pwprot;
    char mode[4];
    io::read(data, oid);
    io::read(data, peercnt);
    io::read(data, pwprot);
    strncpy((char*)mode, (const char*)data, 4);

    //Don't add result if the overseer has the same ID as another
    for (unsigned i=0; i<results.size(); ++i)
      if (results[i].overseer == oid)
        return;

    //OK, add result
    Result res;
    res.connectByEndpoint = true;
    res.peer = source;
    res.overseer = oid;
    res.passwordProtected = pwprot;
    res.peerCount = peercnt;
    memcpy(res.gameMode, mode, sizeof(mode));
    results.push_back(res);
    sort(results.begin(), results.end(), resultLessThan);
  } else {
    //Abuhops advert
    if (len < 4+1+1+4) {
#ifdef DEBUG
      cerr << "Warning: Ignoring Abendspiel ADVERT of bad length: "
           << len << endl;
#endif
      return;
    }

    bool v6 = data[4+1];
    if (len != 4+1+1+4 + 2*(v6? 2+8*2 : 2+4)) {
#ifdef DEBUG
      cerr << "Warning: Ignoring Abendspiel ADVERT of unexpected length: "
           << len << endl;
#endif
      return;
    }

    unsigned oid;
    byte peercnt;
    io::read(data, oid);
    io::read(data, peercnt);
    ++data; //IP version

    //Don't add result if the overseer has the same ID as another
    for (unsigned i=0; i<results.size(); ++i)
      if (results[i].overseer == oid)
        return;

    //OK
    Result res;
    res.connectByEndpoint = false;
    res.peergid.ipv = v6? GlobalID::IPv6 : GlobalID::IPv4;
    res.overseer = oid;
    res.passwordProtected = false;
    res.peerCount = peercnt;
    if (v6) {
      io::a6tohbo(res.peergid.la6, data);
      data += 2*8;
      io::read(data, res.peergid.lport);
      io::a6tohbo(res.peergid.ia6, data);
      data += 2*8;
      io::read(data, res.peergid.iport);
    } else {
      memcpy(res.peergid.la4, data, 4);
      data += 4;
      io::read(data, res.peergid.lport);
      memcpy(res.peergid.ia4, data, 4);
      data += 4;
      io::read(data, res.peergid.iport);
    }
    strncpy((char*)res.gameMode, (char*)data, sizeof(res.gameMode));
    results.push_back(res);
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 William W. Fisher (at gmail dot com)
// This file is distributed under the MIT License.

#include "ofp/demux/pktfilter.h"
#include <pcap/bpf.h>
#include "ofp/log.h"

using namespace ofp::demux;

PktFilter::PktFilter(PktFilter &&rhs) : prog_{rhs.prog_}, filter_{std::move(rhs.filter_)} {
  rhs.prog_.bf_insns = nullptr;
  assert(rhs.filter_.empty());
}

void PktFilter::clear() {
  if (!empty()) {
    pcap_freecode(&prog_);
    filter_.clear();
  }
  assert(empty());
}

bool PktFilter::setFilter(const std::string &filter) {
  const int kOptimize = 1;
  const int kSnapLen = 65535;
  const int kLinkType = DLT_EN10MB;

  struct bpf_program newProg = { 0, nullptr };
  int ret = pcap_compile_nopcap(kSnapLen, kLinkType, &newProg, filter.c_str(),
                                kOptimize, PCAP_NETMASK_UNKNOWN);
  if (ret < 0) {
    assert(newProg.bf_insns == nullptr);
    log_error("pcap_compile_nopcap failed for filter:", filter);
    return false;
  }

  clear();
  prog_ = newProg;
  filter_ = filter;

  return true;
}

bool PktFilter::match(ByteRange data, size_t totalLen) const {
  // Empty filter never matches.
  if (empty())
    return false;

  struct pcap_pkthdr hdr;
  hdr.ts.tv_sec = 0;
  hdr.ts.tv_usec = 0;
  hdr.caplen = UInt32_narrow_cast(data.size());
  hdr.len = UInt32_narrow_cast(totalLen);

  assert(prog_.bf_insns != nullptr);
  return pcap_offline_filter(&prog_, &hdr, data.data()) > 0;
}
<commit_msg>Fix gcc-4.8 compiler error.<commit_after>// Copyright (c) 2017 William W. Fisher (at gmail dot com)
// This file is distributed under the MIT License.

#include "ofp/demux/pktfilter.h"
#include <pcap/bpf.h>
#include "ofp/log.h"

using namespace ofp::demux;

// In the following member-wise initialization, we need to use
// `prog_(rhs.prog_)`. Using braces results in a GCC-4.8.4 compiler error.

PktFilter::PktFilter(PktFilter &&rhs) : prog_(rhs.prog_), filter_{std::move(rhs.filter_)} {
  rhs.prog_.bf_insns = nullptr;
  assert(rhs.filter_.empty());
}

void PktFilter::clear() {
  if (!empty()) {
    pcap_freecode(&prog_);
    filter_.clear();
  }
  assert(empty());
}

bool PktFilter::setFilter(const std::string &filter) {
  const int kOptimize = 1;
  const int kSnapLen = 65535;
  const int kLinkType = DLT_EN10MB;

  struct bpf_program newProg = { 0, nullptr };
  int ret = pcap_compile_nopcap(kSnapLen, kLinkType, &newProg, filter.c_str(),
                                kOptimize, PCAP_NETMASK_UNKNOWN);
  if (ret < 0) {
    assert(newProg.bf_insns == nullptr);
    log_error("pcap_compile_nopcap failed for filter:", filter);
    return false;
  }

  clear();
  prog_ = newProg;
  filter_ = filter;

  return true;
}

bool PktFilter::match(ByteRange data, size_t totalLen) const {
  // Empty filter never matches.
  if (empty())
    return false;

  struct pcap_pkthdr hdr;
  hdr.ts.tv_sec = 0;
  hdr.ts.tv_usec = 0;
  hdr.caplen = UInt32_narrow_cast(data.size());
  hdr.len = UInt32_narrow_cast(totalLen);

  assert(prog_.bf_insns != nullptr);
  return pcap_offline_filter(&prog_, &hdr, data.data()) > 0;
}
<|endoftext|>