<commit_before>// Time:  O(nlogn)
// Space: O(1)

class Solution {
public:
    bool isReflected(vector<pair<int, int>>& points) {
        if (points.empty()) {
            return true;
        }
        sort(points.begin(), points.end());
        sort(points.begin(), points.begin() + distance(points.begin(), points.end()) / 2,
            [](const pair<int, int>& a, const pair<int, int>& b) {
                if (a.first == b.first) {
                    return a.second > b.second;
                }
                return a.first < b.first;
            });

        const auto mid = points.front().first + (points.back().first - points.front().first) / 2.0;
        for (int left = 0, right = points.size() - 1; left <= right; ++left, --right) {
            if ((mid != points[left].first + (points[right].first - points[left].first) / 2.0) ||
                (points[left].first != points[right].first &&
                 points[left].second != points[right].second)) {
                return false;
            }
        }
        return true;
    }
};
<commit_msg>Update line-reflection.cpp<commit_after>// Time:  O(nlogn)
// Space: O(1)

class Solution {
public:
    bool isReflected(vector<pair<int, int>>& points) {
        if (points.empty()) {
            return true;
        }
        sort(points.begin(), points.end());
        sort(points.begin(), points.begin() + distance(points.begin(), points.end()) / 2,
            [](const pair<int, int>& a, const pair<int, int>& b) {
                if (a.first == b.first) {
                    return a.second > b.second;
                }
                return a.first < b.first;
            });

        const auto mid = points.front().first + points.back().first;
        for (int left = 0, right = points.size() - 1; left <= right; ++left, --right) {
            if ((mid != points[left].first + points[right].first) ||
                (points[left].first != points[right].first &&
                 points[left].second != points[right].second)) {
                return false;
            }
        }
        return true;
    }
};
<|endoftext|>


<commit_before>/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <ndb_global.h>

#include <File.hpp>

#include <NdbOut.hpp>
#include <my_dir.h>

//
// PUBLIC
//
time_t
File_class::mtime(const char* aFileName)
{
  MY_STAT stmp;
  time_t rc = 0;

  if (my_stat(aFileName, &stmp, MYF(0)) != NULL) {
    rc = stmp.st_mtime;
  }

  return rc;
}

bool
File_class::exists(const char* aFileName)
{
  MY_STAT stmp;

  return (my_stat(aFileName, &stmp, MYF(0))!=NULL);
}

off_t
File_class::size(FILE* f)
{
  MY_STAT s;

  // Note that my_fstat behaves *differently* than my_stat. ARGGGHH!
  if(my_fstat(::fileno(f), &s, MYF(0)))
    return 0;

  return s.st_size;
}

bool
File_class::rename(const char* currFileName, const char* newFileName)
{
  return ::rename(currFileName, newFileName) == 0 ? true : false;
}
bool
File_class::remove(const char* aFileName)
{
  return ::remove(aFileName) == 0 ? true : false;
}

File_class::File_class() :
  m_file(NULL),
  m_fileMode("r")
{
}

File_class::File_class(const char* aFileName, const char* mode) :
  m_file(NULL),
  m_fileMode(mode)
{
  BaseString::snprintf(m_fileName, PATH_MAX, aFileName);
}

bool
File_class::open()
{
  return open(m_fileName, m_fileMode);
}

bool
File_class::open(const char* aFileName, const char* mode)
{
  if(m_fileName != aFileName){
    /**
     * Only copy if it's not the same string
     */
    BaseString::snprintf(m_fileName, PATH_MAX, aFileName);
  }
  m_fileMode = mode;
  bool rc = true;
  if ((m_file = ::fopen(m_fileName, m_fileMode))== NULL)
  {
    rc = false;
  }

  return rc;
}
File_class::~File_class()
{
  close();
}

bool
File_class::remove()
{
  // Close the file first!
  close();
  return File_class::remove(m_fileName);
}

bool
File_class::close()
{
  bool rc = true;
  int retval = 0;

  if (m_file != NULL)
  {
    ::fflush(m_file);
    retval = ::fclose(m_file);
    while ( (retval != 0) && (errno == EINTR) ){
      retval = ::fclose(m_file);
    }
    if( retval == 0){
      rc = true;
    }
    else {
      rc = false;
      ndbout_c("ERROR: Close file error in File.cpp for %s",strerror(errno));
    }
  }
  m_file = NULL;

  return rc;
}

int
File_class::read(void* buf, size_t itemSize, size_t nitems) const
{
  return ::fread(buf, itemSize,  nitems, m_file);
}

int
File_class::readChar(char* buf, long start, long length) const
{
  return ::fread((void*)&buf[start], 1, length, m_file);
}

int
File_class::readChar(char* buf)
{
  return readChar(buf, 0, strlen(buf));
}

int
File_class::write(const void* buf, size_t size, size_t nitems)
{
  return ::fwrite(buf, size, nitems, m_file);
}

int
File_class::writeChar(const char* buf, long start, long length)
{
  return ::fwrite((const void*)&buf[start], sizeof(char), length, m_file);
}

int
File_class::writeChar(const char* buf)
{
  return writeChar(buf, 0, ::strlen(buf));
}

off_t
File_class::size() const
{
  return File_class::size(m_file);
}

const char*
File_class::getName() const
{
  return m_fileName;
}

int
File_class::flush() const
{
  return ::fflush(m_file);;
}
<commit_msg>Change ::fileno() to fileno() in ndb/common/util/File.cpp.<commit_after>/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <ndb_global.h>

#include <File.hpp>

#include <NdbOut.hpp>
#include <my_dir.h>

//
// PUBLIC
//
time_t
File_class::mtime(const char* aFileName)
{
  MY_STAT stmp;
  time_t rc = 0;

  if (my_stat(aFileName, &stmp, MYF(0)) != NULL) {
    rc = stmp.st_mtime;
  }

  return rc;
}

bool
File_class::exists(const char* aFileName)
{
  MY_STAT stmp;

  return (my_stat(aFileName, &stmp, MYF(0))!=NULL);
}

off_t
File_class::size(FILE* f)
{
  MY_STAT s;

  // Note that my_fstat behaves *differently* than my_stat. ARGGGHH!
  if (my_fstat(fileno(f), &s, MYF(0)))
    return 0;

  return s.st_size;
}

bool
File_class::rename(const char* currFileName, const char* newFileName)
{
  return ::rename(currFileName, newFileName) == 0 ? true : false;
}
bool
File_class::remove(const char* aFileName)
{
  return ::remove(aFileName) == 0 ? true : false;
}

File_class::File_class() :
  m_file(NULL),
  m_fileMode("r")
{
}

File_class::File_class(const char* aFileName, const char* mode) :
  m_file(NULL),
  m_fileMode(mode)
{
  BaseString::snprintf(m_fileName, PATH_MAX, aFileName);
}

bool
File_class::open()
{
  return open(m_fileName, m_fileMode);
}

bool
File_class::open(const char* aFileName, const char* mode)
{
  if(m_fileName != aFileName){
    /**
     * Only copy if it's not the same string
     */
    BaseString::snprintf(m_fileName, PATH_MAX, aFileName);
  }
  m_fileMode = mode;
  bool rc = true;
  if ((m_file = ::fopen(m_fileName, m_fileMode))== NULL)
  {
    rc = false;
  }

  return rc;
}
File_class::~File_class()
{
  close();
}

bool
File_class::remove()
{
  // Close the file first!
  close();
  return File_class::remove(m_fileName);
}

bool
File_class::close()
{
  bool rc = true;
  int retval = 0;

  if (m_file != NULL)
  {
    ::fflush(m_file);
    retval = ::fclose(m_file);
    while ( (retval != 0) && (errno == EINTR) ){
      retval = ::fclose(m_file);
    }
    if( retval == 0){
      rc = true;
    }
    else {
      rc = false;
      ndbout_c("ERROR: Close file error in File.cpp for %s",strerror(errno));
    }
  }
  m_file = NULL;

  return rc;
}

int
File_class::read(void* buf, size_t itemSize, size_t nitems) const
{
  return ::fread(buf, itemSize,  nitems, m_file);
}

int
File_class::readChar(char* buf, long start, long length) const
{
  return ::fread((void*)&buf[start], 1, length, m_file);
}

int
File_class::readChar(char* buf)
{
  return readChar(buf, 0, strlen(buf));
}

int
File_class::write(const void* buf, size_t size, size_t nitems)
{
  return ::fwrite(buf, size, nitems, m_file);
}

int
File_class::writeChar(const char* buf, long start, long length)
{
  return ::fwrite((const void*)&buf[start], sizeof(char), length, m_file);
}

int
File_class::writeChar(const char* buf)
{
  return writeChar(buf, 0, ::strlen(buf));
}

off_t
File_class::size() const
{
  return File_class::size(m_file);
}

const char*
File_class::getName() const
{
  return m_fileName;
}

int
File_class::flush() const
{
  return ::fflush(m_file);;
}
<|endoftext|>


<commit_before><commit_msg>coverity#704836 Dereference after null check<commit_after><|endoftext|>


<commit_before>#define CDM_CONFIGURE_NAMESPACE a0038898
#include "../../cdm/application/using_many_libs/cdm.hpp"
#include "log.hpp"
#include "temporary.hpp"
#include <boost/test/unit_test.hpp>
#include <silicium/sink/ostream_sink.hpp>
#include <ventura/file_operations.hpp>
#include <cdm/locate_cache.hpp>

#if !defined(_MSC_VER) || (_MSC_VER != 1900)
// websocketpp does not compille on VS 2015 yet

namespace
{
	ventura::absolute_path const this_file = *ventura::absolute_path::create(__FILE__);
	ventura::absolute_path const test = *ventura::parent(this_file);
	ventura::absolute_path const repository = *ventura::parent(test);
}

BOOST_AUTO_TEST_CASE(test_using_many_libs)
{
	cdm::travis_keep_alive_printer keep_travis_alive;
	ventura::absolute_path const app_source = repository / "application/using_many_libs";
	ventura::absolute_path const tmp = cdm::get_temporary_root_for_testing() / "cdm_b";
	ventura::recreate_directories(tmp, Si::throw_);
	ventura::absolute_path const module_temporaries = tmp / "build";
	ventura::create_directories(module_temporaries, Si::throw_);
	ventura::absolute_path const application_build_dir = tmp / "using_many_libs";
	ventura::create_directories(application_build_dir, Si::throw_);
	std::unique_ptr<std::ofstream> log_file = cdm::open_log(application_build_dir / "test_using_many_libs.txt");
	auto output = cdm::make_program_output_printer(Si::ostream_ref_sink(*log_file));
	unsigned const cpu_parallelism =
#if CDM_TESTS_RUNNING_ON_TRAVIS_CI
	    2;
#else
	    boost::thread::hardware_concurrency();
#endif
	CDM_CONFIGURE_NAMESPACE::configure(
	    module_temporaries, cdm::locate_cache_for_this_binary(), app_source, application_build_dir, cpu_parallelism,
	    cdm::detect_this_binary_operating_system(CDM_TESTS_RUNNING_ON_TRAVIS_CI, CDM_TESTS_RUNNING_ON_APPVEYOR),
	    cdm::approximate_configuration_of_this_binary(), output);
	{
		std::vector<Si::os_string> arguments;
		arguments.emplace_back(SILICIUM_OS_STR("--build"));
		arguments.emplace_back(SILICIUM_OS_STR("."));
		auto console_output = Si::Sink<char, Si::success>::erase(Si::ostream_ref_sink(std::cerr));
		BOOST_REQUIRE_EQUAL(0,
		                    ventura::run_process(ventura::cmake_exe, arguments, application_build_dir, console_output,
		                                         std::vector<std::pair<Si::os_char const *, Si::os_char const *>>(),
		                                         ventura::environment_inheritance::inherit));
	}
	{
		std::vector<Si::os_string> arguments;
		ventura::relative_path const relative(
#ifdef _MSC_VER
		    "Debug/"
#endif
		    "using_many_libs"
#ifdef _MSC_VER
		    ".exe"
#endif
		    );
		BOOST_REQUIRE_EQUAL(0, ventura::run_process(application_build_dir / relative, arguments, application_build_dir,
		                                            output,
		                                            std::vector<std::pair<Si::os_char const *, Si::os_char const *>>(),
		                                            ventura::environment_inheritance::inherit));
	}
}
#endif
<commit_msg>ignore websocketpp issue on GCC 4.6<commit_after>#define CDM_CONFIGURE_NAMESPACE a0038898
#include "../../cdm/application/using_many_libs/cdm.hpp"
#include "log.hpp"
#include "temporary.hpp"
#include <boost/test/unit_test.hpp>
#include <silicium/sink/ostream_sink.hpp>
#include <ventura/file_operations.hpp>
#include <cdm/locate_cache.hpp>

#if (!defined(_MSC_VER) || (_MSC_VER != 1900)) && !SILICIUM_GCC46
// websocketpp does not compille on VS 2015 yet.
// GCC 4.6 is excluded because Catch requires C++11 for GCC 5 while websocketpp does not
// compile with C++11 on GCC 4.6. Ignoring the ancient compiler is the best option here.

namespace
{
	ventura::absolute_path const this_file = *ventura::absolute_path::create(__FILE__);
	ventura::absolute_path const test = *ventura::parent(this_file);
	ventura::absolute_path const repository = *ventura::parent(test);
}

BOOST_AUTO_TEST_CASE(test_using_many_libs)
{
	cdm::travis_keep_alive_printer keep_travis_alive;
	ventura::absolute_path const app_source = repository / "application/using_many_libs";
	ventura::absolute_path const tmp = cdm::get_temporary_root_for_testing() / "cdm_b";
	ventura::recreate_directories(tmp, Si::throw_);
	ventura::absolute_path const module_temporaries = tmp / "build";
	ventura::create_directories(module_temporaries, Si::throw_);
	ventura::absolute_path const application_build_dir = tmp / "using_many_libs";
	ventura::create_directories(application_build_dir, Si::throw_);
	std::unique_ptr<std::ofstream> log_file = cdm::open_log(application_build_dir / "test_using_many_libs.txt");
	auto output = cdm::make_program_output_printer(Si::ostream_ref_sink(*log_file));
	unsigned const cpu_parallelism =
#if CDM_TESTS_RUNNING_ON_TRAVIS_CI
	    2;
#else
	    boost::thread::hardware_concurrency();
#endif
	CDM_CONFIGURE_NAMESPACE::configure(
	    module_temporaries, cdm::locate_cache_for_this_binary(), app_source, application_build_dir, cpu_parallelism,
	    cdm::detect_this_binary_operating_system(CDM_TESTS_RUNNING_ON_TRAVIS_CI, CDM_TESTS_RUNNING_ON_APPVEYOR),
	    cdm::approximate_configuration_of_this_binary(), output);
	{
		std::vector<Si::os_string> arguments;
		arguments.emplace_back(SILICIUM_OS_STR("--build"));
		arguments.emplace_back(SILICIUM_OS_STR("."));
		auto console_output = Si::Sink<char, Si::success>::erase(Si::ostream_ref_sink(std::cerr));
		BOOST_REQUIRE_EQUAL(0,
		                    ventura::run_process(ventura::cmake_exe, arguments, application_build_dir, console_output,
		                                         std::vector<std::pair<Si::os_char const *, Si::os_char const *>>(),
		                                         ventura::environment_inheritance::inherit));
	}
	{
		std::vector<Si::os_string> arguments;
		ventura::relative_path const relative(
#ifdef _MSC_VER
		    "Debug/"
#endif
		    "using_many_libs"
#ifdef _MSC_VER
		    ".exe"
#endif
		    );
		BOOST_REQUIRE_EQUAL(0, ventura::run_process(application_build_dir / relative, arguments, application_build_dir,
		                                            output,
		                                            std::vector<std::pair<Si::os_char const *, Si::os_char const *>>(),
		                                            ventura::environment_inheritance::inherit));
	}
}
#endif
<|endoftext|>


<commit_before>/* Copyright 2013-present Barefoot Networks, 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.
 */

/*
 * Antonin Bas (antonin@barefootnetworks.com)
 *
 */

#include <bm/bm_sim/actions.h>
#include <bm/bm_sim/calculations.h>
#include <bm/bm_sim/core/primitives.h>
#include <bm/bm_sim/counters.h>
#include <bm/bm_sim/meters.h>
#include <bm/bm_sim/packet.h>
#include <bm/bm_sim/phv.h>
#include <bm/bm_sim/logger.h>

#include <random>
#include <thread>

template <typename... Args>
using ActionPrimitive = bm::ActionPrimitive<Args...>;

using bm::Data;
using bm::Field;
using bm::Header;
using bm::MeterArray;
using bm::CounterArray;
using bm::RegisterArray;
using bm::NamedCalculation;
using bm::HeaderStack;

class modify_field : public ActionPrimitive<Data &, const Data &> {
  void operator ()(Data &dst, const Data &src) {
    bm::core::assign()(dst, src);
  }
};

REGISTER_PRIMITIVE(modify_field);

class modify_field_rng_uniform
  : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &b, const Data &e) {
    // TODO(antonin): a little hacky, fix later if there is a need using GMP
    // random fns
    using engine = std::default_random_engine;
    using hash = std::hash<std::thread::id>;
    static thread_local engine generator(hash()(std::this_thread::get_id()));
    using distrib64 = std::uniform_int_distribution<uint64_t>;
    distrib64 distribution(b.get_uint64(), e.get_uint64());
    f.set(distribution(generator));
  }
};

REGISTER_PRIMITIVE(modify_field_rng_uniform);

class add_to_field : public ActionPrimitive<Field &, const Data &> {
  void operator ()(Field &f, const Data &d) {
    f.add(f, d);
  }
};

REGISTER_PRIMITIVE(add_to_field);

class subtract_from_field : public ActionPrimitive<Field &, const Data &> {
  void operator ()(Field &f, const Data &d) {
    f.sub(f, d);
  }
};

REGISTER_PRIMITIVE(subtract_from_field);

class add : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.add(d1, d2);
  }
};

REGISTER_PRIMITIVE(add);

class subtract : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.sub(d1, d2);
  }
};

REGISTER_PRIMITIVE(subtract);

class bit_xor : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.bit_xor(d1, d2);
  }
};

REGISTER_PRIMITIVE(bit_xor);

class bit_or : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.bit_or(d1, d2);
  }
};

REGISTER_PRIMITIVE(bit_or);

class bit_and : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.bit_and(d1, d2);
  }
};

REGISTER_PRIMITIVE(bit_and);

class shift_left :
  public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.shift_left(d1, d2);
  }
};

REGISTER_PRIMITIVE(shift_left);

class shift_right :
  public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.shift_right(d1, d2);
  }
};

REGISTER_PRIMITIVE(shift_right);

class drop : public ActionPrimitive<> {
  void operator ()() {
    get_field("standard_metadata.egress_spec").set(511);
    if (get_phv().has_field("intrinsic_metadata.mcast_grp")) {
      get_field("intrinsic_metadata.mcast_grp").set(0);
    }
  }
};

REGISTER_PRIMITIVE(drop);

class exit_ : public ActionPrimitive<> {
  void operator ()() {
    get_packet().mark_for_exit();
  }
};

REGISTER_PRIMITIVE_W_NAME("exit", exit_);

class generate_digest : public ActionPrimitive<const Data &, const Data &> {
  void operator ()(const Data &receiver, const Data &learn_id) {
    // discared receiver for now
    (void) receiver;
    get_field("intrinsic_metadata.lf_field_list").set(learn_id);
  }
};

REGISTER_PRIMITIVE(generate_digest);

class add_header : public ActionPrimitive<Header &> {
  void operator ()(Header &hdr) {
    // TODO(antonin): reset header to 0?
    if (!hdr.is_valid()) {
      hdr.reset();
      hdr.mark_valid();
      // updated the length packet register (register 0)
      auto &packet = get_packet();
      packet.set_register(0, packet.get_register(0) + hdr.get_nbytes_packet());
    }
  }
};

REGISTER_PRIMITIVE(add_header);

class add_header_fast : public ActionPrimitive<Header &> {
  void operator ()(Header &hdr) {
    hdr.mark_valid();
  }
};

REGISTER_PRIMITIVE(add_header_fast);

class remove_header : public ActionPrimitive<Header &> {
  void operator ()(Header &hdr) {
    if (hdr.is_valid()) {
      // updated the length packet register (register 0)
      auto &packet = get_packet();
      packet.set_register(0, packet.get_register(0) - hdr.get_nbytes_packet());
      hdr.mark_invalid();
    }
  }
};

REGISTER_PRIMITIVE(remove_header);

class copy_header : public ActionPrimitive<Header &, const Header &> {
  void operator ()(Header &dst, const Header &src) {
    bm::core::assign_header()(dst, src);
  }
};

REGISTER_PRIMITIVE(copy_header);

/* standard_metadata.clone_spec will contain the mirror id (16 LSB) and the
   field list id to copy (16 MSB) */
class clone_ingress_pkt_to_egress
  : public ActionPrimitive<const Data &, const Data &> {
  void operator ()(const Data &clone_spec, const Data &field_list_id) {
    Field &f_clone_spec = get_field("standard_metadata.clone_spec");
    f_clone_spec.shift_left(field_list_id, 16);
    f_clone_spec.add(f_clone_spec, clone_spec);
  }
};

REGISTER_PRIMITIVE(clone_ingress_pkt_to_egress);

class clone_egress_pkt_to_egress
  : public ActionPrimitive<const Data &, const Data &> {
  void operator ()(const Data &clone_spec, const Data &field_list_id) {
    Field &f_clone_spec = get_field("standard_metadata.clone_spec");
    f_clone_spec.shift_left(field_list_id, 16);
    f_clone_spec.add(f_clone_spec, clone_spec);
  }
};

REGISTER_PRIMITIVE(clone_egress_pkt_to_egress);

class resubmit : public ActionPrimitive<const Data &> {
  void operator ()(const Data &field_list_id) {
    if (get_phv().has_field("intrinsic_metadata.resubmit_flag")) {
      get_phv().get_field("intrinsic_metadata.resubmit_flag")
          .set(field_list_id);
    }
  }
};

REGISTER_PRIMITIVE(resubmit);

class recirculate : public ActionPrimitive<const Data &> {
  void operator ()(const Data &field_list_id) {
    if (get_phv().has_field("intrinsic_metadata.recirculate_flag")) {
      get_phv().get_field("intrinsic_metadata.recirculate_flag")
          .set(field_list_id);
    }
  }
};

REGISTER_PRIMITIVE(recirculate);

class modify_field_with_hash_based_offset
  : public ActionPrimitive<Data &, const Data &,
                           const NamedCalculation &, const Data &> {
  void operator ()(Data &dst, const Data &base,
                   const NamedCalculation &hash, const Data &size) {
    uint64_t v =
      (hash.output(get_packet()) % size.get<uint64_t>()) + base.get<uint64_t>();
    dst.set(v);
  }
};

REGISTER_PRIMITIVE(modify_field_with_hash_based_offset);

class no_op : public ActionPrimitive<> {
  void operator ()() {
    // nothing
  }
};

REGISTER_PRIMITIVE(no_op);

class execute_meter
  : public ActionPrimitive<MeterArray &, const Data &, Field &> {
  void operator ()(MeterArray &meter_array, const Data &idx, Field &dst) {
    auto i = idx.get_uint();
#ifndef NDEBUG
    if (i >= meter_array.size()) {
        BMLOG_ERROR_PKT(get_packet(),
                        "Attempted to update meter '{}' with size {}"
                        " at out-of-bounds index {}."
                        "  No meters were updated, and neither was"
                        " dest field.",
                        meter_array.get_name(), meter_array.size(), i);
        return;
    }
#endif  // NDEBUG
    auto color = meter_array.execute_meter(get_packet(), i);
    dst.set(color);
    BMLOG_TRACE_PKT(get_packet(),
                    "Updated meter '{}' at index {},"
                    " assigning dest field the color result {}",
                    meter_array.get_name(), i, color);
  }
};

REGISTER_PRIMITIVE(execute_meter);

class count : public ActionPrimitive<CounterArray &, const Data &> {
  void operator ()(CounterArray &counter_array, const Data &idx) {
    auto i = idx.get_uint();
#ifndef NDEBUG
    if (i >= counter_array.size()) {
        BMLOG_ERROR_PKT(get_packet(),
                        "Attempted to update counter '{}' with size {}"
                        " at out-of-bounds index {}."
                        "  No counters were updated.",
                        counter_array.get_name(), counter_array.size(), i);
        return;
    }
#endif  // NDEBUG
    counter_array.get_counter(i).increment_counter(get_packet());
    BMLOG_TRACE_PKT(get_packet(),
                    "Updated counter '{}' at index {}",
                    counter_array.get_name(), i);
  }
};

REGISTER_PRIMITIVE(count);

class register_read
  : public ActionPrimitive<Field &, const RegisterArray &, const Data &> {
  void operator ()(Field &dst, const RegisterArray &src, const Data &idx) {
    auto i = idx.get_uint();
#ifndef NDEBUG
    if (i >= src.size()) {
        BMLOG_ERROR_PKT(get_packet(),
                        "Attempted to read register '{}' with size {}"
                        " at out-of-bounds index {}."
                        "  Dest field was not updated.",
                        src.get_name(), src.size(), i);
        return;
    }
#endif  // NDEBUG
    dst.set(src[i]);
    BMLOG_TRACE_PKT(get_packet(),
                    "Read register '{}' at index {} read value {}",
                    src.get_name(), i, src[i]);
  }
};

REGISTER_PRIMITIVE(register_read);

class register_write
  : public ActionPrimitive<RegisterArray &, const Data &, const Data &> {
  void operator ()(RegisterArray &dst, const Data &idx, const Data &src) {
    auto i = idx.get_uint();
#ifndef NDEBUG
    if (i >= dst.size()) {
        BMLOG_ERROR_PKT(get_packet(),
                        "Attempted to write register '{}' with size {}"
                        " at out-of-bounds index {}."
                        "  No register array elements were updated.",
                        dst.get_name(), dst.size(), i);
        return;
    }
#endif  // NDEBUG
    dst[i].set(src);
    BMLOG_TRACE_PKT(get_packet(),
                    "Wrote register '{}' at index {} with value {}",
                    dst.get_name(), i, dst[i]);
  }
};

REGISTER_PRIMITIVE(register_write);

// I cannot name this "truncate" and register it with the usual
// REGISTER_PRIMITIVE macro, because of a name conflict:
//
// In file included from /usr/include/boost/config/stdlib/libstdcpp3.hpp:77:0,
//   from /usr/include/boost/config.hpp:44,
//   from /usr/include/boost/cstdint.hpp:36,
//   from /usr/include/boost/multiprecision/number.hpp:9,
//   from /usr/include/boost/multiprecision/gmp.hpp:9,
//   from ../../src/bm_sim/include/bm_sim/bignum.h:25,
//   from ../../src/bm_sim/include/bm_sim/data.h:32,
//   from ../../src/bm_sim/include/bm_sim/fields.h:28,
//   from ../../src/bm_sim/include/bm_sim/phv.h:34,
//   from ../../src/bm_sim/include/bm_sim/actions.h:34,
//   from primitives.cpp:21:
//     /usr/include/unistd.h:993:12: note: declared here
//     extern int truncate (const char *__file, __off_t __length)
class truncate_ : public ActionPrimitive<const Data &> {
  void operator ()(const Data &truncated_length) {
    get_packet().truncate(truncated_length.get<size_t>());
  }
};

REGISTER_PRIMITIVE_W_NAME("truncate", truncate_);

// dummy function, which ensures that this unit is not discarded by the linker
// it is being called by the constructor of SimpleSwitch
// the previous alternative was to have all the primitives in a header file (the
// primitives could also be placed in simple_switch.cpp directly), but I need
// this dummy function if I want to keep the primitives in their own file
int import_primitives() {
  return 0;
}
<commit_msg>Avoid crash on hash with max=0, and warn if lo > hi for random (#745)<commit_after>/* Copyright 2013-present Barefoot Networks, 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.
 */

/*
 * Antonin Bas (antonin@barefootnetworks.com)
 *
 */

#include <bm/bm_sim/actions.h>
#include <bm/bm_sim/calculations.h>
#include <bm/bm_sim/core/primitives.h>
#include <bm/bm_sim/counters.h>
#include <bm/bm_sim/meters.h>
#include <bm/bm_sim/packet.h>
#include <bm/bm_sim/phv.h>
#include <bm/bm_sim/logger.h>

#include <random>
#include <thread>

template <typename... Args>
using ActionPrimitive = bm::ActionPrimitive<Args...>;

using bm::Data;
using bm::Field;
using bm::Header;
using bm::MeterArray;
using bm::CounterArray;
using bm::RegisterArray;
using bm::NamedCalculation;
using bm::HeaderStack;
using bm::Logger;

class modify_field : public ActionPrimitive<Data &, const Data &> {
  void operator ()(Data &dst, const Data &src) {
    bm::core::assign()(dst, src);
  }
};

REGISTER_PRIMITIVE(modify_field);

class modify_field_rng_uniform
  : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &b, const Data &e) {
    // TODO(antonin): a little hacky, fix later if there is a need using GMP
    // random fns
    using engine = std::default_random_engine;
    using hash = std::hash<std::thread::id>;
    static thread_local engine generator(hash()(std::this_thread::get_id()));
    using distrib64 = std::uniform_int_distribution<uint64_t>;
    auto lo = b.get_uint64();
    auto hi = e.get_uint64();
    if (lo > hi) {
        Logger::get()->warn("random result is not specified when lo > hi");
        // Return without writing to the result field at all.  We
        // should avoid the distrib64 call below, since its behavior
        // is not defined in this case.
        return;
    }
    distrib64 distribution(lo, hi);
    auto rand_val = distribution(generator);
    BMLOG_TRACE_PKT(get_packet(),
                    "random(lo={}, hi={}) = {}",
                    lo, hi, rand_val);
    f.set(rand_val);
  }
};

REGISTER_PRIMITIVE(modify_field_rng_uniform);

class add_to_field : public ActionPrimitive<Field &, const Data &> {
  void operator ()(Field &f, const Data &d) {
    f.add(f, d);
  }
};

REGISTER_PRIMITIVE(add_to_field);

class subtract_from_field : public ActionPrimitive<Field &, const Data &> {
  void operator ()(Field &f, const Data &d) {
    f.sub(f, d);
  }
};

REGISTER_PRIMITIVE(subtract_from_field);

class add : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.add(d1, d2);
  }
};

REGISTER_PRIMITIVE(add);

class subtract : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.sub(d1, d2);
  }
};

REGISTER_PRIMITIVE(subtract);

class bit_xor : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.bit_xor(d1, d2);
  }
};

REGISTER_PRIMITIVE(bit_xor);

class bit_or : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.bit_or(d1, d2);
  }
};

REGISTER_PRIMITIVE(bit_or);

class bit_and : public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.bit_and(d1, d2);
  }
};

REGISTER_PRIMITIVE(bit_and);

class shift_left :
  public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.shift_left(d1, d2);
  }
};

REGISTER_PRIMITIVE(shift_left);

class shift_right :
  public ActionPrimitive<Data &, const Data &, const Data &> {
  void operator ()(Data &f, const Data &d1, const Data &d2) {
    f.shift_right(d1, d2);
  }
};

REGISTER_PRIMITIVE(shift_right);

class drop : public ActionPrimitive<> {
  void operator ()() {
    get_field("standard_metadata.egress_spec").set(511);
    if (get_phv().has_field("intrinsic_metadata.mcast_grp")) {
      get_field("intrinsic_metadata.mcast_grp").set(0);
    }
  }
};

REGISTER_PRIMITIVE(drop);

class exit_ : public ActionPrimitive<> {
  void operator ()() {
    get_packet().mark_for_exit();
  }
};

REGISTER_PRIMITIVE_W_NAME("exit", exit_);

class generate_digest : public ActionPrimitive<const Data &, const Data &> {
  void operator ()(const Data &receiver, const Data &learn_id) {
    // discared receiver for now
    (void) receiver;
    get_field("intrinsic_metadata.lf_field_list").set(learn_id);
  }
};

REGISTER_PRIMITIVE(generate_digest);

class add_header : public ActionPrimitive<Header &> {
  void operator ()(Header &hdr) {
    // TODO(antonin): reset header to 0?
    if (!hdr.is_valid()) {
      hdr.reset();
      hdr.mark_valid();
      // updated the length packet register (register 0)
      auto &packet = get_packet();
      packet.set_register(0, packet.get_register(0) + hdr.get_nbytes_packet());
    }
  }
};

REGISTER_PRIMITIVE(add_header);

class add_header_fast : public ActionPrimitive<Header &> {
  void operator ()(Header &hdr) {
    hdr.mark_valid();
  }
};

REGISTER_PRIMITIVE(add_header_fast);

class remove_header : public ActionPrimitive<Header &> {
  void operator ()(Header &hdr) {
    if (hdr.is_valid()) {
      // updated the length packet register (register 0)
      auto &packet = get_packet();
      packet.set_register(0, packet.get_register(0) - hdr.get_nbytes_packet());
      hdr.mark_invalid();
    }
  }
};

REGISTER_PRIMITIVE(remove_header);

class copy_header : public ActionPrimitive<Header &, const Header &> {
  void operator ()(Header &dst, const Header &src) {
    bm::core::assign_header()(dst, src);
  }
};

REGISTER_PRIMITIVE(copy_header);

/* standard_metadata.clone_spec will contain the mirror id (16 LSB) and the
   field list id to copy (16 MSB) */
class clone_ingress_pkt_to_egress
  : public ActionPrimitive<const Data &, const Data &> {
  void operator ()(const Data &clone_spec, const Data &field_list_id) {
    Field &f_clone_spec = get_field("standard_metadata.clone_spec");
    f_clone_spec.shift_left(field_list_id, 16);
    f_clone_spec.add(f_clone_spec, clone_spec);
  }
};

REGISTER_PRIMITIVE(clone_ingress_pkt_to_egress);

class clone_egress_pkt_to_egress
  : public ActionPrimitive<const Data &, const Data &> {
  void operator ()(const Data &clone_spec, const Data &field_list_id) {
    Field &f_clone_spec = get_field("standard_metadata.clone_spec");
    f_clone_spec.shift_left(field_list_id, 16);
    f_clone_spec.add(f_clone_spec, clone_spec);
  }
};

REGISTER_PRIMITIVE(clone_egress_pkt_to_egress);

class resubmit : public ActionPrimitive<const Data &> {
  void operator ()(const Data &field_list_id) {
    if (get_phv().has_field("intrinsic_metadata.resubmit_flag")) {
      get_phv().get_field("intrinsic_metadata.resubmit_flag")
          .set(field_list_id);
    }
  }
};

REGISTER_PRIMITIVE(resubmit);

class recirculate : public ActionPrimitive<const Data &> {
  void operator ()(const Data &field_list_id) {
    if (get_phv().has_field("intrinsic_metadata.recirculate_flag")) {
      get_phv().get_field("intrinsic_metadata.recirculate_flag")
          .set(field_list_id);
    }
  }
};

REGISTER_PRIMITIVE(recirculate);

class modify_field_with_hash_based_offset
  : public ActionPrimitive<Data &, const Data &,
                           const NamedCalculation &, const Data &> {
  void operator ()(Data &dst, const Data &base,
                   const NamedCalculation &hash, const Data &size) {
    auto b = base.get<uint64_t>();
    auto orig_sz = size.get<uint64_t>();
    auto sz = orig_sz;
    if (sz == 0) {
        sz = 1;
        Logger::get()->warn("hash max given as 0, but treating it as 1");
    }
    auto v = (hash.output(get_packet()) % sz) + b;
    BMLOG_TRACE_PKT(get_packet(),
                    "hash(base={}, max={}) = {}",
                    b, orig_sz, v);
    dst.set(v);
  }
};

REGISTER_PRIMITIVE(modify_field_with_hash_based_offset);

class no_op : public ActionPrimitive<> {
  void operator ()() {
    // nothing
  }
};

REGISTER_PRIMITIVE(no_op);

class execute_meter
  : public ActionPrimitive<MeterArray &, const Data &, Field &> {
  void operator ()(MeterArray &meter_array, const Data &idx, Field &dst) {
    auto i = idx.get_uint();
#ifndef NDEBUG
    if (i >= meter_array.size()) {
        BMLOG_ERROR_PKT(get_packet(),
                        "Attempted to update meter '{}' with size {}"
                        " at out-of-bounds index {}."
                        "  No meters were updated, and neither was"
                        " dest field.",
                        meter_array.get_name(), meter_array.size(), i);
        return;
    }
#endif  // NDEBUG
    auto color = meter_array.execute_meter(get_packet(), i);
    dst.set(color);
    BMLOG_TRACE_PKT(get_packet(),
                    "Updated meter '{}' at index {},"
                    " assigning dest field the color result {}",
                    meter_array.get_name(), i, color);
  }
};

REGISTER_PRIMITIVE(execute_meter);

class count : public ActionPrimitive<CounterArray &, const Data &> {
  void operator ()(CounterArray &counter_array, const Data &idx) {
    auto i = idx.get_uint();
#ifndef NDEBUG
    if (i >= counter_array.size()) {
        BMLOG_ERROR_PKT(get_packet(),
                        "Attempted to update counter '{}' with size {}"
                        " at out-of-bounds index {}."
                        "  No counters were updated.",
                        counter_array.get_name(), counter_array.size(), i);
        return;
    }
#endif  // NDEBUG
    counter_array.get_counter(i).increment_counter(get_packet());
    BMLOG_TRACE_PKT(get_packet(),
                    "Updated counter '{}' at index {}",
                    counter_array.get_name(), i);
  }
};

REGISTER_PRIMITIVE(count);

class register_read
  : public ActionPrimitive<Field &, const RegisterArray &, const Data &> {
  void operator ()(Field &dst, const RegisterArray &src, const Data &idx) {
    auto i = idx.get_uint();
#ifndef NDEBUG
    if (i >= src.size()) {
        BMLOG_ERROR_PKT(get_packet(),
                        "Attempted to read register '{}' with size {}"
                        " at out-of-bounds index {}."
                        "  Dest field was not updated.",
                        src.get_name(), src.size(), i);
        return;
    }
#endif  // NDEBUG
    dst.set(src[i]);
    BMLOG_TRACE_PKT(get_packet(),
                    "Read register '{}' at index {} read value {}",
                    src.get_name(), i, src[i]);
  }
};

REGISTER_PRIMITIVE(register_read);

class register_write
  : public ActionPrimitive<RegisterArray &, const Data &, const Data &> {
  void operator ()(RegisterArray &dst, const Data &idx, const Data &src) {
    auto i = idx.get_uint();
#ifndef NDEBUG
    if (i >= dst.size()) {
        BMLOG_ERROR_PKT(get_packet(),
                        "Attempted to write register '{}' with size {}"
                        " at out-of-bounds index {}."
                        "  No register array elements were updated.",
                        dst.get_name(), dst.size(), i);
        return;
    }
#endif  // NDEBUG
    dst[i].set(src);
    BMLOG_TRACE_PKT(get_packet(),
                    "Wrote register '{}' at index {} with value {}",
                    dst.get_name(), i, dst[i]);
  }
};

REGISTER_PRIMITIVE(register_write);

// I cannot name this "truncate" and register it with the usual
// REGISTER_PRIMITIVE macro, because of a name conflict:
//
// In file included from /usr/include/boost/config/stdlib/libstdcpp3.hpp:77:0,
//   from /usr/include/boost/config.hpp:44,
//   from /usr/include/boost/cstdint.hpp:36,
//   from /usr/include/boost/multiprecision/number.hpp:9,
//   from /usr/include/boost/multiprecision/gmp.hpp:9,
//   from ../../src/bm_sim/include/bm_sim/bignum.h:25,
//   from ../../src/bm_sim/include/bm_sim/data.h:32,
//   from ../../src/bm_sim/include/bm_sim/fields.h:28,
//   from ../../src/bm_sim/include/bm_sim/phv.h:34,
//   from ../../src/bm_sim/include/bm_sim/actions.h:34,
//   from primitives.cpp:21:
//     /usr/include/unistd.h:993:12: note: declared here
//     extern int truncate (const char *__file, __off_t __length)
class truncate_ : public ActionPrimitive<const Data &> {
  void operator ()(const Data &truncated_length) {
    get_packet().truncate(truncated_length.get<size_t>());
  }
};

REGISTER_PRIMITIVE_W_NAME("truncate", truncate_);

// dummy function, which ensures that this unit is not discarded by the linker
// it is being called by the constructor of SimpleSwitch
// the previous alternative was to have all the primitives in a header file (the
// primitives could also be placed in simple_switch.cpp directly), but I need
// this dummy function if I want to keep the primitives in their own file
int import_primitives() {
  return 0;
}
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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

// See docs in ../ops/data_flow_ops.cc.

#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/queue_interface.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/platform/macros.h"
#include "tensorflow/core/platform/types.h"

namespace tensorflow {

class QueueOpKernel : public AsyncOpKernel {
 public:
  explicit QueueOpKernel(OpKernelConstruction* context)
      : AsyncOpKernel(context) {}

  void ComputeAsync(OpKernelContext* ctx, DoneCallback callback) final {
    QueueInterface* queue;
    OP_REQUIRES_OK_ASYNC(ctx, GetResourceFromContext(ctx, "handle", &queue),
                         callback);
    ComputeAsync(ctx, queue, [callback, queue]() {
      queue->Unref();
      callback();
    });
  }

 protected:
  virtual void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                            DoneCallback callback) = 0;
};

class QueueAccessOpKernel : public QueueOpKernel {
 public:
  explicit QueueAccessOpKernel(OpKernelConstruction* context)
      : QueueOpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("timeout_ms", &timeout_));
    // TODO(keveman): Enable timeout.
    OP_REQUIRES(context, timeout_ == -1,
                errors::InvalidArgument("Timeout not supported yet."));
  }

 protected:
  int64 timeout_;
};

// Defines an EnqueueOp, the execution of which enqueues a tuple of
// tensors in the given Queue.
//
// The op has 1 + k inputs, where k is the number of components in the
// tuples stored in the given Queue:
// - Input 0: queue handle.
// - Input 1: 0th element of the tuple.
// - ...
// - Input (1+k): kth element of the tuple.
class EnqueueOp : public QueueAccessOpKernel {
 public:
  explicit EnqueueOp(OpKernelConstruction* context)
      : QueueAccessOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    DataTypeVector expected_inputs = {DT_STRING_REF};
    for (DataType dt : queue->component_dtypes()) {
      expected_inputs.push_back(dt);
    }
    OP_REQUIRES_OK_ASYNC(ctx, ctx->MatchSignature(expected_inputs, {}),
                         callback);

    QueueInterface::Tuple tuple;
    OpInputList components;
    OP_REQUIRES_OK_ASYNC(ctx, ctx->input_list("components", &components),
                         callback);
    for (const Tensor& Tcomponent : components) {
      tuple.push_back(Tcomponent);
    }

    OP_REQUIRES_OK_ASYNC(ctx, queue->ValidateTuple(tuple), callback);
    queue->TryEnqueue(tuple, ctx, callback);
  }

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(EnqueueOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueEnqueue").Device(DEVICE_CPU), EnqueueOp);

// Defines an EnqueueManyOp, the execution of which slices each
// component of a tuple of tensors along the 0th dimension, and
// enqueues tuples of slices in the given Queue.
//
// The op has 1 + k inputs, where k is the number of components in the
// tuples stored in the given Queue:
// - Input 0: queue handle.
// - Input 1: 0th element of the tuple.
// - ...
// - Input (1+k): kth element of the tuple.
//
// N.B. All tuple components must have the same size in the 0th
// dimension.
class EnqueueManyOp : public QueueAccessOpKernel {
 public:
  explicit EnqueueManyOp(OpKernelConstruction* context)
      : QueueAccessOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    DataTypeVector expected_inputs = {DT_STRING_REF};
    for (DataType dt : queue->component_dtypes()) {
      expected_inputs.push_back(dt);
    }
    OP_REQUIRES_OK_ASYNC(ctx, ctx->MatchSignature(expected_inputs, {}),
                         callback);

    QueueInterface::Tuple tuple;
    OpInputList components;
    OP_REQUIRES_OK_ASYNC(ctx, ctx->input_list("components", &components),
                         callback);
    for (const Tensor& Tcomponent : components) {
      tuple.push_back(Tcomponent);
    }

    OP_REQUIRES_OK_ASYNC(ctx, queue->ValidateManyTuple(tuple), callback);
    queue->TryEnqueueMany(tuple, ctx, callback);
  }

  ~EnqueueManyOp() override {}

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(EnqueueManyOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueEnqueueMany").Device(DEVICE_CPU),
                        EnqueueManyOp);

// Defines a DequeueOp, the execution of which dequeues a tuple of
// tensors from the given Queue.
//
// The op has one input, which is the handle of the appropriate
// Queue. The op has k outputs, where k is the number of components in
// the tuples stored in the given Queue, and output i is the ith
// component of the dequeued tuple.
class DequeueOp : public QueueAccessOpKernel {
 public:
  explicit DequeueOp(OpKernelConstruction* context)
      : QueueAccessOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    OP_REQUIRES_OK_ASYNC(
        ctx, ctx->MatchSignature({DT_STRING_REF}, queue->component_dtypes()),
        callback);

    queue->TryDequeue(ctx, [ctx, callback](const QueueInterface::Tuple& tuple) {
      if (!ctx->status().ok()) {
        callback();
        return;
      }
      OpOutputList output_components;
      OP_REQUIRES_OK_ASYNC(
          ctx, ctx->output_list("components", &output_components), callback);
      for (int i = 0; i < ctx->num_outputs(); ++i) {
        output_components.set(i, tuple[i]);
      }
      callback();
    });
  }

  ~DequeueOp() override {}

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(DequeueOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueDequeue").Device(DEVICE_CPU), DequeueOp);

// Defines a DequeueManyOp, the execution of which concatenates the
// requested number of elements from the given Queue along the 0th
// dimension, and emits the result as a single tuple of tensors.
//
// The op has two inputs:
// - Input 0: the handle to a queue.
// - Input 1: the number of elements to dequeue.
//
// The op has k outputs, where k is the number of components in the
// tuples stored in the given Queue, and output i is the ith component
// of the dequeued tuple.
class DequeueManyOp : public QueueAccessOpKernel {
 public:
  explicit DequeueManyOp(OpKernelConstruction* context)
      : QueueAccessOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    const Tensor& Tnum_elements = ctx->input(1);
    int32 num_elements = Tnum_elements.flat<int32>()(0);

    OP_REQUIRES_ASYNC(
        ctx, num_elements >= 0,
        errors::InvalidArgument("DequeueManyOp must request a positive number "
                                "of elements"),
        callback);

    OP_REQUIRES_OK_ASYNC(ctx, ctx->MatchSignature({DT_STRING_REF, DT_INT32},
                                                  queue->component_dtypes()),
                         callback);

    queue->TryDequeueMany(
        num_elements, ctx, false /* allow_small_batch */,
        [ctx, callback](const QueueInterface::Tuple& tuple) {
          if (!ctx->status().ok()) {
            callback();
            return;
          }
          OpOutputList output_components;
          OP_REQUIRES_OK_ASYNC(
              ctx, ctx->output_list("components", &output_components),
              callback);
          for (int i = 0; i < ctx->num_outputs(); ++i) {
            output_components.set(i, tuple[i]);
          }
          callback();
        });
  }

  ~DequeueManyOp() override {}

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(DequeueManyOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueDequeueMany").Device(DEVICE_CPU),
                        DequeueManyOp);

// Defines a DequeueUpToOp, the execution of which concatenates the
// requested number of elements from the given Queue along the 0th
// dimension, and emits the result as a single tuple of tensors.
//
// The difference between this op and DequeueMany is the handling when
// the Queue is closed.  While the DequeueMany op will return if there
// an error when there are less than num_elements elements left in the
// closed queue, this op will return between 1 and
// min(num_elements, elements_remaining_in_queue), and will not block.
// If there are no elements left, then the standard DequeueMany error
// is returned.
//
// This op only works if the underlying Queue implementation accepts
// the allow_small_batch = true parameter to TryDequeueMany.
// If it does not, an errors::Unimplemented exception is returned.
//
// The op has two inputs:
// - Input 0: the handle to a queue.
// - Input 1: the number of elements to dequeue.
//
// The op has k outputs, where k is the number of components in the
// tuples stored in the given Queue, and output i is the ith component
// of the dequeued tuple.
//
// The op has one attribute: allow_small_batch.  If the Queue supports
// it, setting this to true causes the queue to return smaller
// (possibly zero length) batches when it is closed, up to however
// many elements are available when the op executes.  In this case,
// the Queue does not block when closed.
class DequeueUpToOp : public QueueAccessOpKernel {
 public:
  explicit DequeueUpToOp(OpKernelConstruction* context)
      : QueueAccessOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    const Tensor& Tnum_elements = ctx->input(1);
    int32 num_elements = Tnum_elements.flat<int32>()(0);

    OP_REQUIRES_ASYNC(
        ctx, num_elements >= 0,
        errors::InvalidArgument("DequeueUpToOp must request a positive number "
                                "of elements"),
        callback);

    OP_REQUIRES_OK_ASYNC(ctx, ctx->MatchSignature({DT_STRING_REF, DT_INT32},
                                                  queue->component_dtypes()),
                         callback);

    queue->TryDequeueMany(
        num_elements, ctx, true /* allow_small_batch */,
        [ctx, callback](const QueueInterface::Tuple& tuple) {
          if (!ctx->status().ok()) {
            callback();
            return;
          }
          OpOutputList output_components;
          OP_REQUIRES_OK_ASYNC(
              ctx, ctx->output_list("components", &output_components),
              callback);
          for (int i = 0; i < ctx->num_outputs(); ++i) {
            output_components.set(i, tuple[i]);
          }
          callback();
        });
  }

  ~DequeueUpToOp() override {}

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(DequeueUpToOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueDequeueUpTo").Device(DEVICE_CPU),
                        DequeueUpToOp);

// Defines a QueueCloseOp, which closes the given Queue. Closing a
// Queue signals that no more elements will be enqueued in it.
//
// The op has one input, which is the handle of the appropriate Queue.
class QueueCloseOp : public QueueOpKernel {
 public:
  explicit QueueCloseOp(OpKernelConstruction* context)
      : QueueOpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("cancel_pending_enqueues",
                                             &cancel_pending_enqueues_));
  }

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    queue->Close(ctx, cancel_pending_enqueues_, callback);
  }

 private:
  bool cancel_pending_enqueues_;
  TF_DISALLOW_COPY_AND_ASSIGN(QueueCloseOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueClose").Device(DEVICE_CPU), QueueCloseOp);

// Defines a QueueSizeOp, which computes the number of elements in the
// given Queue, and emits it as an output tensor.
//
// The op has one input, which is the handle of the appropriate Queue;
// and one output, which is a single-element tensor containing the current
// size of that Queue.
class QueueSizeOp : public QueueOpKernel {
 public:
  explicit QueueSizeOp(OpKernelConstruction* context)
      : QueueOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    Tensor* Tqueue_size = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, TensorShape({}), &Tqueue_size));
    Tqueue_size->flat<int32>().setConstant(queue->size());
    callback();
  }

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(QueueSizeOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueSize").Device(DEVICE_CPU), QueueSizeOp);

}  // namespace tensorflow
<commit_msg>Fix dequeue error messages Change: 128191932<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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

// See docs in ../ops/data_flow_ops.cc.

#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/queue_interface.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/platform/macros.h"
#include "tensorflow/core/platform/types.h"

namespace tensorflow {

class QueueOpKernel : public AsyncOpKernel {
 public:
  explicit QueueOpKernel(OpKernelConstruction* context)
      : AsyncOpKernel(context) {}

  void ComputeAsync(OpKernelContext* ctx, DoneCallback callback) final {
    QueueInterface* queue;
    OP_REQUIRES_OK_ASYNC(ctx, GetResourceFromContext(ctx, "handle", &queue),
                         callback);
    ComputeAsync(ctx, queue, [callback, queue]() {
      queue->Unref();
      callback();
    });
  }

 protected:
  virtual void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                            DoneCallback callback) = 0;
};

class QueueAccessOpKernel : public QueueOpKernel {
 public:
  explicit QueueAccessOpKernel(OpKernelConstruction* context)
      : QueueOpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("timeout_ms", &timeout_));
    // TODO(keveman): Enable timeout.
    OP_REQUIRES(context, timeout_ == -1,
                errors::InvalidArgument("Timeout not supported yet."));
  }

 protected:
  int64 timeout_;
};

// Defines an EnqueueOp, the execution of which enqueues a tuple of
// tensors in the given Queue.
//
// The op has 1 + k inputs, where k is the number of components in the
// tuples stored in the given Queue:
// - Input 0: queue handle.
// - Input 1: 0th element of the tuple.
// - ...
// - Input (1+k): kth element of the tuple.
class EnqueueOp : public QueueAccessOpKernel {
 public:
  explicit EnqueueOp(OpKernelConstruction* context)
      : QueueAccessOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    DataTypeVector expected_inputs = {DT_STRING_REF};
    for (DataType dt : queue->component_dtypes()) {
      expected_inputs.push_back(dt);
    }
    OP_REQUIRES_OK_ASYNC(ctx, ctx->MatchSignature(expected_inputs, {}),
                         callback);

    QueueInterface::Tuple tuple;
    OpInputList components;
    OP_REQUIRES_OK_ASYNC(ctx, ctx->input_list("components", &components),
                         callback);
    for (const Tensor& Tcomponent : components) {
      tuple.push_back(Tcomponent);
    }

    OP_REQUIRES_OK_ASYNC(ctx, queue->ValidateTuple(tuple), callback);
    queue->TryEnqueue(tuple, ctx, callback);
  }

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(EnqueueOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueEnqueue").Device(DEVICE_CPU), EnqueueOp);

// Defines an EnqueueManyOp, the execution of which slices each
// component of a tuple of tensors along the 0th dimension, and
// enqueues tuples of slices in the given Queue.
//
// The op has 1 + k inputs, where k is the number of components in the
// tuples stored in the given Queue:
// - Input 0: queue handle.
// - Input 1: 0th element of the tuple.
// - ...
// - Input (1+k): kth element of the tuple.
//
// N.B. All tuple components must have the same size in the 0th
// dimension.
class EnqueueManyOp : public QueueAccessOpKernel {
 public:
  explicit EnqueueManyOp(OpKernelConstruction* context)
      : QueueAccessOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    DataTypeVector expected_inputs = {DT_STRING_REF};
    for (DataType dt : queue->component_dtypes()) {
      expected_inputs.push_back(dt);
    }
    OP_REQUIRES_OK_ASYNC(ctx, ctx->MatchSignature(expected_inputs, {}),
                         callback);

    QueueInterface::Tuple tuple;
    OpInputList components;
    OP_REQUIRES_OK_ASYNC(ctx, ctx->input_list("components", &components),
                         callback);
    for (const Tensor& Tcomponent : components) {
      tuple.push_back(Tcomponent);
    }

    OP_REQUIRES_OK_ASYNC(ctx, queue->ValidateManyTuple(tuple), callback);
    queue->TryEnqueueMany(tuple, ctx, callback);
  }

  ~EnqueueManyOp() override {}

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(EnqueueManyOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueEnqueueMany").Device(DEVICE_CPU),
                        EnqueueManyOp);

// Defines a DequeueOp, the execution of which dequeues a tuple of
// tensors from the given Queue.
//
// The op has one input, which is the handle of the appropriate
// Queue. The op has k outputs, where k is the number of components in
// the tuples stored in the given Queue, and output i is the ith
// component of the dequeued tuple.
class DequeueOp : public QueueAccessOpKernel {
 public:
  explicit DequeueOp(OpKernelConstruction* context)
      : QueueAccessOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    OP_REQUIRES_OK_ASYNC(
        ctx, ctx->MatchSignature({DT_STRING_REF}, queue->component_dtypes()),
        callback);

    queue->TryDequeue(ctx, [ctx, callback](const QueueInterface::Tuple& tuple) {
      if (!ctx->status().ok()) {
        callback();
        return;
      }
      OpOutputList output_components;
      OP_REQUIRES_OK_ASYNC(
          ctx, ctx->output_list("components", &output_components), callback);
      for (int i = 0; i < ctx->num_outputs(); ++i) {
        output_components.set(i, tuple[i]);
      }
      callback();
    });
  }

  ~DequeueOp() override {}

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(DequeueOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueDequeue").Device(DEVICE_CPU), DequeueOp);

// Defines a DequeueManyOp, the execution of which concatenates the
// requested number of elements from the given Queue along the 0th
// dimension, and emits the result as a single tuple of tensors.
//
// The op has two inputs:
// - Input 0: the handle to a queue.
// - Input 1: the number of elements to dequeue.
//
// The op has k outputs, where k is the number of components in the
// tuples stored in the given Queue, and output i is the ith component
// of the dequeued tuple.
class DequeueManyOp : public QueueAccessOpKernel {
 public:
  explicit DequeueManyOp(OpKernelConstruction* context)
      : QueueAccessOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    const Tensor& Tnum_elements = ctx->input(1);
    int32 num_elements = Tnum_elements.flat<int32>()(0);

    OP_REQUIRES_ASYNC(ctx, num_elements >= 0,
                      errors::InvalidArgument("DequeueManyOp requested ",
                                              num_elements, " < 0 elements"),
                      callback);

    OP_REQUIRES_OK_ASYNC(ctx, ctx->MatchSignature({DT_STRING_REF, DT_INT32},
                                                  queue->component_dtypes()),
                         callback);

    queue->TryDequeueMany(
        num_elements, ctx, false /* allow_small_batch */,
        [ctx, callback](const QueueInterface::Tuple& tuple) {
          if (!ctx->status().ok()) {
            callback();
            return;
          }
          OpOutputList output_components;
          OP_REQUIRES_OK_ASYNC(
              ctx, ctx->output_list("components", &output_components),
              callback);
          for (int i = 0; i < ctx->num_outputs(); ++i) {
            output_components.set(i, tuple[i]);
          }
          callback();
        });
  }

  ~DequeueManyOp() override {}

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(DequeueManyOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueDequeueMany").Device(DEVICE_CPU),
                        DequeueManyOp);

// Defines a DequeueUpToOp, the execution of which concatenates the
// requested number of elements from the given Queue along the 0th
// dimension, and emits the result as a single tuple of tensors.
//
// The difference between this op and DequeueMany is the handling when
// the Queue is closed.  While the DequeueMany op will return if there
// an error when there are less than num_elements elements left in the
// closed queue, this op will return between 1 and
// min(num_elements, elements_remaining_in_queue), and will not block.
// If there are no elements left, then the standard DequeueMany error
// is returned.
//
// This op only works if the underlying Queue implementation accepts
// the allow_small_batch = true parameter to TryDequeueMany.
// If it does not, an errors::Unimplemented exception is returned.
//
// The op has two inputs:
// - Input 0: the handle to a queue.
// - Input 1: the number of elements to dequeue.
//
// The op has k outputs, where k is the number of components in the
// tuples stored in the given Queue, and output i is the ith component
// of the dequeued tuple.
//
// The op has one attribute: allow_small_batch.  If the Queue supports
// it, setting this to true causes the queue to return smaller
// (possibly zero length) batches when it is closed, up to however
// many elements are available when the op executes.  In this case,
// the Queue does not block when closed.
class DequeueUpToOp : public QueueAccessOpKernel {
 public:
  explicit DequeueUpToOp(OpKernelConstruction* context)
      : QueueAccessOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    const Tensor& Tnum_elements = ctx->input(1);
    int32 num_elements = Tnum_elements.flat<int32>()(0);

    OP_REQUIRES_ASYNC(ctx, num_elements >= 0,
                      errors::InvalidArgument("DequeueUpToOp requested ",
                                              num_elements, " < 0 elements"),
                      callback);

    OP_REQUIRES_OK_ASYNC(ctx, ctx->MatchSignature({DT_STRING_REF, DT_INT32},
                                                  queue->component_dtypes()),
                         callback);

    queue->TryDequeueMany(
        num_elements, ctx, true /* allow_small_batch */,
        [ctx, callback](const QueueInterface::Tuple& tuple) {
          if (!ctx->status().ok()) {
            callback();
            return;
          }
          OpOutputList output_components;
          OP_REQUIRES_OK_ASYNC(
              ctx, ctx->output_list("components", &output_components),
              callback);
          for (int i = 0; i < ctx->num_outputs(); ++i) {
            output_components.set(i, tuple[i]);
          }
          callback();
        });
  }

  ~DequeueUpToOp() override {}

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(DequeueUpToOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueDequeueUpTo").Device(DEVICE_CPU),
                        DequeueUpToOp);

// Defines a QueueCloseOp, which closes the given Queue. Closing a
// Queue signals that no more elements will be enqueued in it.
//
// The op has one input, which is the handle of the appropriate Queue.
class QueueCloseOp : public QueueOpKernel {
 public:
  explicit QueueCloseOp(OpKernelConstruction* context)
      : QueueOpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("cancel_pending_enqueues",
                                             &cancel_pending_enqueues_));
  }

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    queue->Close(ctx, cancel_pending_enqueues_, callback);
  }

 private:
  bool cancel_pending_enqueues_;
  TF_DISALLOW_COPY_AND_ASSIGN(QueueCloseOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueClose").Device(DEVICE_CPU), QueueCloseOp);

// Defines a QueueSizeOp, which computes the number of elements in the
// given Queue, and emits it as an output tensor.
//
// The op has one input, which is the handle of the appropriate Queue;
// and one output, which is a single-element tensor containing the current
// size of that Queue.
class QueueSizeOp : public QueueOpKernel {
 public:
  explicit QueueSizeOp(OpKernelConstruction* context)
      : QueueOpKernel(context) {}

 protected:
  void ComputeAsync(OpKernelContext* ctx, QueueInterface* queue,
                    DoneCallback callback) override {
    Tensor* Tqueue_size = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, TensorShape({}), &Tqueue_size));
    Tqueue_size->flat<int32>().setConstant(queue->size());
    callback();
  }

 private:
  TF_DISALLOW_COPY_AND_ASSIGN(QueueSizeOp);
};

REGISTER_KERNEL_BUILDER(Name("QueueSize").Device(DEVICE_CPU), QueueSizeOp);

}  // namespace tensorflow
<|endoftext|>


<commit_before>#include "mainwidget.h"

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    CpuRate_Label = new QLabel(this);
    RamRate_Label = new QLabel(this);
    Speed_Label = new QLabel(this);
    m_timer = new QTimer(this);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(timeout_slot()));
    this->setMinimumSize(200, 200);
    layoutInit();

    //usually,iphlpapi.dll has existed in windows
    m_lib.setFileName("iphlpapi.dll");
    m_lib.load();
    m_funcGetIfTable = (GetIfTable)m_lib.resolve("GetIfTable");

    m_preNetIn = 0;
    m_preNetOut = 0;
    memset(&m_preIdleTime, 0, sizeof(FILETIME));
    memset(&m_preKernelTime, 0, sizeof(FILETIME));
    memset(&m_preUserTime, 0, sizeof(FILETIME));

    m_timer->start(1000);
}

MainWidget::~MainWidget()
{
    m_timer->stop();
}

void MainWidget::paintEvent(QPaintEvent *event)
{
    layoutInit();
    QWidget::paintEvent(event);
}

void MainWidget::layoutInit(void)
{
    CpuRate_Label->move(this->width() / 2 - CpuRate_Label->width() / 2, 20);
    RamRate_Label->move(this->width() / 2 - CpuRate_Label->width() / 2, CpuRate_Label->y() + CpuRate_Label->height() + 10);
    Speed_Label->move(this->width() / 2 - Speed_Label->width() / 2, RamRate_Label->y() + RamRate_Label->height() + 10);
}

void MainWidget::timeout_slot(void)
{
    //memory
    MEMORYSTATUSEX memsStat;
    memsStat.dwLength = sizeof(memsStat);
    if(GlobalMemoryStatusEx(&memsStat))
    {
        int nMemFree = memsStat.ullAvailPhys / (1024 * 1024);
        int nMemTotal = memsStat.ullTotalPhys / (1024 * 1024);

        RamRate_Label->setText(QString("RAM rate:%1\%").arg((nMemTotal - nMemFree) * 100 / nMemTotal));
        RamRate_Label->adjustSize();
    }

    //cpu
    FILETIME IdleTime;
    FILETIME KernelTime;
    FILETIME UserTime;
    if(GetSystemTimes(&IdleTime, &KernelTime, &UserTime))
    {
        if(0 != m_preIdleTime.dwHighDateTime &&  0 != m_preIdleTime.dwLowDateTime)
        {
            int idle = delOfInt64(IdleTime, m_preIdleTime);
            int kernel = delOfInt64(KernelTime,m_preKernelTime);
            int user = delOfInt64(UserTime,m_preUserTime);

            int rate = (kernel + user - idle) * 100 / (kernel + user);
            CpuRate_Label->setText(QString("CPU rate:%1\%").arg(rate));
            CpuRate_Label->adjustSize();
        }
        m_preIdleTime = IdleTime;
        m_preKernelTime = KernelTime;
        m_preUserTime = UserTime;
    }

    //network
    PMIB_IFTABLE m_pTable = NULL;
    DWORD m_dwAdapters = 0;
    //first call is just get the m_dwAdapters's value
    //more detail,pls see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365943(v=vs.85).aspx
    m_funcGetIfTable(m_pTable, &m_dwAdapters, FALSE);

    m_pTable = (PMIB_IFTABLE)new BYTE[m_dwAdapters];
    //speed = sum / time,so it should record the time
    int nowTime = QDateTime().currentDateTime().toString("zzz").toInt();
    m_funcGetIfTable(m_pTable, &m_dwAdapters, FALSE);
    DWORD NowIn = 0;
    DWORD NowOut = 0;
    QList<int> typeList;
    for (UINT i = 0; i < m_pTable->dwNumEntries; i++)
    {
        MIB_IFROW Row = m_pTable->table[i];
        //1 type should only be count only once
        bool bExist = false;
        for(int j = 0;j < typeList.count();j++)
        {
            if(typeList.at(j) == (int)Row.dwType)
            {
                bExist = true;
                break;
            }
        }

        if(false == bExist)
        {
            typeList.append(Row.dwType);
            NowIn += Row.dwInOctets;
            NowOut += Row.dwOutOctets;
        }
    }
    delete []m_pTable;

    if(0 != m_preNetOut && 0 != m_preNetIn)
    {
        double coeffcient = (double)(1000 + nowTime - m_preTime) / 1000;
        //download and upload speed should keep same unit
        Speed_Label->setText(getSpeedInfo((int)(NowIn - m_preNetIn) / coeffcient, (int)(NowOut - m_preNetOut) / coeffcient));
        Speed_Label->adjustSize();
    }
    m_preTime = nowTime;
    m_preNetOut = NowOut;
    m_preNetIn = NowIn;

}

//There is an interesting test of this function:
QString MainWidget::getSpeedInfo(int idownloadSpeed, int iuploadSpeed)
{
    QString speedString = "B/s";
    double downloadSpeed = idownloadSpeed;
    double uploadSpeed = iuploadSpeed;
    if(downloadSpeed >= 1024 || uploadSpeed >= 1024)
    {
        speedString = "KB/s";

        downloadSpeed = (double)(int((downloadSpeed / 1024.0) * 100)) / 100;
        uploadSpeed = (double)(int((uploadSpeed / 1024.0) * 100)) / 100;
        if(downloadSpeed >= 1024 || uploadSpeed >= 1024)
        {
            speedString = "MB/s";

            //retain 2 decimals
            downloadSpeed = (double)(int((downloadSpeed / 1024.0) * 100)) / 100;
            uploadSpeed = (double)(int((uploadSpeed / 1024.0) * 100)) / 100;

            if(downloadSpeed >= 1024 || uploadSpeed >= 1024)
            {
                speedString = "GB/s";

                //retain 2 decimals
                downloadSpeed = (double)(int((downloadSpeed / 1024.0) * 100)) / 100;
                uploadSpeed = (double)(int((uploadSpeed / 1024.0) * 100)) / 100;
            }
        }
    }

    return QString("download:%1%2\nupload:%3%2").arg(uploadSpeed).arg(speedString).arg(downloadSpeed);
}

int MainWidget::delOfInt64(FILETIME subtrahend, FILETIME minuend)
{
    __int64 a = (__int64)(subtrahend.dwHighDateTime) << 32 | (__int64)subtrahend.dwLowDateTime ;
    __int64 b = (__int64)(minuend.dwHighDateTime) << 32 | (__int64)minuend.dwLowDateTime ;

    int answer = 0;
    if(b > a)
    {
        answer = b - a;
    }
    else
    {
        answer = 0xFFFFFFFFFFFFFFFF - a + b;
    }
    return answer;
}
<commit_msg>note<commit_after>#include "mainwidget.h"

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    CpuRate_Label = new QLabel(this);
    RamRate_Label = new QLabel(this);
    Speed_Label = new QLabel(this);
    m_timer = new QTimer(this);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(timeout_slot()));
    this->setMinimumSize(200, 200);
    layoutInit();

    //usually,iphlpapi.dll has existed in windows
    m_lib.setFileName("iphlpapi.dll");
    m_lib.load();
    m_funcGetIfTable = (GetIfTable)m_lib.resolve("GetIfTable");

    m_preNetIn = 0;
    m_preNetOut = 0;
    memset(&m_preIdleTime, 0, sizeof(FILETIME));
    memset(&m_preKernelTime, 0, sizeof(FILETIME));
    memset(&m_preUserTime, 0, sizeof(FILETIME));

    m_timer->start(1000);
}

MainWidget::~MainWidget()
{
    m_timer->stop();
}

void MainWidget::paintEvent(QPaintEvent *event)
{
    layoutInit();
    QWidget::paintEvent(event);
}

void MainWidget::layoutInit(void)
{
    CpuRate_Label->move(this->width() / 2 - CpuRate_Label->width() / 2, 20);
    RamRate_Label->move(this->width() / 2 - CpuRate_Label->width() / 2, CpuRate_Label->y() + CpuRate_Label->height() + 10);
    Speed_Label->move(this->width() / 2 - Speed_Label->width() / 2, RamRate_Label->y() + RamRate_Label->height() + 10);
}

void MainWidget::timeout_slot(void)
{
    //memory
    MEMORYSTATUSEX memsStat;
    memsStat.dwLength = sizeof(memsStat);
    if(GlobalMemoryStatusEx(&memsStat))
    {
        int nMemFree = memsStat.ullAvailPhys / (1024 * 1024);
        int nMemTotal = memsStat.ullTotalPhys / (1024 * 1024);

        RamRate_Label->setText(QString("RAM rate:%1\%").arg((nMemTotal - nMemFree) * 100 / nMemTotal));
        RamRate_Label->adjustSize();
    }

    //cpu
    FILETIME IdleTime;
    FILETIME KernelTime;
    FILETIME UserTime;
    if(GetSystemTimes(&IdleTime, &KernelTime, &UserTime))
    {
        if(0 != m_preIdleTime.dwHighDateTime &&  0 != m_preIdleTime.dwLowDateTime)
        {
            int idle = delOfInt64(IdleTime, m_preIdleTime);
            int kernel = delOfInt64(KernelTime,m_preKernelTime);
            int user = delOfInt64(UserTime,m_preUserTime);

            int rate = (kernel + user - idle) * 100 / (kernel + user);
            CpuRate_Label->setText(QString("CPU rate:%1\%").arg(rate));
            CpuRate_Label->adjustSize();
        }
        m_preIdleTime = IdleTime;
        m_preKernelTime = KernelTime;
        m_preUserTime = UserTime;
    }

    //network
    PMIB_IFTABLE m_pTable = NULL;
    DWORD m_dwAdapters = 0;
    //first call is just get the m_dwAdapters's value
    //more detail,pls see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365943(v=vs.85).aspx
    m_funcGetIfTable(m_pTable, &m_dwAdapters, FALSE);

    m_pTable = (PMIB_IFTABLE)new BYTE[m_dwAdapters];
    //speed = sum / time,so it should record the time
    int nowTime = QDateTime().currentDateTime().toString("zzz").toInt();
    m_funcGetIfTable(m_pTable, &m_dwAdapters, FALSE);
    DWORD NowIn = 0;
    DWORD NowOut = 0;
    QList<int> typeList;
    for (UINT i = 0; i < m_pTable->dwNumEntries; i++)
    {
        MIB_IFROW Row = m_pTable->table[i];
        //1 type should only be count only once
        bool bExist = false;
        for(int j = 0;j < typeList.count();j++)
        {
            if(typeList.at(j) == (int)Row.dwType)
            {
                bExist = true;
                break;
            }
        }

        if(false == bExist)
        {
            typeList.append(Row.dwType);
            NowIn += Row.dwInOctets;
            NowOut += Row.dwOutOctets;
        }
    }
    delete []m_pTable;

    if(0 != m_preNetOut && 0 != m_preNetIn)
    {
        double coeffcient = (double)(1000 + nowTime - m_preTime) / 1000;
        //download and upload speed should keep same unit
        Speed_Label->setText(getSpeedInfo((int)(NowIn - m_preNetIn) / coeffcient, (int)(NowOut - m_preNetOut) / coeffcient));
        Speed_Label->adjustSize();
    }
    m_preTime = nowTime;
    m_preNetOut = NowOut;
    m_preNetIn = NowIn;

}

//There is an interesting test of this function:
//I tried change this 2 input parameters' types to double,
//then in release mode,crash;in debug mode, run correctly.
QString MainWidget::getSpeedInfo(int idownloadSpeed, int iuploadSpeed)
{
    QString speedString = "B/s";
    double downloadSpeed = idownloadSpeed;
    double uploadSpeed = iuploadSpeed;
    if(downloadSpeed >= 1024 || uploadSpeed >= 1024)
    {
        speedString = "KB/s";

        downloadSpeed = (double)(int((downloadSpeed / 1024.0) * 100)) / 100;
        uploadSpeed = (double)(int((uploadSpeed / 1024.0) * 100)) / 100;
        if(downloadSpeed >= 1024 || uploadSpeed >= 1024)
        {
            speedString = "MB/s";

            //retain 2 decimals
            downloadSpeed = (double)(int((downloadSpeed / 1024.0) * 100)) / 100;
            uploadSpeed = (double)(int((uploadSpeed / 1024.0) * 100)) / 100;

            if(downloadSpeed >= 1024 || uploadSpeed >= 1024)
            {
                speedString = "GB/s";

                //retain 2 decimals
                downloadSpeed = (double)(int((downloadSpeed / 1024.0) * 100)) / 100;
                uploadSpeed = (double)(int((uploadSpeed / 1024.0) * 100)) / 100;
            }
        }
    }

    return QString("download:%1%2\nupload:%3%2").arg(uploadSpeed).arg(speedString).arg(downloadSpeed);
}

int MainWidget::delOfInt64(FILETIME subtrahend, FILETIME minuend)
{
    __int64 a = (__int64)(subtrahend.dwHighDateTime) << 32 | (__int64)subtrahend.dwLowDateTime ;
    __int64 b = (__int64)(minuend.dwHighDateTime) << 32 | (__int64)minuend.dwLowDateTime ;

    int answer = 0;
    if(b > a)
    {
        answer = b - a;
    }
    else
    {
        answer = 0xFFFFFFFFFFFFFFFF - a + b;
    }
    return answer;
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "aboutdialog.h"
#include "instructionsdialog.h"
#include "robotpath.h"
#include "robotgriditem.h"
#include "robotgridmatrix.h"
#include "map.h"
#include <QMessageBox>
#include <QPixmap>
#include <QGraphicsPixmapItem>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow) {
    ui->setupUi(this);
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::on_actionRun_triggered() {

    int ib[8][10] = { {2,2,2,2,2,0,0,0,0,1},
                      {0,0,0,0,2,0,0,0,1,1},
                      {0,0,1,1,3,1,1,1,1,0},
                      {1,1,1,0,2,0,0,0,0,0},
                      {1,0,0,0,2,2,2,0,0,0},
                      {1,0,0,0,0,0,2,0,0,0},
                      {1,0,0,0,0,0,2,2,2,0},
                      {1,0,0,0,0,0,0,0,2,2}};

    QGraphicsScene *scene = new QGraphicsScene(this);
    ui->areaPlot->setScene(scene);
    ui->areaPlot->setRenderHint(QPainter::Antialiasing);

    QList<RobotGridItem*> grid;
    QList<QPoint> path_1, path_2;

    RobotGridMatrix Matrix(grid);

    //Maze.ImportMaze(ib);

    Map Maze;
    Maze.mapFromArray(ib);
    Matrix.MapToScene(Maze);
    Matrix.AttachToScene(scene);
    qDebug(">>> %d >>>", Maze.popValue(QPoint(0,0)));
    qDebug(">>> %d >>>", Maze.popValue(QPoint(0,1)));
    qDebug(">>> %d >>>", Maze.popValue(QPoint(1,0)));
    qDebug(">>> %d >>>", Maze.popValue(QPoint(9,0)));

    RobotPath(Maze, path_1, path_2);
    //QListIterator<QPoint> i(path_1); while(i.hasNext()) qDebug() << i.next();
    QGraphicsPixmapItem *c = scene->addPixmap(QPixmap(":/terrain/monolith3.png"));
    c->setPos(0,5*71);
    qDebug() << "Action->run";
}

void MainWindow::on_actionReset_triggered() {
    ui->areaPlot->repaint();
    qDebug() << "Action->reset";
}

void MainWindow::on_actionGenerate_triggered() {qDebug() << "Action->generate";}

void MainWindow::on_actionImportAll_triggered() {qDebug() << "Action->ImportAll";}
void MainWindow::on_actionImportMap_triggered() {qDebug() << "Action->ImportMap";}

void MainWindow::on_actionExportCriticalPlaces_triggered() {qDebug() << "Action->ExportCriticalPlaces";}
void MainWindow::on_actionExportMap_triggered() {qDebug() << "Action->ExportMap";}
void MainWindow::on_actionExportMovements_triggered() {qDebug() << "Action->ExportMovements";}

void MainWindow::on_actionHelpAbout_triggered() {
    AboutDialog *about = new AboutDialog;
    about->setWindowTitle("About");
    about->show();
    qDebug() << "Action->HelpAbout";
}

void MainWindow::on_actionHelpInstructions_triggered(){
    InstructionsDialog *inst = new InstructionsDialog;
    inst->setWindowTitle("Instructions");
    inst->show();
    qDebug() << "Action->HelpInstructions";
}
<commit_msg>another update<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "aboutdialog.h"
#include "instructionsdialog.h"
#include "robotpath.h"
#include "robotgriditem.h"
#include "robotgridmatrix.h"
#include "robotgraphicsitem.h"
#include "map.h"
#include <QMessageBox>
#include <QPixmap>
#include <QGraphicsPixmapItem>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow) {
    ui->setupUi(this);
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::on_actionRun_triggered() {

    int ib[8][10] = { {2,2,2,2,2,0,0,0,0,1},
                      {0,0,0,0,2,0,0,0,1,1},
                      {0,0,1,1,3,1,1,1,1,0},
                      {1,1,1,0,2,0,0,0,0,0},
                      {1,0,0,0,2,2,2,0,0,0},
                      {1,0,0,0,0,0,2,0,0,0},
                      {1,0,0,0,0,0,2,2,2,0},
                      {1,0,0,0,0,0,0,0,2,2}};

    QGraphicsScene *scene = new QGraphicsScene(this);
    ui->areaPlot->setScene(scene);
    ui->areaPlot->setRenderHint(QPainter::Antialiasing);

    QList<RobotGridItem*> grid;
    QList<QPoint> path_1, path_2;

    RobotGridMatrix Matrix(grid);

    //Maze.ImportMaze(ib);

    Map Maze;
    Maze.mapFromArray(ib);
    Matrix.MapToScene(Maze);
    Matrix.AttachToScene(scene);
    qDebug(">>> %d >>>", Maze.popValue(QPoint(0,0)));
    qDebug(">>> %d >>>", Maze.popValue(QPoint(0,1)));
    qDebug(">>> %d >>>", Maze.popValue(QPoint(1,0)));
    qDebug(">>> %d >>>", Maze.popValue(QPoint(9,0)));

    RobotPath(Maze, path_1, path_2);
    //QListIterator<QPoint> i(path_1); while(i.hasNext()) qDebug() << i.next();
    RobotGraphicsItem *bot = new RobotGraphicsItem(QPixmap(":terrain/monument3.png"),0,path_1,QPoint(0,7));
    scene->addItem(bot);
    RobotGraphicsObject *O_bot = new RobotGraphicsObject(QPixmap(":terrain/monument3.png"),0,path_1,QPoint(0,7));
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()),ui->areaPlot, SLOT(animateMovement()));
    timer->start(100);

    qDebug() << "Action->run";
}

void MainWindow::on_actionReset_triggered() {
    ui->areaPlot->repaint();
    qDebug() << "Action->reset";
}

void MainWindow::on_actionGenerate_triggered() {qDebug() << "Action->generate";}

void MainWindow::on_actionImportAll_triggered() {qDebug() << "Action->ImportAll";}
void MainWindow::on_actionImportMap_triggered() {qDebug() << "Action->ImportMap";}

void MainWindow::on_actionExportCriticalPlaces_triggered() {qDebug() << "Action->ExportCriticalPlaces";}
void MainWindow::on_actionExportMap_triggered() {qDebug() << "Action->ExportMap";}
void MainWindow::on_actionExportMovements_triggered() {qDebug() << "Action->ExportMovements";}

void MainWindow::on_actionHelpAbout_triggered() {
    AboutDialog *about = new AboutDialog;
    about->setWindowTitle("About");
    about->show();
    qDebug() << "Action->HelpAbout";
}

void MainWindow::on_actionHelpInstructions_triggered(){
    InstructionsDialog *inst = new InstructionsDialog;
    inst->setWindowTitle("Instructions");
    inst->show();
    qDebug() << "Action->HelpInstructions";
}
<|endoftext|>


<commit_before>#include <QFileDialog>
#include <QImageReader>
#include <QLabel>
#include <QMessageBox>

#include "canvaswidget.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget* parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  setAttribute(Qt::WA_QuitOnClose);
  setWindowState(windowState() | Qt::WindowMaximized);
  setWindowTitle(appName());

  QActionGroup* modeActionGroup = new QActionGroup(this);
  setEtalonAction                   = new QAction(QIcon(":/pictures/etalon.png"),                 QString::fromUtf8("Задание эталона"),                    modeActionGroup);
  measureSegmentLengthAction        = new QAction(QIcon(":/pictures/segment_length.png"),         QString::fromUtf8("Измерение длин отрезков"),            modeActionGroup);
  measurePolylineLengthAction       = new QAction(QIcon(":/pictures/polyline_length.png"),        QString::fromUtf8("Измерение длин кривых"),              modeActionGroup);
  measureClosedPolylineLengthAction = new QAction(QIcon(":/pictures/closed_polyline_length.png"), QString::fromUtf8("Измерение длин замкнутых кривых"),    modeActionGroup);
  measureRectangleAreaAction        = new QAction(QIcon(":/pictures/rectangle_area.png"),         QString::fromUtf8("Измерение площадей прямоугольников"), modeActionGroup);
  measurePolygonAreaAction          = new QAction(QIcon(":/pictures/polygon_area.png"),           QString::fromUtf8("Измерение площадей многоугольников"), modeActionGroup);
  foreach (QAction* action, modeActionGroup->actions())
    action->setCheckable(true);
  setEtalonAction->setChecked(true);
  ui->mainToolBar->addActions(modeActionGroup->actions());
  ui->mainToolBar->setIconSize(QSize(32, 32));
  ui->mainToolBar->setContextMenuPolicy(Qt::CustomContextMenu);
  setMeasurementEnabled(false);
  connect(modeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(updateMode(QAction*)));

  QList<QByteArray> supportedFormatsList = QImageReader::supportedImageFormats();
  QString supportedFormatsString;
  foreach (const QByteArray& format, supportedFormatsList)
     supportedFormatsString += "*." + QString(format).toLower() + " ";

  QString imageFile = QFileDialog::getOpenFileName (this, QString::fromUtf8("Укажите путь к изображению — ") + appName(),
                                                    QString(), QString::fromUtf8("Все изображения (%1)").arg(supportedFormatsString));
  if (imageFile.isEmpty()) {
    exit(EXIT_SUCCESS);
    return;
  }

  QPixmap* image = new QPixmap;
  if (!image->load(imageFile)) {
    QMessageBox::warning(this, appName(), QString::fromUtf8("Не могу открыть изображение \"%1\".").arg(imageFile));
    delete image;
    exit(EXIT_SUCCESS);
    return;
  }

  QLabel* statusLabel = new QLabel(this);
  QFont labelFont = statusLabel->font();
  int newSize = QFontInfo(labelFont).pointSize() * 1.5;  // In contrast to ``labelFont.pointSize()'' it always works
  labelFont.setPointSize(newSize);
  statusLabel->setFont(labelFont);
  ui->statusBar->addWidget(statusLabel);
  canvasWidget = new CanvasWidget(image, this, ui->containingScrollArea, statusLabel, this);
  ui->containingScrollArea->setBackgroundRole(QPalette::Dark);
  ui->containingScrollArea->setWidget(canvasWidget);
}

MainWindow::~MainWindow()
{
  delete ui;
}

QString MainWindow::appName() const
{
  return "AreaMeasurement";
}

void MainWindow::setMode(Mode newMode)
{
  canvasWidget->setMode(newMode);
}

void MainWindow::setMeasurementEnabled(bool state)
{
  measureSegmentLengthAction       ->setEnabled(state);
  measurePolylineLengthAction      ->setEnabled(state);
  measureClosedPolylineLengthAction->setEnabled(state);
  measureRectangleAreaAction       ->setEnabled(state);
  measurePolygonAreaAction         ->setEnabled(state);
}

void MainWindow::updateMode(QAction* modeAction)
{
  if (modeAction == setEtalonAction)
    return setMode(SET_ETALON);
  if (modeAction == measureSegmentLengthAction)
    return setMode(MEASURE_SEGMENT_LENGTH);
  if (modeAction == measurePolylineLengthAction)
    return setMode(MEASURE_POLYLINE_LENGTH);
  if (modeAction == measureClosedPolylineLengthAction)
    return setMode(MEASURE_CLOSED_POLYLINE_LENGTH);
  if (modeAction == measureRectangleAreaAction)
    return setMode(MEASURE_RECTANGLE_AREA);
  if (modeAction == measurePolygonAreaAction)
    return setMode(MEASURE_POLYGON_AREA);
  abort();
}
<commit_msg>Small fix<commit_after>#include <QFileDialog>
#include <QImageReader>
#include <QLabel>
#include <QMessageBox>

#include "canvaswidget.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget* parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  setAttribute(Qt::WA_QuitOnClose);
  setWindowState(windowState() | Qt::WindowMaximized);
  setWindowTitle(appName());

  QActionGroup* modeActionGroup = new QActionGroup(this);
  setEtalonAction                   = new QAction(QIcon(":/pictures/etalon.png"),                 QString::fromUtf8("Задание эталона"),                    modeActionGroup);
  measureSegmentLengthAction        = new QAction(QIcon(":/pictures/segment_length.png"),         QString::fromUtf8("Измерение длин отрезков"),            modeActionGroup);
  measurePolylineLengthAction       = new QAction(QIcon(":/pictures/polyline_length.png"),        QString::fromUtf8("Измерение длин кривых"),              modeActionGroup);
  measureClosedPolylineLengthAction = new QAction(QIcon(":/pictures/closed_polyline_length.png"), QString::fromUtf8("Измерение длин замкнутых кривых"),    modeActionGroup);
  measureRectangleAreaAction        = new QAction(QIcon(":/pictures/rectangle_area.png"),         QString::fromUtf8("Измерение площадей прямоугольников"), modeActionGroup);
  measurePolygonAreaAction          = new QAction(QIcon(":/pictures/polygon_area.png"),           QString::fromUtf8("Измерение площадей многоугольников"), modeActionGroup);
  foreach (QAction* action, modeActionGroup->actions())
    action->setCheckable(true);
  setEtalonAction->setChecked(true);
  ui->mainToolBar->addActions(modeActionGroup->actions());
  ui->mainToolBar->setIconSize(QSize(32, 32));
  ui->mainToolBar->setContextMenuPolicy(Qt::PreventContextMenu);
  setMeasurementEnabled(false);
  connect(modeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(updateMode(QAction*)));

  QList<QByteArray> supportedFormatsList = QImageReader::supportedImageFormats();
  QString supportedFormatsString;
  foreach (const QByteArray& format, supportedFormatsList)
     supportedFormatsString += "*." + QString(format).toLower() + " ";

  QString imageFile = QFileDialog::getOpenFileName (this, QString::fromUtf8("Укажите путь к изображению — ") + appName(),
                                                    QString(), QString::fromUtf8("Все изображения (%1)").arg(supportedFormatsString));
  if (imageFile.isEmpty()) {
    exit(EXIT_SUCCESS);
    return;
  }

  QPixmap* image = new QPixmap;
  if (!image->load(imageFile)) {
    QMessageBox::warning(this, appName(), QString::fromUtf8("Не могу открыть изображение \"%1\".").arg(imageFile));
    delete image;
    exit(EXIT_SUCCESS);
    return;
  }

  QLabel* statusLabel = new QLabel(this);
  QFont labelFont = statusLabel->font();
  int newSize = QFontInfo(labelFont).pointSize() * 1.5;  // In contrast to ``labelFont.pointSize()'' it always works
  labelFont.setPointSize(newSize);
  statusLabel->setFont(labelFont);
  ui->statusBar->addWidget(statusLabel);
  canvasWidget = new CanvasWidget(image, this, ui->containingScrollArea, statusLabel, this);
  ui->containingScrollArea->setBackgroundRole(QPalette::Dark);
  ui->containingScrollArea->setWidget(canvasWidget);
}

MainWindow::~MainWindow()
{
  delete ui;
}

QString MainWindow::appName() const
{
  return "AreaMeasurement";
}

void MainWindow::setMode(Mode newMode)
{
  canvasWidget->setMode(newMode);
}

void MainWindow::setMeasurementEnabled(bool state)
{
  measureSegmentLengthAction       ->setEnabled(state);
  measurePolylineLengthAction      ->setEnabled(state);
  measureClosedPolylineLengthAction->setEnabled(state);
  measureRectangleAreaAction       ->setEnabled(state);
  measurePolygonAreaAction         ->setEnabled(state);
}

void MainWindow::updateMode(QAction* modeAction)
{
  if (modeAction == setEtalonAction)
    return setMode(SET_ETALON);
  if (modeAction == measureSegmentLengthAction)
    return setMode(MEASURE_SEGMENT_LENGTH);
  if (modeAction == measurePolylineLengthAction)
    return setMode(MEASURE_POLYLINE_LENGTH);
  if (modeAction == measureClosedPolylineLengthAction)
    return setMode(MEASURE_CLOSED_POLYLINE_LENGTH);
  if (modeAction == measureRectangleAreaAction)
    return setMode(MEASURE_RECTANGLE_AREA);
  if (modeAction == measurePolygonAreaAction)
    return setMode(MEASURE_POLYGON_AREA);
  abort();
}
<|endoftext|>