<commit_before>/*
The MIT License (MIT)

Copyright (c) 2013-2014 winlin

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#ifndef SRS_CORE_HPP
#define SRS_CORE_HPP

/*
#include <srs_core.hpp>
*/

// current release version
#define VERSION_MAJOR "0"
#define VERSION_MINOR "9"
#define VERSION_REVISION "13"
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
// server info.
#define RTMP_SIG_SRS_KEY "srs"
#define RTMP_SIG_SRS_ROLE "origin server"
#define RTMP_SIG_SRS_NAME RTMP_SIG_SRS_KEY"(simple rtmp server)"
#define RTMP_SIG_SRS_URL "https://"RTMP_SIG_SRS_URL_SHORT
#define RTMP_SIG_SRS_URL_SHORT "github.com/winlinvip/simple-rtmp-server"
#define RTMP_SIG_SRS_WEB "http://blog.csdn.net/win_lin"
#define RTMP_SIG_SRS_EMAIL "winlin@vip.126.com"
#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)"
#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013-2014 winlin"
#define RTMP_SIG_SRS_PRIMARY_AUTHROS "winlin,wenjiegit"

/**
* the core provides the common defined macros, utilities,
* user must include the srs_core.hpp before any header, or maybe
* build failed.
*/

// for int64_t print using PRId64 format.
#ifndef __STDC_FORMAT_MACROS
    #define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>

#include <assert.h>
#define srs_assert(expression) assert(expression)

#include <stddef.h>
#include <sys/types.h>

// generated by configure.
#include <srs_auto_headers.hpp>

// free the p and set to NULL.
// p must be a T*.
#define srs_freep(p) \
	if (p) { \
		delete p; \
		p = NULL; \
	} \
	(void)0
// free the p which represents a array
#define srs_freepa(p) \
	if (p) { \
		delete[] p; \
		p = NULL; \
	} \
	(void)0

// compare
#define srs_min(a, b) (((a) < (b))? (a) : (b))
#define srs_max(a, b) (((a) < (b))? (b) : (a))

// get current system time in ms, use cache to avoid performance problem
extern int64_t srs_get_system_time_ms();
// the deamon st-thread will update it.
extern void srs_update_system_time_ms();

// signal defines.
#define SIGNAL_RELOAD SIGHUP

#include <string>
// replace utility
extern std::string srs_replace(std::string str, std::string old_str, std::string new_str);
// dns resolve utility, return the resolved ip address.
extern std::string srs_dns_resolve(std::string host);

/**
* disable copy constructor of class
*/
#define disable_default_copy(className)\
    private:\
        /** \
        * disable the copy constructor and operator=, donot allow directly copy. \
        */ \
        className(const className&); \
        className& operator= (const className&)

#endif<commit_msg>change version to 0.9.14, finish amf0 basic utest<commit_after>/*
The MIT License (MIT)

Copyright (c) 2013-2014 winlin

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#ifndef SRS_CORE_HPP
#define SRS_CORE_HPP

/*
#include <srs_core.hpp>
*/

// current release version
#define VERSION_MAJOR "0"
#define VERSION_MINOR "9"
#define VERSION_REVISION "14"
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
// server info.
#define RTMP_SIG_SRS_KEY "srs"
#define RTMP_SIG_SRS_ROLE "origin server"
#define RTMP_SIG_SRS_NAME RTMP_SIG_SRS_KEY"(simple rtmp server)"
#define RTMP_SIG_SRS_URL "https://"RTMP_SIG_SRS_URL_SHORT
#define RTMP_SIG_SRS_URL_SHORT "github.com/winlinvip/simple-rtmp-server"
#define RTMP_SIG_SRS_WEB "http://blog.csdn.net/win_lin"
#define RTMP_SIG_SRS_EMAIL "winlin@vip.126.com"
#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)"
#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013-2014 winlin"
#define RTMP_SIG_SRS_PRIMARY_AUTHROS "winlin,wenjie.zhao"

/**
* the core provides the common defined macros, utilities,
* user must include the srs_core.hpp before any header, or maybe
* build failed.
*/

// for int64_t print using PRId64 format.
#ifndef __STDC_FORMAT_MACROS
    #define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>

#include <assert.h>
#define srs_assert(expression) assert(expression)

#include <stddef.h>
#include <sys/types.h>

// generated by configure.
#include <srs_auto_headers.hpp>

// free the p and set to NULL.
// p must be a T*.
#define srs_freep(p) \
	if (p) { \
		delete p; \
		p = NULL; \
	} \
	(void)0
// free the p which represents a array
#define srs_freepa(p) \
	if (p) { \
		delete[] p; \
		p = NULL; \
	} \
	(void)0

// compare
#define srs_min(a, b) (((a) < (b))? (a) : (b))
#define srs_max(a, b) (((a) < (b))? (b) : (a))

// get current system time in ms, use cache to avoid performance problem
extern int64_t srs_get_system_time_ms();
// the deamon st-thread will update it.
extern void srs_update_system_time_ms();

// signal defines.
#define SIGNAL_RELOAD SIGHUP

#include <string>
// replace utility
extern std::string srs_replace(std::string str, std::string old_str, std::string new_str);
// dns resolve utility, return the resolved ip address.
extern std::string srs_dns_resolve(std::string host);

/**
* disable copy constructor of class
*/
#define disable_default_copy(className)\
    private:\
        /** \
        * disable the copy constructor and operator=, donot allow directly copy. \
        */ \
        className(const className&); \
        className& operator= (const className&)

#endif<|endoftext|>


<commit_before>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/flow/skia_gpu_object.h"

#include "flutter/fml/message_loop.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/task_runner.h"
#include "flutter/testing/thread_test.h"
#include "gtest/gtest.h"
#include "third_party/skia/include/core/SkRefCnt.h"

#include <future>

namespace flutter {
namespace testing {

class TestSkObject : public SkRefCnt {
 public:
  TestSkObject(std::shared_ptr<fml::AutoResetWaitableEvent> latch,
               fml::TaskQueueId* dtor_task_queue_id)
      : latch_(latch), dtor_task_queue_id_(dtor_task_queue_id) {}

  ~TestSkObject() {
    if (dtor_task_queue_id_) {
      *dtor_task_queue_id_ = fml::MessageLoop::GetCurrentTaskQueueId();
    }
    latch_->Signal();
  }

 private:
  std::shared_ptr<fml::AutoResetWaitableEvent> latch_;
  fml::TaskQueueId* dtor_task_queue_id_;
};

class SkiaGpuObjectTest : public ThreadTest {
 public:
  SkiaGpuObjectTest()
      : unref_task_runner_(CreateNewThread()),
        unref_queue_(fml::MakeRefCounted<SkiaUnrefQueue>(
            unref_task_runner(),
            fml::TimeDelta::FromSeconds(0))),
        delayed_unref_queue_(fml::MakeRefCounted<SkiaUnrefQueue>(
            unref_task_runner(),
            fml::TimeDelta::FromSeconds(3))) {
    // The unref queues must be created in the same thread of the
    // unref_task_runner so the queue can access the same-thread-only WeakPtr of
    // the GrContext constructed during the creation.
    std::promise<bool> queuesCreated;
    unref_task_runner_->PostTask([this, &queuesCreated]() {
      unref_queue_ = fml::MakeRefCounted<SkiaUnrefQueue>(
          unref_task_runner(), fml::TimeDelta::FromSeconds(0));
      delayed_unref_queue_ = fml::MakeRefCounted<SkiaUnrefQueue>(
          unref_task_runner(), fml::TimeDelta::FromSeconds(3));
      queuesCreated.set_value(true);
    });
    queuesCreated.get_future().wait();
    ::testing::FLAGS_gtest_death_test_style = "threadsafe";
  }

  fml::RefPtr<fml::TaskRunner> unref_task_runner() {
    return unref_task_runner_;
  }
  fml::RefPtr<SkiaUnrefQueue> unref_queue() { return unref_queue_; }
  fml::RefPtr<SkiaUnrefQueue> delayed_unref_queue() {
    return delayed_unref_queue_;
  }

 private:
  fml::RefPtr<fml::TaskRunner> unref_task_runner_;
  fml::RefPtr<SkiaUnrefQueue> unref_queue_;
  fml::RefPtr<SkiaUnrefQueue> delayed_unref_queue_;
};

TEST_F(SkiaGpuObjectTest, QueueSimple) {
  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
      std::make_shared<fml::AutoResetWaitableEvent>();
  fml::TaskQueueId dtor_task_queue_id(0);
  SkRefCnt* ref_object = new TestSkObject(latch, &dtor_task_queue_id);

  unref_queue()->Unref(ref_object);
  latch->Wait();
  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
}

TEST_F(SkiaGpuObjectTest, ObjectDestructor) {
  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
      std::make_shared<fml::AutoResetWaitableEvent>();
  fml::TaskQueueId dtor_task_queue_id(0);

  {
    auto object = sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id);
    SkiaGPUObject<TestSkObject> sk_object(object, unref_queue());
    ASSERT_EQ(sk_object.get(), object);
    ASSERT_EQ(dtor_task_queue_id, 0);
  }

  latch->Wait();
  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
}

TEST_F(SkiaGpuObjectTest, ObjectReset) {
  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
      std::make_shared<fml::AutoResetWaitableEvent>();
  fml::TaskQueueId dtor_task_queue_id(0);
  SkiaGPUObject<TestSkObject> sk_object(
      sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id), unref_queue());

  sk_object.reset();
  ASSERT_EQ(sk_object.get(), nullptr);

  latch->Wait();
  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
}

TEST_F(SkiaGpuObjectTest, ObjectResetBeforeDestructor) {
  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
      std::make_shared<fml::AutoResetWaitableEvent>();
  fml::TaskQueueId dtor_task_queue_id(0);

  {
    auto object = sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id);
    SkiaGPUObject<TestSkObject> sk_object(object, unref_queue());
    ASSERT_EQ(sk_object.get(), object);
    ASSERT_EQ(dtor_task_queue_id, 0);

    sk_object.reset();
    ASSERT_EQ(sk_object.get(), nullptr);
  }

  latch->Wait();
  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
}

TEST_F(SkiaGpuObjectTest, ObjectResetTwice) {
  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
      std::make_shared<fml::AutoResetWaitableEvent>();
  fml::TaskQueueId dtor_task_queue_id(0);
  SkiaGPUObject<TestSkObject> sk_object(
      sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id), unref_queue());

  sk_object.reset();
  ASSERT_EQ(sk_object.get(), nullptr);
  sk_object.reset();
  ASSERT_EQ(sk_object.get(), nullptr);

  latch->Wait();
  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
}

}  // namespace testing
}  // namespace flutter
<commit_msg>Fix race in SkiaGPUObject unit-tests. (#16351)<commit_after>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/flow/skia_gpu_object.h"

#include "flutter/fml/message_loop.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/task_runner.h"
#include "flutter/testing/thread_test.h"
#include "gtest/gtest.h"
#include "third_party/skia/include/core/SkRefCnt.h"

#include <future>

namespace flutter {
namespace testing {

class TestSkObject : public SkRefCnt {
 public:
  TestSkObject(std::shared_ptr<fml::AutoResetWaitableEvent> latch,
               fml::TaskQueueId* dtor_task_queue_id)
      : latch_(latch), dtor_task_queue_id_(dtor_task_queue_id) {}

  ~TestSkObject() {
    if (dtor_task_queue_id_) {
      *dtor_task_queue_id_ = fml::MessageLoop::GetCurrentTaskQueueId();
    }
    latch_->Signal();
  }

 private:
  std::shared_ptr<fml::AutoResetWaitableEvent> latch_;
  fml::TaskQueueId* dtor_task_queue_id_;
};

class SkiaGpuObjectTest : public ThreadTest {
 public:
  SkiaGpuObjectTest()
      : unref_task_runner_(CreateNewThread()),
        unref_queue_(fml::MakeRefCounted<SkiaUnrefQueue>(
            unref_task_runner(),
            fml::TimeDelta::FromSeconds(0))),
        delayed_unref_queue_(fml::MakeRefCounted<SkiaUnrefQueue>(
            unref_task_runner(),
            fml::TimeDelta::FromSeconds(3))) {
    // The unref queues must be created in the same thread of the
    // unref_task_runner so the queue can access the same-thread-only WeakPtr of
    // the GrContext constructed during the creation.
    std::promise<bool> queuesCreated;
    unref_task_runner_->PostTask([this, &queuesCreated]() {
      unref_queue_ = fml::MakeRefCounted<SkiaUnrefQueue>(
          unref_task_runner(), fml::TimeDelta::FromSeconds(0));
      delayed_unref_queue_ = fml::MakeRefCounted<SkiaUnrefQueue>(
          unref_task_runner(), fml::TimeDelta::FromSeconds(3));
      queuesCreated.set_value(true);
    });
    queuesCreated.get_future().wait();
    ::testing::FLAGS_gtest_death_test_style = "threadsafe";
  }

  fml::RefPtr<fml::TaskRunner> unref_task_runner() {
    return unref_task_runner_;
  }
  fml::RefPtr<SkiaUnrefQueue> unref_queue() { return unref_queue_; }
  fml::RefPtr<SkiaUnrefQueue> delayed_unref_queue() {
    return delayed_unref_queue_;
  }

 private:
  fml::RefPtr<fml::TaskRunner> unref_task_runner_;
  fml::RefPtr<SkiaUnrefQueue> unref_queue_;
  fml::RefPtr<SkiaUnrefQueue> delayed_unref_queue_;
};

TEST_F(SkiaGpuObjectTest, QueueSimple) {
  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
      std::make_shared<fml::AutoResetWaitableEvent>();
  fml::TaskQueueId dtor_task_queue_id(0);
  SkRefCnt* ref_object = new TestSkObject(latch, &dtor_task_queue_id);

  unref_queue()->Unref(ref_object);
  latch->Wait();
  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
}

TEST_F(SkiaGpuObjectTest, ObjectDestructor) {
  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
      std::make_shared<fml::AutoResetWaitableEvent>();
  fml::TaskQueueId dtor_task_queue_id(0);
  auto object = sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id);
  {
    SkiaGPUObject<TestSkObject> sk_object(std::move(object), unref_queue());
    // Verify that the default SkiaGPUObject dtor queues and unref.
  }

  latch->Wait();
  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
}

TEST_F(SkiaGpuObjectTest, ObjectReset) {
  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
      std::make_shared<fml::AutoResetWaitableEvent>();
  fml::TaskQueueId dtor_task_queue_id(0);
  SkiaGPUObject<TestSkObject> sk_object(
      sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id), unref_queue());
  // Verify that explicitly resetting the GPU object queues and unref.
  sk_object.reset();
  ASSERT_EQ(sk_object.get(), nullptr);
  latch->Wait();
  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
}

TEST_F(SkiaGpuObjectTest, ObjectResetTwice) {
  std::shared_ptr<fml::AutoResetWaitableEvent> latch =
      std::make_shared<fml::AutoResetWaitableEvent>();
  fml::TaskQueueId dtor_task_queue_id(0);
  SkiaGPUObject<TestSkObject> sk_object(
      sk_make_sp<TestSkObject>(latch, &dtor_task_queue_id), unref_queue());

  sk_object.reset();
  ASSERT_EQ(sk_object.get(), nullptr);
  sk_object.reset();
  ASSERT_EQ(sk_object.get(), nullptr);

  latch->Wait();
  ASSERT_EQ(dtor_task_queue_id, unref_task_runner()->GetTaskQueueId());
}

}  // namespace testing
}  // namespace flutter
<|endoftext|>


<commit_before>/*
 * symbols.cxx
 *
 * $Id$
 *
 */

#include <tptlib/symbols.h>
#include <tptlib/parse.h>

namespace TPTLib {

/**
 *
 * Get the value specified by id from the symbols table, recursing to
 * process embedded symbols as needed.
 *
 * @param	id		ID of symbol to retrieve.
 * @return	Value of requested symbol;
 * @return	Empty string when symbol not found.
 * @author	Isaac W. Foraker
 *
 */
std::string SymbolMap::get(const std::string& id)
{
	// If this is an enclosed id, strip ${};
	if (id[0] == '$')
		return get(id.substr(2, id.size()-3));

	// Return symbol if no embedded id.
	if (id.find('$') == std::string::npos)
	{
		SymbolTable::const_iterator it(symmap.find(id));
		if (it == symmap.end())
			return "";
		return (*it).second;
	}

	// When an id contains an embedded ${id}, recurse and build new id.
	Buffer buf(id.c_str(), id.size());
	Parser p(buf, &symmap);
	std::string newid(p.run());
	return get(newid);
}

/**
 *
 * TODO: document function
 *
 * @param	id			ID of the symbol to be pushed.
 * @param	value		Value of the symbol to be pushed.
 * @return	nothing
 * @author	Isaac W. Foraker
 *
 */
void SymbolMap::set(const std::string& id, const std::string& value)
{
	if (id[0] == '$')
		symmap[id.substr(2, id.size()-3)] = value;
	else
		symmap[id] = value;
}

/**
 *
 * Check whether the specified id exists in the symbol table.
 *
 * @param	id			ID of symbol to retrieve.
 * @return	true if symbol exists;
 * @return	false if symbol does not exist.
 * @author	Isaac W. Foraker
 *
 */
bool SymbolMap::exists(const std::string& id)
{
	// If this is an enclosed id, strip ${};
	if (id[0] == '$')
		return symmap.find(id.substr(2, id.size()-3)) != symmap.end();
	return symmap.find(id) != symmap.end();
}

/**
 *
 * Copy a symbol table into the symbol map, replacing any existing
 * entries.
 *
 * @param	symtab		Table to be copied.
 * @return	Const reference to the local symbol table.
 * @author	Isaac W. Foraker
 *
 */
const SymbolTable& SymbolMap::operator=(const SymbolTable& symtab)
{
	return symmap = symtab;
}

/**
 *
 * Push a symbol (id and value) onto the symbol stack.
 *
 * @param	id			ID of the symbol to be pushed.
 * @param	value		Value of the symbol to be pushed.
 * @return	nothing
 * @author	Isaac W. Foraker
 *
 */
void SymbolStack::push(const std::string& id, const std::string& value)
{
	Symbol_t sym;
	sym.id = id;
	sym.value = value;
	symstack.push(sym);
}

/**
 *
 * TODO: document function
 *
 * @param	symmap		Symbol Map to receive symbols.
 * @return	nothing
 * @author	Isaac W. Foraker
 *
 */
void SymbolStack::popall(SymbolMap& symmap)
{
	while (!symstack.empty())
	{
		Symbol_t& sym = symstack.top();
		symmap.set(sym.id, sym.value);
	}
}

} // end namespace TPTLib
<commit_msg>checkpoint<commit_after>/*
 * symbols.cxx
 *
 * $Id$
 *
 */

#include <tptlib/symbols.h>
#include <tptlib/parse.h>

namespace TPTLib {

/**
 *
 * Get the value specified by id from the symbols table, recursing to
 * process embedded symbols as needed.
 *
 * @param	id		ID of symbol to retrieve.
 * @return	Value of requested symbol;
 * @return	Empty string when symbol not found.
 * @author	Isaac W. Foraker
 *
 */
std::string SymbolMap::get(const std::string& id)
{
	// If this is an enclosed id, strip ${};
	if (id[0] == '$')
		return get(id.substr(2, id.size()-3));

	// Return symbol if no embedded id.
	if (id.find('$') == std::string::npos)
	{
		SymbolTable::const_iterator it(symmap.find(id));
		if (it == symmap.end())
			return "";
		return (*it).second;
	}

	// When an id contains an embedded ${id}, recurse and build new id.
	Buffer buf(id.c_str(), id.size());
	Parser p(buf, &symmap);
	std::string newid(p.run());
	return get(newid);
}

/**
 *
 * TODO: document function
 *
 * @param	id			ID of the symbol to be pushed.
 * @param	value		Value of the symbol to be pushed.
 * @return	nothing
 * @author	Isaac W. Foraker
 *
 */
void SymbolMap::set(const std::string& id, const std::string& value)
{
	if (id[0] == '$')
		symmap[id.substr(2, id.size()-3)] = value;
	else
		symmap[id] = value;
}

/**
 *
 * Check whether the specified id exists in the symbol table.
 *
 * @param	id			ID of symbol to retrieve.
 * @return	true if symbol exists;
 * @return	false if symbol does not exist.
 * @author	Isaac W. Foraker
 *
 */
bool SymbolMap::exists(const std::string& id)
{
	// If this is an enclosed id, strip ${};
	if (id[0] == '$')
		return symmap.find(id.substr(2, id.size()-3)) != symmap.end();
	return symmap.find(id) != symmap.end();
}

/**
 *
 * Copy a symbol table into the symbol map, replacing any existing
 * entries.
 *
 * @param	symtab		Table to be copied.
 * @return	Const reference to the local symbol table.
 * @author	Isaac W. Foraker
 *
 */
const SymbolTable& SymbolMap::operator=(const SymbolTable& symtab)
{
	return symmap = symtab;
}

/**
 *
 * Push a symbol (id and value) onto the symbol stack.
 *
 * @param	id			ID of the symbol to be pushed.
 * @param	value		Value of the symbol to be pushed.
 * @return	nothing
 * @author	Isaac W. Foraker
 *
 */
void SymbolStack::push(const std::string& id, const std::string& value)
{
	Symbol_t sym;
	sym.id = id;
	sym.value = value;
	symstack.push(sym);
}

/**
 *
 * TODO: document function
 *
 * @param	symmap		Symbol Map to receive symbols.
 * @return	nothing
 * @author	Isaac W. Foraker
 *
 */
void SymbolStack::popall(SymbolMap& symmap)
{
	while (!symstack.empty())
	{
		Symbol_t& sym = symstack.top();
		symstack.pop();
		symmap.set(sym.id, sym.value);
	}
}

} // end namespace TPTLib
<|endoftext|>


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

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
#include <pwd.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <linux/prctl.h>
#include <cutils/sockets.h>
#include <cutils/record_stream.h>
#include <unistd.h>
#include <queue>
#include <string>

#include "IpcSocketListener.h"
#include "NfcIpcSocket.h"
#include "MessageHandler.h"
#include "NfcDebug.h"

#define NFCD_SOCKET_NAME "nfcd"
#define MAX_COMMAND_BYTES (8 * 1024)

using android::Parcel;

static int nfcdRw;

/**
 * NfcIpcSocket
 */
NfcIpcSocket* NfcIpcSocket::sInstance = NULL;

NfcIpcSocket* NfcIpcSocket::Instance() {
  if (!sInstance) {
    sInstance = new NfcIpcSocket();
  }
  return sInstance;
}

NfcIpcSocket::NfcIpcSocket()
  : mMsgHandler(NULL)
{
}

NfcIpcSocket::~NfcIpcSocket()
{
}

void NfcIpcSocket::Initialize(MessageHandler* aMsgHandler)
{
  InitSocket();
  mMsgHandler = aMsgHandler;
}

void NfcIpcSocket::InitSocket()
{
  mSleep_spec.tv_sec = 0;
  mSleep_spec.tv_nsec = 500 * 1000;
  mSleep_spec_rem.tv_sec = 0;
  mSleep_spec_rem.tv_nsec = 0;
}

int NfcIpcSocket::GetListenSocket() {
  const int nfcdConn = android_get_control_socket(NFCD_SOCKET_NAME);
  if (nfcdConn < 0) {
    ALOGE("Could not connect to %s socket: %s\n", NFCD_SOCKET_NAME, strerror(errno));
    return -1;
  }

  if (listen(nfcdConn, 4) != 0) {
    return -1;
  }
  return nfcdConn;
}

void NfcIpcSocket::SetSocketListener(IpcSocketListener* aListener) {
  mListener = aListener;
}

void NfcIpcSocket::Loop()
{
  bool connected = false;
  int nfcdConn = -1;
  int ret;

  while(1) {
    struct sockaddr_un peeraddr;
    socklen_t socklen = sizeof (peeraddr);

    if (!connected) {
      nfcdConn = GetListenSocket();
      if (nfcdConn < 0) {
        nanosleep(&mSleep_spec, &mSleep_spec_rem);
        continue;
      }
    }

    nfcdRw = accept(nfcdConn, (struct sockaddr*)&peeraddr, &socklen);

    if (nfcdRw < 0 ) {
      ALOGE("Error on accept() errno:%d", errno);
      /* start listening for new connections again */
      continue;
    }

    ret = fcntl(nfcdRw, F_SETFL, O_NONBLOCK);
    if (ret < 0) {
      ALOGE ("Error setting O_NONBLOCK errno:%d", errno);
    }

    ALOGD("Socket connected");
    connected = true;

    RecordStream *rs = record_stream_new(nfcdRw, MAX_COMMAND_BYTES);

    mListener->OnConnected();

    struct pollfd fds[1];
    fds[0].fd = nfcdRw;
    fds[0].events = POLLIN;
    fds[0].revents = 0;

    while(connected) {
      poll(fds, 1, -1);
      if(fds[0].revents > 0) {
        fds[0].revents = 0;

        void* data;
        size_t dataLen;
        int ret = record_stream_get_next(rs, &data, &dataLen);
        ALOGD(" %d of bytes to be sent... data=%p ret=%d", dataLen, data, ret);
        if (ret == 0 && data == NULL) {
          // end-of-stream
          break;
        } else if (ret < 0) {
          break;
        }
        WriteToIncomingQueue((uint8_t*)data, dataLen);
      }
    }
    record_stream_free(rs);
    close(nfcdRw);
  }

  return;
}

// Write NFC data to Gecko
// Outgoing queue contain the data should be send to gecko
// TODO check thread, this should run on the NfcService thread.
void NfcIpcSocket::WriteToOutgoingQueue(uint8_t* aData, size_t aDataLen)
{
  ALOGD("%s enter, data=%p, dataLen=%d", __func__, aData, aDataLen);

  if (aData == NULL || aDataLen == 0) {
    return;
  }

  size_t writeOffset = 0;
  int written = 0;

  ALOGD("Writing %d bytes to gecko ", aDataLen);
  while (writeOffset < aDataLen) {
    do {
      written = write (nfcdRw, aData + writeOffset, aDataLen - writeOffset);
    } while (written < 0 && errno == EINTR);

    if (written >= 0) {
      writeOffset += written;
    } else {
      ALOGE("Response: unexpected error on write errno:%d", errno);
      break;
    }
  }
}

// Write Gecko data to NFC
// Incoming queue contains
// TODO check thread, this should run on top of main thread of nfcd.
void NfcIpcSocket::WriteToIncomingQueue(uint8_t* aData, size_t aDataLen)
{
  ALOGD("%s enter, data=%p, dataLen=%d", __func__, aData, aDataLen);

  if (aData != NULL && aDataLen > 0) {
    mMsgHandler->ProcessRequest(aData, aDataLen);
  }
}
<commit_msg>Bug 1109592: Initialize |NfcIpcSocket::mListener| in constructor<commit_after>/*
 * Copyright (C) 2013-2014  Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
#include <pwd.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <linux/prctl.h>
#include <cutils/sockets.h>
#include <cutils/record_stream.h>
#include <unistd.h>
#include <queue>
#include <string>

#include "IpcSocketListener.h"
#include "NfcIpcSocket.h"
#include "MessageHandler.h"
#include "NfcDebug.h"

#define NFCD_SOCKET_NAME "nfcd"
#define MAX_COMMAND_BYTES (8 * 1024)

using android::Parcel;

static int nfcdRw;

/**
 * NfcIpcSocket
 */
NfcIpcSocket* NfcIpcSocket::sInstance = NULL;

NfcIpcSocket* NfcIpcSocket::Instance() {
  if (!sInstance) {
    sInstance = new NfcIpcSocket();
  }
  return sInstance;
}

NfcIpcSocket::NfcIpcSocket()
  : mMsgHandler(NULL)
  , mListener(NULL)
{
}

NfcIpcSocket::~NfcIpcSocket()
{
}

void NfcIpcSocket::Initialize(MessageHandler* aMsgHandler)
{
  InitSocket();
  mMsgHandler = aMsgHandler;
}

void NfcIpcSocket::InitSocket()
{
  mSleep_spec.tv_sec = 0;
  mSleep_spec.tv_nsec = 500 * 1000;
  mSleep_spec_rem.tv_sec = 0;
  mSleep_spec_rem.tv_nsec = 0;
}

int NfcIpcSocket::GetListenSocket() {
  const int nfcdConn = android_get_control_socket(NFCD_SOCKET_NAME);
  if (nfcdConn < 0) {
    ALOGE("Could not connect to %s socket: %s\n", NFCD_SOCKET_NAME, strerror(errno));
    return -1;
  }

  if (listen(nfcdConn, 4) != 0) {
    return -1;
  }
  return nfcdConn;
}

void NfcIpcSocket::SetSocketListener(IpcSocketListener* aListener) {
  mListener = aListener;
}

void NfcIpcSocket::Loop()
{
  bool connected = false;
  int nfcdConn = -1;
  int ret;

  while(1) {
    struct sockaddr_un peeraddr;
    socklen_t socklen = sizeof (peeraddr);

    if (!connected) {
      nfcdConn = GetListenSocket();
      if (nfcdConn < 0) {
        nanosleep(&mSleep_spec, &mSleep_spec_rem);
        continue;
      }
    }

    nfcdRw = accept(nfcdConn, (struct sockaddr*)&peeraddr, &socklen);

    if (nfcdRw < 0 ) {
      ALOGE("Error on accept() errno:%d", errno);
      /* start listening for new connections again */
      continue;
    }

    ret = fcntl(nfcdRw, F_SETFL, O_NONBLOCK);
    if (ret < 0) {
      ALOGE ("Error setting O_NONBLOCK errno:%d", errno);
    }

    ALOGD("Socket connected");
    connected = true;

    RecordStream *rs = record_stream_new(nfcdRw, MAX_COMMAND_BYTES);

    mListener->OnConnected();

    struct pollfd fds[1];
    fds[0].fd = nfcdRw;
    fds[0].events = POLLIN;
    fds[0].revents = 0;

    while(connected) {
      poll(fds, 1, -1);
      if(fds[0].revents > 0) {
        fds[0].revents = 0;

        void* data;
        size_t dataLen;
        int ret = record_stream_get_next(rs, &data, &dataLen);
        ALOGD(" %d of bytes to be sent... data=%p ret=%d", dataLen, data, ret);
        if (ret == 0 && data == NULL) {
          // end-of-stream
          break;
        } else if (ret < 0) {
          break;
        }
        WriteToIncomingQueue((uint8_t*)data, dataLen);
      }
    }
    record_stream_free(rs);
    close(nfcdRw);
  }

  return;
}

// Write NFC data to Gecko
// Outgoing queue contain the data should be send to gecko
// TODO check thread, this should run on the NfcService thread.
void NfcIpcSocket::WriteToOutgoingQueue(uint8_t* aData, size_t aDataLen)
{
  ALOGD("%s enter, data=%p, dataLen=%d", __func__, aData, aDataLen);

  if (aData == NULL || aDataLen == 0) {
    return;
  }

  size_t writeOffset = 0;
  int written = 0;

  ALOGD("Writing %d bytes to gecko ", aDataLen);
  while (writeOffset < aDataLen) {
    do {
      written = write (nfcdRw, aData + writeOffset, aDataLen - writeOffset);
    } while (written < 0 && errno == EINTR);

    if (written >= 0) {
      writeOffset += written;
    } else {
      ALOGE("Response: unexpected error on write errno:%d", errno);
      break;
    }
  }
}

// Write Gecko data to NFC
// Incoming queue contains
// TODO check thread, this should run on top of main thread of nfcd.
void NfcIpcSocket::WriteToIncomingQueue(uint8_t* aData, size_t aDataLen)
{
  ALOGD("%s enter, data=%p, dataLen=%d", __func__, aData, aDataLen);

  if (aData != NULL && aDataLen > 0) {
    mMsgHandler->ProcessRequest(aData, aDataLen);
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2019 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <evo/cbtx.h>
#include <evo/deterministicmns.h>
#include <llmq/quorums_blockprocessor.h>
#include <llmq/quorums_commitment.h>
#include <evo/simplifiedmns.h>
#include <evo/specialtx.h>

#include <chainparams.h>
#include <consensus/merkle.h>
#include <validation.h>

bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
{
    if (tx.nType != TRANSACTION_COINBASE) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-type");
    }

    if (!tx.IsCoinBase()) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-invalid");
    }

    CCbTx cbTx;
    if (!GetTxPayload(tx, cbTx)) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-payload");
    }

    if (cbTx.nVersion == 0 || cbTx.nVersion > CCbTx::CURRENT_VERSION) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-version");
    }

    if (pindexPrev && pindexPrev->nHeight + 1 != cbTx.nHeight) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-height");
    }

    if (pindexPrev) {
        bool fDIP0008Active = VersionBitsState(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0008, versionbitscache) == ThresholdState::ACTIVE;
        if (fDIP0008Active && cbTx.nVersion < 2) {
            return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-version");
        }
    }

    return true;
}

// This can only be done after the block has been fully processed, as otherwise we won't have the finished MN list
bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CValidationState& state)
{
    if (block.vtx[0]->nType != TRANSACTION_COINBASE) {
        return true;
    }

    static int64_t nTimePayload = 0;
    static int64_t nTimeMerkleMNL = 0;
    static int64_t nTimeMerkleQuorum = 0;

    int64_t nTime1 = GetTimeMicros();

    CCbTx cbTx;
    if (!GetTxPayload(*block.vtx[0], cbTx)) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-payload");
    }

    int64_t nTime2 = GetTimeMicros(); nTimePayload += nTime2 - nTime1;
    LogPrint(BCLog::BENCHMARK, "          - GetTxPayload: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimePayload * 0.000001);

    if (pindex) {
        uint256 calculatedMerkleRoot;
        if (!CalcCbTxMerkleRootMNList(block, pindex->pprev, calculatedMerkleRoot, state)) {
            // pass the state returned by the function above
            return false;
        }
        if (calculatedMerkleRoot != cbTx.merkleRootMNList) {
            return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-mnmerkleroot");
        }

        int64_t nTime3 = GetTimeMicros(); nTimeMerkleMNL += nTime3 - nTime2;
        LogPrint(BCLog::BENCHMARK, "          - CalcCbTxMerkleRootMNList: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeMerkleMNL * 0.000001);

        if (cbTx.nVersion >= 2) {
            if (!CalcCbTxMerkleRootQuorums(block, pindex->pprev, calculatedMerkleRoot, state)) {
                // pass the state returned by the function above
                return false;
            }
            if (calculatedMerkleRoot != cbTx.merkleRootQuorums) {
                return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-quorummerkleroot");
            }
        }

        int64_t nTime4 = GetTimeMicros(); nTimeMerkleQuorum += nTime4 - nTime3;
        LogPrint(BCLog::BENCHMARK, "          - CalcCbTxMerkleRootQuorums: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeMerkleQuorum * 0.000001);

    }

    return true;
}

bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, CValidationState& state)
{
    LOCK(deterministicMNManager->cs);

    static int64_t nTimeDMN = 0;
    static int64_t nTimeSMNL = 0;
    static int64_t nTimeMerkle = 0;

    int64_t nTime1 = GetTimeMicros();

    try {
        CDeterministicMNList tmpMNList;
        if (!deterministicMNManager->BuildNewListFromBlock(block, pindexPrev, state, tmpMNList, false)) {
            // pass the state returned by the function above
            return false;
        }

        int64_t nTime2 = GetTimeMicros(); nTimeDMN += nTime2 - nTime1;
        LogPrint(BCLog::BENCHMARK, "            - BuildNewListFromBlock: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeDMN * 0.000001);

        CSimplifiedMNList sml(tmpMNList);

        int64_t nTime3 = GetTimeMicros(); nTimeSMNL += nTime3 - nTime2;
        LogPrint(BCLog::BENCHMARK, "            - CSimplifiedMNList: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeSMNL * 0.000001);

        static CSimplifiedMNList smlCached;
        static uint256 merkleRootCached;
        static bool mutatedCached{false};

        if (sml.mnList == smlCached.mnList) {
            merkleRootRet = merkleRootCached;
            if (mutatedCached) {
                return state.DoS(100, false, REJECT_INVALID, "mutated-cached-calc-cb-mnmerkleroot");
            }
            return true;
        }

        bool mutated = false;
        merkleRootRet = sml.CalcMerkleRoot(&mutated);

        int64_t nTime4 = GetTimeMicros(); nTimeMerkle += nTime4 - nTime3;
        LogPrint(BCLog::BENCHMARK, "            - CalcMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeMerkle * 0.000001);

        smlCached = std::move(sml);
        merkleRootCached = merkleRootRet;
        mutatedCached = mutated;

        if (mutated) {
            return state.DoS(100, false, REJECT_INVALID, "mutated-calc-cb-mnmerkleroot");
        }

        return true;
    } catch (const std::exception& e) {
        LogPrintf("%s -- failed: %s\n", __func__, e.what());
        return state.DoS(100, false, REJECT_INVALID, "failed-calc-cb-mnmerkleroot");
    }
}

bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, CValidationState& state)
{
    static int64_t nTimeMinedAndActive = 0;
    static int64_t nTimeMined = 0;
    static int64_t nTimeLoop = 0;
    static int64_t nTimeMerkle = 0;

    int64_t nTime1 = GetTimeMicros();

    static std::map<Consensus::LLMQType, std::vector<const CBlockIndex*>> quorumsCached;
    static std::map<Consensus::LLMQType, std::vector<uint256>> qcHashesCached;

    // The returned quorums are in reversed order, so the most recent one is at index 0
    auto quorums = llmq::quorumBlockProcessor->GetMinedAndActiveCommitmentsUntilBlock(pindexPrev);
    std::map<Consensus::LLMQType, std::vector<uint256>> qcHashes;
    size_t hashCount = 0;

    int64_t nTime2 = GetTimeMicros(); nTimeMinedAndActive += nTime2 - nTime1;
    LogPrint(BCLog::BENCHMARK, "            - GetMinedAndActiveCommitmentsUntilBlock: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeMinedAndActive * 0.000001);

    if (quorums == quorumsCached) {
        qcHashes = qcHashesCached;
    } else {
        for (const auto& p : quorums) {
            auto& v = qcHashes[p.first];
            v.reserve(p.second.size());
            for (const auto& p2 : p.second) {
                llmq::CFinalCommitment qc;
                uint256 minedBlockHash;
                bool found = llmq::quorumBlockProcessor->GetMinedCommitment(p.first, p2->GetBlockHash(), qc, minedBlockHash);
                if (!found) return state.DoS(100, false, REJECT_INVALID, "commitment-not-found");
                v.emplace_back(::SerializeHash(qc));
                hashCount++;
            }
        }
        quorumsCached = quorums;
        qcHashesCached = qcHashes;
    }

    int64_t nTime3 = GetTimeMicros(); nTimeMined += nTime3 - nTime2;
    LogPrint(BCLog::BENCHMARK, "            - GetMinedCommitment: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeMined * 0.000001);

    // now add the commitments from the current block, which are not returned by GetMinedAndActiveCommitmentsUntilBlock
    // due to the use of pindexPrev (we don't have the tip index here)
    for (size_t i = 1; i < block.vtx.size(); i++) {
        auto& tx = block.vtx[i];

        if (tx->nVersion == 3 && tx->nType == TRANSACTION_QUORUM_COMMITMENT) {
            llmq::CFinalCommitmentTxPayload qc;
            if (!GetTxPayload(*tx, qc)) {
                return state.DoS(100, false, REJECT_INVALID, "bad-qc-payload-calc-cbtx-quorummerkleroot");
            }
            if (qc.commitment.IsNull()) {
                continue;
            }
            auto qcHash = ::SerializeHash(qc.commitment);
            const auto& params = Params().GetConsensus().llmqs.at((Consensus::LLMQType)qc.commitment.llmqType);
            auto& v = qcHashes[params.type];
            if (v.size() == params.signingActiveQuorumCount) {
                // we pop the last entry, which is actually the oldest quorum as GetMinedAndActiveCommitmentsUntilBlock
                // returned quorums in reversed order. This pop and later push can only work ONCE, but we rely on the
                // fact that a block can only contain a single commitment for one LLMQ type
                v.pop_back();
            }
            v.emplace_back(qcHash);
            hashCount++;
            if (v.size() > params.signingActiveQuorumCount) {
                return state.DoS(100, false, REJECT_INVALID, "excess-quorums-calc-cbtx-quorummerkleroot");
            }
        }
    }

    std::vector<uint256> qcHashesVec;
    qcHashesVec.reserve(hashCount);

    for (const auto& p : qcHashes) {
        for (const auto& h : p.second) {
            qcHashesVec.emplace_back(h);
        }
    }
    std::sort(qcHashesVec.begin(), qcHashesVec.end());

    int64_t nTime4 = GetTimeMicros(); nTimeLoop += nTime4 - nTime3;
    LogPrint(BCLog::BENCHMARK, "            - Loop: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeLoop * 0.000001);

    bool mutated = false;
    merkleRootRet = ComputeMerkleRoot(qcHashesVec, &mutated);

    int64_t nTime5 = GetTimeMicros(); nTimeMerkle += nTime5 - nTime4;
    LogPrint(BCLog::BENCHMARK, "            - ComputeMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeMerkle * 0.000001);

    if (mutated) {
        return state.DoS(100, false, REJECT_INVALID, "mutated-calc-cbtx-quorummerkleroot");
    }

    return true;
}

std::string CCbTx::ToString() const
{
    return strprintf("CCbTx(nHeight=%d, nVersion=%d, merkleRootMNList=%s, merkleRootQuorums=%s)",
        nVersion, nHeight, merkleRootMNList.ToString(), merkleRootQuorums.ToString());
}
<commit_msg>fix ToString bug in cbtx.cpp (#3807)<commit_after>// Copyright (c) 2017-2019 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <evo/cbtx.h>
#include <evo/deterministicmns.h>
#include <llmq/quorums_blockprocessor.h>
#include <llmq/quorums_commitment.h>
#include <evo/simplifiedmns.h>
#include <evo/specialtx.h>

#include <chainparams.h>
#include <consensus/merkle.h>
#include <validation.h>

bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
{
    if (tx.nType != TRANSACTION_COINBASE) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-type");
    }

    if (!tx.IsCoinBase()) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-invalid");
    }

    CCbTx cbTx;
    if (!GetTxPayload(tx, cbTx)) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-payload");
    }

    if (cbTx.nVersion == 0 || cbTx.nVersion > CCbTx::CURRENT_VERSION) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-version");
    }

    if (pindexPrev && pindexPrev->nHeight + 1 != cbTx.nHeight) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-height");
    }

    if (pindexPrev) {
        bool fDIP0008Active = VersionBitsState(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0008, versionbitscache) == ThresholdState::ACTIVE;
        if (fDIP0008Active && cbTx.nVersion < 2) {
            return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-version");
        }
    }

    return true;
}

// This can only be done after the block has been fully processed, as otherwise we won't have the finished MN list
bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CValidationState& state)
{
    if (block.vtx[0]->nType != TRANSACTION_COINBASE) {
        return true;
    }

    static int64_t nTimePayload = 0;
    static int64_t nTimeMerkleMNL = 0;
    static int64_t nTimeMerkleQuorum = 0;

    int64_t nTime1 = GetTimeMicros();

    CCbTx cbTx;
    if (!GetTxPayload(*block.vtx[0], cbTx)) {
        return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-payload");
    }

    int64_t nTime2 = GetTimeMicros(); nTimePayload += nTime2 - nTime1;
    LogPrint(BCLog::BENCHMARK, "          - GetTxPayload: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimePayload * 0.000001);

    if (pindex) {
        uint256 calculatedMerkleRoot;
        if (!CalcCbTxMerkleRootMNList(block, pindex->pprev, calculatedMerkleRoot, state)) {
            // pass the state returned by the function above
            return false;
        }
        if (calculatedMerkleRoot != cbTx.merkleRootMNList) {
            return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-mnmerkleroot");
        }

        int64_t nTime3 = GetTimeMicros(); nTimeMerkleMNL += nTime3 - nTime2;
        LogPrint(BCLog::BENCHMARK, "          - CalcCbTxMerkleRootMNList: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeMerkleMNL * 0.000001);

        if (cbTx.nVersion >= 2) {
            if (!CalcCbTxMerkleRootQuorums(block, pindex->pprev, calculatedMerkleRoot, state)) {
                // pass the state returned by the function above
                return false;
            }
            if (calculatedMerkleRoot != cbTx.merkleRootQuorums) {
                return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-quorummerkleroot");
            }
        }

        int64_t nTime4 = GetTimeMicros(); nTimeMerkleQuorum += nTime4 - nTime3;
        LogPrint(BCLog::BENCHMARK, "          - CalcCbTxMerkleRootQuorums: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeMerkleQuorum * 0.000001);

    }

    return true;
}

bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, CValidationState& state)
{
    LOCK(deterministicMNManager->cs);

    static int64_t nTimeDMN = 0;
    static int64_t nTimeSMNL = 0;
    static int64_t nTimeMerkle = 0;

    int64_t nTime1 = GetTimeMicros();

    try {
        CDeterministicMNList tmpMNList;
        if (!deterministicMNManager->BuildNewListFromBlock(block, pindexPrev, state, tmpMNList, false)) {
            // pass the state returned by the function above
            return false;
        }

        int64_t nTime2 = GetTimeMicros(); nTimeDMN += nTime2 - nTime1;
        LogPrint(BCLog::BENCHMARK, "            - BuildNewListFromBlock: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeDMN * 0.000001);

        CSimplifiedMNList sml(tmpMNList);

        int64_t nTime3 = GetTimeMicros(); nTimeSMNL += nTime3 - nTime2;
        LogPrint(BCLog::BENCHMARK, "            - CSimplifiedMNList: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeSMNL * 0.000001);

        static CSimplifiedMNList smlCached;
        static uint256 merkleRootCached;
        static bool mutatedCached{false};

        if (sml.mnList == smlCached.mnList) {
            merkleRootRet = merkleRootCached;
            if (mutatedCached) {
                return state.DoS(100, false, REJECT_INVALID, "mutated-cached-calc-cb-mnmerkleroot");
            }
            return true;
        }

        bool mutated = false;
        merkleRootRet = sml.CalcMerkleRoot(&mutated);

        int64_t nTime4 = GetTimeMicros(); nTimeMerkle += nTime4 - nTime3;
        LogPrint(BCLog::BENCHMARK, "            - CalcMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeMerkle * 0.000001);

        smlCached = std::move(sml);
        merkleRootCached = merkleRootRet;
        mutatedCached = mutated;

        if (mutated) {
            return state.DoS(100, false, REJECT_INVALID, "mutated-calc-cb-mnmerkleroot");
        }

        return true;
    } catch (const std::exception& e) {
        LogPrintf("%s -- failed: %s\n", __func__, e.what());
        return state.DoS(100, false, REJECT_INVALID, "failed-calc-cb-mnmerkleroot");
    }
}

bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, CValidationState& state)
{
    static int64_t nTimeMinedAndActive = 0;
    static int64_t nTimeMined = 0;
    static int64_t nTimeLoop = 0;
    static int64_t nTimeMerkle = 0;

    int64_t nTime1 = GetTimeMicros();

    static std::map<Consensus::LLMQType, std::vector<const CBlockIndex*>> quorumsCached;
    static std::map<Consensus::LLMQType, std::vector<uint256>> qcHashesCached;

    // The returned quorums are in reversed order, so the most recent one is at index 0
    auto quorums = llmq::quorumBlockProcessor->GetMinedAndActiveCommitmentsUntilBlock(pindexPrev);
    std::map<Consensus::LLMQType, std::vector<uint256>> qcHashes;
    size_t hashCount = 0;

    int64_t nTime2 = GetTimeMicros(); nTimeMinedAndActive += nTime2 - nTime1;
    LogPrint(BCLog::BENCHMARK, "            - GetMinedAndActiveCommitmentsUntilBlock: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeMinedAndActive * 0.000001);

    if (quorums == quorumsCached) {
        qcHashes = qcHashesCached;
    } else {
        for (const auto& p : quorums) {
            auto& v = qcHashes[p.first];
            v.reserve(p.second.size());
            for (const auto& p2 : p.second) {
                llmq::CFinalCommitment qc;
                uint256 minedBlockHash;
                bool found = llmq::quorumBlockProcessor->GetMinedCommitment(p.first, p2->GetBlockHash(), qc, minedBlockHash);
                if (!found) return state.DoS(100, false, REJECT_INVALID, "commitment-not-found");
                v.emplace_back(::SerializeHash(qc));
                hashCount++;
            }
        }
        quorumsCached = quorums;
        qcHashesCached = qcHashes;
    }

    int64_t nTime3 = GetTimeMicros(); nTimeMined += nTime3 - nTime2;
    LogPrint(BCLog::BENCHMARK, "            - GetMinedCommitment: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeMined * 0.000001);

    // now add the commitments from the current block, which are not returned by GetMinedAndActiveCommitmentsUntilBlock
    // due to the use of pindexPrev (we don't have the tip index here)
    for (size_t i = 1; i < block.vtx.size(); i++) {
        auto& tx = block.vtx[i];

        if (tx->nVersion == 3 && tx->nType == TRANSACTION_QUORUM_COMMITMENT) {
            llmq::CFinalCommitmentTxPayload qc;
            if (!GetTxPayload(*tx, qc)) {
                return state.DoS(100, false, REJECT_INVALID, "bad-qc-payload-calc-cbtx-quorummerkleroot");
            }
            if (qc.commitment.IsNull()) {
                continue;
            }
            auto qcHash = ::SerializeHash(qc.commitment);
            const auto& params = Params().GetConsensus().llmqs.at((Consensus::LLMQType)qc.commitment.llmqType);
            auto& v = qcHashes[params.type];
            if (v.size() == params.signingActiveQuorumCount) {
                // we pop the last entry, which is actually the oldest quorum as GetMinedAndActiveCommitmentsUntilBlock
                // returned quorums in reversed order. This pop and later push can only work ONCE, but we rely on the
                // fact that a block can only contain a single commitment for one LLMQ type
                v.pop_back();
            }
            v.emplace_back(qcHash);
            hashCount++;
            if (v.size() > params.signingActiveQuorumCount) {
                return state.DoS(100, false, REJECT_INVALID, "excess-quorums-calc-cbtx-quorummerkleroot");
            }
        }
    }

    std::vector<uint256> qcHashesVec;
    qcHashesVec.reserve(hashCount);

    for (const auto& p : qcHashes) {
        for (const auto& h : p.second) {
            qcHashesVec.emplace_back(h);
        }
    }
    std::sort(qcHashesVec.begin(), qcHashesVec.end());

    int64_t nTime4 = GetTimeMicros(); nTimeLoop += nTime4 - nTime3;
    LogPrint(BCLog::BENCHMARK, "            - Loop: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeLoop * 0.000001);

    bool mutated = false;
    merkleRootRet = ComputeMerkleRoot(qcHashesVec, &mutated);

    int64_t nTime5 = GetTimeMicros(); nTimeMerkle += nTime5 - nTime4;
    LogPrint(BCLog::BENCHMARK, "            - ComputeMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeMerkle * 0.000001);

    if (mutated) {
        return state.DoS(100, false, REJECT_INVALID, "mutated-calc-cbtx-quorummerkleroot");
    }

    return true;
}

std::string CCbTx::ToString() const
{
    return strprintf("CCbTx(nVersion=%d, nHeight=%d, merkleRootMNList=%s, merkleRootQuorums=%s)",
        nVersion, nHeight, merkleRootMNList.ToString(), merkleRootQuorums.ToString());
}
<|endoftext|>


<commit_before>#ifndef DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_DEFAULT_HH
#define DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_DEFAULT_HH

#ifdef HAVE_CMAKE_CONFIG
#include "cmake_config.h"
#elif defined(HAVE_CONFIG_H)
#include "config.h"
#endif

#include <memory>

#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/grid/io/file/vtk/function.hh>

#include <dune/stuff/la/container/interface.hh>

#include <dune/detailed/discretizations/space/interface.hh>

#include "local.hh"

namespace Dune {
namespace Detailed {
namespace Discretizations {

// template< class DiscreteFunctionSpaceImp, class VectorImp >
// class DefaultConst;

// template< class DiscreteFunctionSpaceImp, class VectorImp >
// class Default
//  : public Dune::VTKFunction< typename DiscreteFunctionSpaceImp::GridViewType >
//{
// private:
//  typedef Dune::VTKFunction< typename DiscreteFunctionSpaceImp::GridViewType > BaseType;

// public:
//  typedef DiscreteFunctionSpaceImp DiscreteFunctionSpaceType;

//  typedef VectorImp VectorType;

//  typedef Default< DiscreteFunctionSpaceType, VectorType > ThisType;

//  typedef DefaultConst< DiscreteFunctionSpaceType, VectorType > ConstType;

//  typedef typename DiscreteFunctionSpaceType::GridViewType::template Codim< 0 >::Iterator::Entity EntityType;

//  static const int polOrder = DiscreteFunctionSpaceType::polynomialOrder;

//  typedef Dune::Detailed::Discretizations::DiscreteFunction::LocalConst< ThisType > ConstLocalFunctionType;

//  typedef Dune::Detailed::Discretizations::DiscreteFunction::Local< ThisType > LocalFunctionType;

//  typedef typename DiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType;

//  typedef typename FunctionSpaceType::DomainType DomainType;

//  typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;

//  typedef typename FunctionSpaceType::RangeType RangeType;

//  static const int dimDomain = DiscreteFunctionSpaceType::dimDomain;

//  static const int dimRange = DiscreteFunctionSpaceType::dimRange;

//  typedef typename VectorType::size_type size_type;

//  Default(const DiscreteFunctionSpaceType& _space,
//          std::shared_ptr< VectorType > _vector,
//          const std::string _name = "discrete_function")
//    : BaseType(),
//      space_(_space)
//    , vector_(_vector)
//    , name_(_name)
//  {
//    assert(vector_->size() == space_.map().size() && "Given vector has wrong size!");
//  }

//  Default(const DiscreteFunctionSpaceType& _space,
//          const std::string _name = "discrete_function")
//    : BaseType(),
//      space_(_space)
//    , vector_(new VectorType(space_.map().size()))
//    , name_(_name)
//  {
//    assert(vector_->size() == space_.map().size() && "Given vector has wrong size!");
//  }

//  std::shared_ptr< const ConstType > createConst() const
//  {
//    std::shared_ptr< const ConstType > ret(new ConstType(*this));
//    return ret;
//  }

// private:
//  Default(const ThisType&);
//  ThisType& operator=(const ThisType&);

// public:
//  const DiscreteFunctionSpaceType& space() const
//  {
//    return space_;
//  }

//  virtual std::string name() const
//  {
//    return name_;
//  }

//  ConstLocalFunctionType localFunction(const EntityType& entity) const
//  {
//    return ConstLocalFunctionType(*this, entity);
//  }

//  LocalFunctionType localFunction(const EntityType& entity)
//  {
//    return LocalFunctionType(*this, entity);
//  }

//  std::shared_ptr< VectorType > vector()
//  {
//    return vector_;
//  }

//  const std::shared_ptr< const VectorType > vector() const
//  {
//    return vector_;
//  }

//  /**
//      @name Convenience methods
//      @{
//   **/
//  size_type size() const
//  {
//    return vector_->size();
//  }
//  /**
//      @}
//   **/

//  void clear()
//  {
//    const RangeFieldType zero(0);
//    for (size_type ii = 0; ii < vector_->size(); ++ii)
//      vector_->set(ii, zero);
//  }

//  /**
//      @name Methods to comply with the Dune::VTKFunction interface
//      @{
//   **/
//  virtual int ncomps() const
//  {
//    return dimRange;
//  }

//  virtual double evaluate(int component, const EntityType& entity, const DomainType& x) const
//  {
//    assert(vector_->size() == space_.map().size() && "Given vector has wrong size!");
//    RangeType ret(0.0);
//    localFunction(entity).evaluate(x, ret);
//    return ret[component];
//  }
//  /**
//      @}
//     **/

// private:
//  const DiscreteFunctionSpaceType& space_;
//  std::shared_ptr< VectorType > vector_;
//  const std::string name_;
//}; // class Defaul

template <class SpaceImp, class VectorImp>
class DiscreteFunctionDefaultConst : public Dune::VTKFunction<typename SpaceImp::GridPartType::GridViewType>,
                                     public Dune::Stuff::LocalizableFunction
{
public:
  typedef typename SpaceInterface<typename SpaceImp::Traits>::derived_type SpaceType;
  typedef typename Dune::Stuff::LA::VectorInterface<typename VectorImp::Traits>::derived_type VectorType;

  typedef typename SpaceType::EntityType EntityType;

  typedef DiscreteFunctionLocalConst<SpaceType, VectorType> ConstLocalFunctionType;
  typedef typename ConstLocalFunctionType::DomainType DomainType;
  typedef typename ConstLocalFunctionType::RangeType RangeType;

  DiscreteFunctionDefaultConst(const SpaceType& sp, const std::shared_ptr<const VectorType> vec,
                               const std::string nm = "discrete_function")
    : /*BaseType()
    , */ space_(sp)
    , name_(nm)
    , vector_(vec)
  {
    assert(vector_->size() == space_.mapper().size() && "Given vector has wrong size!");
  }

  const SpaceType& space() const
  {
    return space_;
  }

  virtual std::string name() const
  {
    return name_;
  }

  ConstLocalFunctionType localFunction(const EntityType& entity) const
  {
    return ConstLocalFunctionType(*this, entity);
  }

  const std::shared_ptr<const VectorType> vector() const
  {
    return vector_;
  }

  /** \defgroup vtk ´´Methods to comply with the Dune::VTKFunction interface.'' */
  /* @{ */
  virtual int ncomps() const
  {
    return SpaceType::dimRange;
  }

  virtual double evaluate(int component, const EntityType& entity, const DomainType& x) const
  {
    RangeType ret(0);
    localFunction(entity).evaluate(x, ret);
    return ret[component];
  }
  /* @} */

private:
  const SpaceType& space_;
  const std::string name_;
  const std::shared_ptr<const VectorType> vector_;
}; // class DiscreteFunctionDefaultConst

template <class SpaceImp, class VectorImp>
class DiscreteFunctionDefault : public DiscreteFunctionDefaultConst<SpaceImp, VectorImp>
{
  typedef DiscreteFunctionDefaultConst<SpaceImp, VectorImp> BaseType;

public:
  typedef typename SpaceInterface<typename SpaceImp::Traits>::derived_type SpaceType;
  typedef typename Dune::Stuff::LA::VectorInterface<typename VectorImp::Traits>::derived_type VectorType;

  typedef typename SpaceType::EntityType EntityType;

  typedef DiscreteFunctionLocal<SpaceType, VectorType> LocalFunctionType;
  typedef typename LocalFunctionType::DomainType DomainType;

  DiscreteFunctionDefault(const SpaceType& sp, std::shared_ptr<VectorType> vec,
                          const std::string nm = "discrete_function")
    : BaseType(sp, vec, nm)
    , nonConstVector_(vec)
  {
  }

  //  DiscreteFunctionDefault(const SpaceType& sp,
  //                          const std::string nm = "discrete_function")
  //    : nonConstVector_(std::make_shared< VectorType >(sp.mapper().size()))
  //    , BaseType(sp, nonConstVector_, nm)
  //  {}

  LocalFunctionType localFunction(const EntityType& entity)
  {
    return LocalFunctionType(*this, entity);
  }

  std::shared_ptr<VectorType> vector()
  {
    return nonConstVector_;
  }

  //  virtual std::string name() const
  //  {
  //    return BaseType::name();
  //  }

  //  /** \defgroup vtk ´´Methods to comply with the Dune::VTKFunction interface.'' */
  //  /* @{ */
  //  virtual int ncomps() const
  //  {
  //    return BaseType::ncomps();
  //  }

  //  virtual double evaluate(int component, const EntityType& entity, const DomainType& x) const
  //  {
  //    BaseType::evaluate(component, entity, x);
  //  }
  //  /* @} */

private:
  std::shared_ptr<VectorType> nonConstVector_;
}; // class DiscreteFunctionDefault

} // namespace Discretizations
} // namespace Detailed
} // namespace Dune

#endif // DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_DEFAULT_HH
<commit_msg>[discretefunction.default] removed unnecessary const<commit_after>#ifndef DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_DEFAULT_HH
#define DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_DEFAULT_HH

#ifdef HAVE_CMAKE_CONFIG
#include "cmake_config.h"
#elif defined(HAVE_CONFIG_H)
#include "config.h"
#endif

#include <memory>

#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/grid/io/file/vtk/function.hh>

#include <dune/stuff/la/container/interface.hh>

#include <dune/detailed/discretizations/space/interface.hh>

#include "local.hh"

namespace Dune {
namespace Detailed {
namespace Discretizations {

// template< class DiscreteFunctionSpaceImp, class VectorImp >
// class DefaultConst;

// template< class DiscreteFunctionSpaceImp, class VectorImp >
// class Default
//  : public Dune::VTKFunction< typename DiscreteFunctionSpaceImp::GridViewType >
//{
// private:
//  typedef Dune::VTKFunction< typename DiscreteFunctionSpaceImp::GridViewType > BaseType;

// public:
//  typedef DiscreteFunctionSpaceImp DiscreteFunctionSpaceType;

//  typedef VectorImp VectorType;

//  typedef Default< DiscreteFunctionSpaceType, VectorType > ThisType;

//  typedef DefaultConst< DiscreteFunctionSpaceType, VectorType > ConstType;

//  typedef typename DiscreteFunctionSpaceType::GridViewType::template Codim< 0 >::Iterator::Entity EntityType;

//  static const int polOrder = DiscreteFunctionSpaceType::polynomialOrder;

//  typedef Dune::Detailed::Discretizations::DiscreteFunction::LocalConst< ThisType > ConstLocalFunctionType;

//  typedef Dune::Detailed::Discretizations::DiscreteFunction::Local< ThisType > LocalFunctionType;

//  typedef typename DiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType;

//  typedef typename FunctionSpaceType::DomainType DomainType;

//  typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;

//  typedef typename FunctionSpaceType::RangeType RangeType;

//  static const int dimDomain = DiscreteFunctionSpaceType::dimDomain;

//  static const int dimRange = DiscreteFunctionSpaceType::dimRange;

//  typedef typename VectorType::size_type size_type;

//  Default(const DiscreteFunctionSpaceType& _space,
//          std::shared_ptr< VectorType > _vector,
//          const std::string _name = "discrete_function")
//    : BaseType(),
//      space_(_space)
//    , vector_(_vector)
//    , name_(_name)
//  {
//    assert(vector_->size() == space_.map().size() && "Given vector has wrong size!");
//  }

//  Default(const DiscreteFunctionSpaceType& _space,
//          const std::string _name = "discrete_function")
//    : BaseType(),
//      space_(_space)
//    , vector_(new VectorType(space_.map().size()))
//    , name_(_name)
//  {
//    assert(vector_->size() == space_.map().size() && "Given vector has wrong size!");
//  }

//  std::shared_ptr< const ConstType > createConst() const
//  {
//    std::shared_ptr< const ConstType > ret(new ConstType(*this));
//    return ret;
//  }

// private:
//  Default(const ThisType&);
//  ThisType& operator=(const ThisType&);

// public:
//  const DiscreteFunctionSpaceType& space() const
//  {
//    return space_;
//  }

//  virtual std::string name() const
//  {
//    return name_;
//  }

//  ConstLocalFunctionType localFunction(const EntityType& entity) const
//  {
//    return ConstLocalFunctionType(*this, entity);
//  }

//  LocalFunctionType localFunction(const EntityType& entity)
//  {
//    return LocalFunctionType(*this, entity);
//  }

//  std::shared_ptr< VectorType > vector()
//  {
//    return vector_;
//  }

//  const std::shared_ptr< const VectorType > vector() const
//  {
//    return vector_;
//  }

//  /**
//      @name Convenience methods
//      @{
//   **/
//  size_type size() const
//  {
//    return vector_->size();
//  }
//  /**
//      @}
//   **/

//  void clear()
//  {
//    const RangeFieldType zero(0);
//    for (size_type ii = 0; ii < vector_->size(); ++ii)
//      vector_->set(ii, zero);
//  }

//  /**
//      @name Methods to comply with the Dune::VTKFunction interface
//      @{
//   **/
//  virtual int ncomps() const
//  {
//    return dimRange;
//  }

//  virtual double evaluate(int component, const EntityType& entity, const DomainType& x) const
//  {
//    assert(vector_->size() == space_.map().size() && "Given vector has wrong size!");
//    RangeType ret(0.0);
//    localFunction(entity).evaluate(x, ret);
//    return ret[component];
//  }
//  /**
//      @}
//     **/

// private:
//  const DiscreteFunctionSpaceType& space_;
//  std::shared_ptr< VectorType > vector_;
//  const std::string name_;
//}; // class Defaul

template <class SpaceImp, class VectorImp>
class DiscreteFunctionDefaultConst : public Dune::VTKFunction<typename SpaceImp::GridPartType::GridViewType>,
                                     public Dune::Stuff::LocalizableFunction
{
public:
  typedef typename SpaceInterface<typename SpaceImp::Traits>::derived_type SpaceType;
  typedef typename Dune::Stuff::LA::VectorInterface<typename VectorImp::Traits>::derived_type VectorType;

  typedef typename SpaceType::EntityType EntityType;

  typedef DiscreteFunctionLocalConst<SpaceType, VectorType> ConstLocalFunctionType;
  typedef typename ConstLocalFunctionType::DomainType DomainType;
  typedef typename ConstLocalFunctionType::RangeType RangeType;

  DiscreteFunctionDefaultConst(const SpaceType& sp, const std::shared_ptr<const VectorType> vec,
                               const std::string nm = "discrete_function")
    : /*BaseType()
    , */ space_(sp)
    , name_(nm)
    , vector_(vec)
  {
    assert(vector_->size() == space_.mapper().size() && "Given vector has wrong size!");
  }

  const SpaceType& space() const
  {
    return space_;
  }

  virtual std::string name() const
  {
    return name_;
  }

  ConstLocalFunctionType localFunction(const EntityType& entity) const
  {
    return ConstLocalFunctionType(*this, entity);
  }

  std::shared_ptr<const VectorType> vector() const
  {
    return vector_;
  }

  /** \defgroup vtk ´´Methods to comply with the Dune::VTKFunction interface.'' */
  /* @{ */
  virtual int ncomps() const
  {
    return SpaceType::dimRange;
  }

  virtual double evaluate(int component, const EntityType& entity, const DomainType& x) const
  {
    RangeType ret(0);
    localFunction(entity).evaluate(x, ret);
    return ret[component];
  }
  /* @} */

private:
  const SpaceType& space_;
  const std::string name_;
  const std::shared_ptr<const VectorType> vector_;
}; // class DiscreteFunctionDefaultConst

template <class SpaceImp, class VectorImp>
class DiscreteFunctionDefault : public DiscreteFunctionDefaultConst<SpaceImp, VectorImp>
{
  typedef DiscreteFunctionDefaultConst<SpaceImp, VectorImp> BaseType;

public:
  typedef typename SpaceInterface<typename SpaceImp::Traits>::derived_type SpaceType;
  typedef typename Dune::Stuff::LA::VectorInterface<typename VectorImp::Traits>::derived_type VectorType;

  typedef typename SpaceType::EntityType EntityType;

  typedef DiscreteFunctionLocal<SpaceType, VectorType> LocalFunctionType;
  typedef typename LocalFunctionType::DomainType DomainType;

  DiscreteFunctionDefault(const SpaceType& sp, std::shared_ptr<VectorType> vec,
                          const std::string nm = "discrete_function")
    : BaseType(sp, vec, nm)
    , nonConstVector_(vec)
  {
  }

  //  DiscreteFunctionDefault(const SpaceType& sp,
  //                          const std::string nm = "discrete_function")
  //    : nonConstVector_(std::make_shared< VectorType >(sp.mapper().size()))
  //    , BaseType(sp, nonConstVector_, nm)
  //  {}

  LocalFunctionType localFunction(const EntityType& entity)
  {
    return LocalFunctionType(*this, entity);
  }

  std::shared_ptr<VectorType> vector()
  {
    return nonConstVector_;
  }

  //  virtual std::string name() const
  //  {
  //    return BaseType::name();
  //  }

  //  /** \defgroup vtk ´´Methods to comply with the Dune::VTKFunction interface.'' */
  //  /* @{ */
  //  virtual int ncomps() const
  //  {
  //    return BaseType::ncomps();
  //  }

  //  virtual double evaluate(int component, const EntityType& entity, const DomainType& x) const
  //  {
  //    BaseType::evaluate(component, entity, x);
  //  }
  //  /* @} */

private:
  std::shared_ptr<VectorType> nonConstVector_;
}; // class DiscreteFunctionDefault

} // namespace Discretizations
} // namespace Detailed
} // namespace Dune

#endif // DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_DEFAULT_HH
<|endoftext|>


<commit_before>/**
   @file proximityadaptor.cpp
   @brief ProximityAdaptor

   Copyright (C) 2009-2010 Nokia Corporation

   @author Ustun Ergenoglu <ext-ustun.ergenoglu@nokia.com>
   @author Timo Rongas <ext-timo.2.rongas@nokia.com>
   @author Matias Muhonen <ext-matias.muhonen@nokia.com>
   @author Lihan Guo <lihan.guo@digia.com>
   @author Shenghua <ext-shenghua.1.liu@nokia.com>
   @author Antti Virtanen <antti.i.virtanen@nokia.com>

   This file is part of Sensord.

   Sensord is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License
   version 2.1 as published by the Free Software Foundation.

   Sensord 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with Sensord.  If not, see <http://www.gnu.org/licenses/>.

*/
#include "proximityadaptor.h"
#include <errno.h>
#include "datatypes/utils.h"
#include "logging.h"
#include "config.h"
#include <QFile>
#include <linux/types.h>

#define THRESHOLD_FILE_PATH_RM680 "/sys/class/misc/bh1770glc_ps/device/ps_threshold"
#define THRESHOLD_FILE_PATH_RM696 "/sys/class/misc/apds990x0/device/prox_threshold"

#define RM680_PS "/dev/bh1770glc_ps"
#define RM696_PS "/dev/apds990x0"

struct bh1770glc_ps {
    __u8 led1;
    __u8 led2;
    __u8 led3;
} __attribute__((packed));

struct apds990x_data {
        __u32 lux; /* 10x scale */
        __u32 lux_raw; /* 10x scale */
        __u16 ps;
        __u16 ps_raw;
        __u16 status;
} __attribute__((packed));

ProximityAdaptor::ProximityAdaptor(const QString& id) :
    SysfsAdaptor(id, SysfsAdaptor::SelectMode, false),
    m_threshold(35)
{

#ifdef SENSORFW_MCE_WATCHER
    dbusIfc = new QDBusInterface(MCE_SERVICE, MCE_REQUEST_PATH, MCE_REQUEST_IF,
                                                 QDBusConnection::systemBus(), this);
#endif

    device = DeviceUnknown;

    QString rm680_ps = Config::configuration()->value("proximity_dev_path_rm680", RM680_PS).toString();
    QString rm696_ps = Config::configuration()->value("proximity_dev_path_rm696", RM696_PS).toString();

    if (QFile::exists(rm680_ps))
    {
        device = RM680;
        addPath(rm680_ps);
    }
    else if (QFile::exists(rm696_ps))
    {
        device = RM696;
        addPath(rm696_ps);
#ifdef SENSORFW_MCE_WATCHER
        dbusIfc->call(QDBus::NoBlock, "req_proximity_sensor_enable");
#endif
    }
    else
    {
        sensordLogC() << "Failed to locate proximity sensor";
    }
    proximityBuffer_ = new DeviceAdaptorRingBuffer<ProximityData>(1);
    addAdaptedSensor("proximity", "Proximity state", proximityBuffer_);

    int threshold = readThreshold();
    if (threshold <= 0) {
        sensordLogW() << "Received value 0 for proximity threshold. Falling back to default " << m_threshold;
    } else {
        m_threshold = threshold;
    }

    setDescription("Proximity sensor readings (Dipro sensor)");
    introduceAvailableDataRange(DataRange(0, 1, 1));
    introduceAvailableInterval(DataRange(0, 0, 0));
    setDefaultInterval(0);
}

ProximityAdaptor::~ProximityAdaptor()
{
    if (device == RM696)
    {
#ifdef SENSORFW_MCE_WATCHER
        dbusIfc->call(QDBus::NoBlock, "req_proximity_sensor_disable");
        delete dbusIfc;
#endif
    }
    delete proximityBuffer_;
}

void ProximityAdaptor::processSample(int pathId, int fd)
{
    Q_UNUSED(pathId);

    if (device == DeviceUnknown)
        return;

    int ret = 0;
    if (device == RM680)
    {
        bh1770glc_ps ps_data;
        int bytesRead = read(fd, &ps_data, sizeof(ps_data));

        if (bytesRead > 0) {
            sensordLogT() << "Proximity Values: " << ps_data.led1 << ", " << ps_data.led2 << ", " <<  ps_data.led3;
        } else {
            sensordLogW() << "read(): " << strerror(errno);
            return;
        }

        if ( ps_data.led1 > m_threshold ) {
            ret = 1;
        }
    }
    else if(device == RM696)
    {
        apds990x_data ps_data;
        int bytesRead = read(fd, &ps_data, sizeof(ps_data));

        if (bytesRead > 0) {
            sensordLogT() << "Proximity Values: " << ps_data.ps << ", " << ps_data.ps_raw << ", " << ps_data.status;
        } else {
            sensordLogW() << "read(): " << strerror(errno);
            return;
        }

        if ( ps_data.ps > m_threshold ) {
            ret = 1;
        }
    }

    ProximityData* proximityData = proximityBuffer_->nextSlot();

    proximityData->timestamp_ = Utils::getTimeStamp();
    proximityData->withinProximity_ = ret;

    proximityBuffer_->commit();
    proximityBuffer_->wakeUpReaders();
}

int ProximityAdaptor::readThreshold()
{
    int value = 0;
    QString configKey = "proximity_threshold_path";
    QString configFileName = (device == RM680 ? THRESHOLD_FILE_PATH_RM680 : THRESHOLD_FILE_PATH_RM696);
    QFile thresholdFile(Config::configuration()->value(configKey, configFileName).toString());

    if (!(thresholdFile.exists() && thresholdFile.open(QIODevice::ReadOnly))) {
        sensordLogW() << "Unable to locate threshold setting for " << id();
    } else {
        char buf[16];

        if (thresholdFile.readLine(buf, sizeof(buf)) > 0) {
            value = QString(buf).split(" ").at(0).toInt();
        }
    }
    return value;
}
<commit_msg>Adaptor also pushes the raw proximity data<commit_after>/**
   @file proximityadaptor.cpp
   @brief ProximityAdaptor

   Copyright (C) 2009-2010 Nokia Corporation

   @author Ustun Ergenoglu <ext-ustun.ergenoglu@nokia.com>
   @author Timo Rongas <ext-timo.2.rongas@nokia.com>
   @author Matias Muhonen <ext-matias.muhonen@nokia.com>
   @author Lihan Guo <lihan.guo@digia.com>
   @author Shenghua <ext-shenghua.1.liu@nokia.com>
   @author Antti Virtanen <antti.i.virtanen@nokia.com>

   This file is part of Sensord.

   Sensord is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License
   version 2.1 as published by the Free Software Foundation.

   Sensord 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with Sensord.  If not, see <http://www.gnu.org/licenses/>.

*/
#include "proximityadaptor.h"
#include <errno.h>
#include "datatypes/utils.h"
#include "logging.h"
#include "config.h"
#include <QFile>
#include <linux/types.h>

#define THRESHOLD_FILE_PATH_RM680 "/sys/class/misc/bh1770glc_ps/device/ps_threshold"
#define THRESHOLD_FILE_PATH_RM696 "/sys/class/misc/apds990x0/device/prox_threshold"

#define RM680_PS "/dev/bh1770glc_ps"
#define RM696_PS "/dev/apds990x0"

struct bh1770glc_ps {
    __u8 led1;
    __u8 led2;
    __u8 led3;
} __attribute__((packed));

struct apds990x_data {
        __u32 lux; /* 10x scale */
        __u32 lux_raw; /* 10x scale */
        __u16 ps;
        __u16 ps_raw;
        __u16 status;
} __attribute__((packed));

ProximityAdaptor::ProximityAdaptor(const QString& id) :
    SysfsAdaptor(id, SysfsAdaptor::SelectMode, false),
    m_threshold(35)
{

#ifdef SENSORFW_MCE_WATCHER
    dbusIfc = new QDBusInterface(MCE_SERVICE, MCE_REQUEST_PATH, MCE_REQUEST_IF,
                                                 QDBusConnection::systemBus(), this);
#endif

    device = DeviceUnknown;

    QString rm680_ps = Config::configuration()->value("proximity_dev_path_rm680", RM680_PS).toString();
    QString rm696_ps = Config::configuration()->value("proximity_dev_path_rm696", RM696_PS).toString();

    if (QFile::exists(rm680_ps))
    {
        device = RM680;
        addPath(rm680_ps);
    }
    else if (QFile::exists(rm696_ps))
    {
        device = RM696;
        addPath(rm696_ps);
#ifdef SENSORFW_MCE_WATCHER
        dbusIfc->call(QDBus::NoBlock, "req_proximity_sensor_enable");
#endif
    }
    else
    {
        sensordLogC() << "Failed to locate proximity sensor";
    }
    proximityBuffer_ = new DeviceAdaptorRingBuffer<ProximityData>(1);
    addAdaptedSensor("proximity", "Proximity state", proximityBuffer_);

    int threshold = readThreshold();
    if (threshold <= 0) {
        sensordLogW() << "Received value 0 for proximity threshold. Falling back to default " << m_threshold;
    } else {
        m_threshold = threshold;
    }

    setDescription("Proximity sensor readings (Dipro sensor)");
    introduceAvailableDataRange(DataRange(0, 1, 1));
    introduceAvailableInterval(DataRange(0, 0, 0));
    setDefaultInterval(0);
}

ProximityAdaptor::~ProximityAdaptor()
{
    if (device == RM696)
    {
#ifdef SENSORFW_MCE_WATCHER
        dbusIfc->call(QDBus::NoBlock, "req_proximity_sensor_disable");
        delete dbusIfc;
#endif
    }
    delete proximityBuffer_;
}

void ProximityAdaptor::processSample(int pathId, int fd)
{
    Q_UNUSED(pathId);

    if (device == DeviceUnknown)
        return;

    int ret = 0;
    unsigned rawdata = 0;

    if (device == RM680)
    {
        bh1770glc_ps ps_data;
        int bytesRead = read(fd, &ps_data, sizeof(ps_data));

        if (bytesRead > 0) {
            sensordLogT() << "Proximity Values: " << ps_data.led1 << ", " << ps_data.led2 << ", " <<  ps_data.led3;
        } else {
            sensordLogW() << "read(): " << strerror(errno);
            return;
        }

        if ( ps_data.led1 > m_threshold ) {
            ret = 1;
        }

        rawdata = ps_data.led1;
    }
    else if(device == RM696)
    {
        apds990x_data ps_data;
        int bytesRead = read(fd, &ps_data, sizeof(ps_data));

        if (bytesRead > 0) {
            sensordLogT() << "Proximity Values: " << ps_data.ps << ", " << ps_data.ps_raw << ", " << ps_data.status;
        } else {
            sensordLogW() << "read(): " << strerror(errno);
            return;
        }

        if ( ps_data.ps > m_threshold ) {
            ret = 1;
        }

        rawdata = ps_data.ps;
    }

    ProximityData* proximityData = proximityBuffer_->nextSlot();

    proximityData->timestamp_ = Utils::getTimeStamp();
    proximityData->withinProximity_ = ret;
    proximityData->value_ = rawdata;

    proximityBuffer_->commit();
    proximityBuffer_->wakeUpReaders();
}

int ProximityAdaptor::readThreshold()
{
    int value = 0;
    QString configKey = "proximity_threshold_path";
    QString configFileName = (device == RM680 ? THRESHOLD_FILE_PATH_RM680 : THRESHOLD_FILE_PATH_RM696);
    QFile thresholdFile(Config::configuration()->value(configKey, configFileName).toString());

    if (!(thresholdFile.exists() && thresholdFile.open(QIODevice::ReadOnly))) {
        sensordLogW() << "Unable to locate threshold setting for " << id();
    } else {
        char buf[16];

        if (thresholdFile.readLine(buf, sizeof(buf)) > 0) {
            value = QString(buf).split(" ").at(0).toInt();
        }
    }
    return value;
}
<|endoftext|>


<commit_before>#include <QtGui/QPainter>
#include <QtWidgets/QStyle>
#include <QtWidgets/QStyleOptionGraphicsItem>

#include <qrkernel/settingsManager.h>
#include "lineItem.h"
#include "wallItem.h"

using namespace twoDModel::items;
using namespace qReal;
using namespace graphicsUtils;

LineItem::LineItem(QPointF const &begin, QPointF const &end, int cornerRadius)
	: mLineImpl()
	, mCornerRadius(cornerRadius)
	, mCellNumbX1(0)
	, mCellNumbY1(0)
	, mCellNumbX2(0)
	, mCellNumbY2(0)
{
	mX1 = begin.x();
	mY1 = begin.y();
	mX2 = end.x();
	mY2 = end.y();
	setFlags(ItemIsSelectable | ItemIsMovable);
	setPrivateData();
}

void LineItem::setPrivateData()
{
	mPen.setColor(Qt::green);
	mPen.setStyle(Qt::SolidLine);
	mSerializeName = "line";
}

QRectF LineItem::boundingRect() const
{
	return mLineImpl.boundingRect(mX1, mY1, mX2, mY2, mPen.width(), drift);
}

void LineItem::drawItem(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
	Q_UNUSED(option);
	Q_UNUSED(widget);
	mLineImpl.drawItem(painter, mX1, mY1, mX2, mY2);
}

void LineItem::drawExtractionForItem(QPainter* painter)
{
	mLineImpl.drawPointExtractionForItem(painter, mX1, mY1, mX2, mY2);
	setPenBrushDriftRect(painter);
	mLineImpl.drawExtractionForItem(painter, mX1, mY1, mX2, mY2, drift);
	mLineImpl.drawFieldForResizeItem(painter, resizeDrift, mX1, mY1, mX2, mY2);

	painter->setPen(QPen(Qt::red));
	painter->setBrush(QBrush(Qt::SolidPattern));
}

QPainterPath LineItem::shape() const
{
	return mLineImpl.shape(drift, mX1, mY1, mX2, mY2);
}

void LineItem::resizeItem(QGraphicsSceneMouseEvent *event)
{
	if (event->modifiers() & Qt::ShiftModifier) {
		mX2=event->scenePos().x();
		mY2=event->scenePos().y();
		reshapeRectWithShift();
	} else {
		if (SettingsManager::value("2dShowGrid").toBool()
				&& (mDragState == TopLeft || mDragState == BottomRight)
				&& dynamic_cast<WallItem *>(this))
		{
			calcResizeItem(event, SettingsManager::value("2dGridCellSize").toInt());
		} else {
			if (mDragState == TopLeft || mDragState == BottomRight) {
				AbstractItem::resizeItem(event);
			} else {
				setFlag(QGraphicsItem::ItemIsMovable, true);
			}
		}
	}
}

void LineItem::calcResizeItem(QGraphicsSceneMouseEvent *event, int indexGrid)
{
	qreal const x = mapFromScene(event->scenePos()).x();
	qreal const y = mapFromScene(event->scenePos()).y();
	if (mDragState != None) {
		setFlag(QGraphicsItem::ItemIsMovable, false);
	}
	if (mDragState == TopLeft) {
		mX1 = x;
		mY1 = y;
		resizeBeginWithGrid(indexGrid);
	} else if (mDragState == BottomRight) {
		mX2 = x;
		mY2 = y;
		reshapeEndWithGrid(indexGrid);
	}
}

void LineItem::reshapeRectWithShift()
{
	qreal differenceX = abs(mX2 - mX1);
	qreal differenceY = abs(mY2 - mY1);
	qreal differenceXY = abs(differenceX - differenceY);
	qreal size = qMax(differenceX, differenceY);
	const int delta = size / 2;
	if (differenceXY > delta) {
		QPair<qreal, qreal> res = mLineImpl.reshapeRectWithShiftForLine(mX1, mY1, mX2, mY2, differenceX, differenceY, size);
		setX2andY2(res.first, res.second);
	} else
		AbstractItem::reshapeRectWithShift();
}

void LineItem::resizeBeginWithGrid(int indexGrid)
{
	int const coefX = static_cast<int>(mX1) / indexGrid;
	int const coefY = static_cast<int>(mY1) / indexGrid;

	if (qAbs(mY2 - mY1) > 2 * qAbs(mX2 - mX1)) {
		setX1andY1(mX2, alignedCoordinate(mY1, coefY, indexGrid));
	} else if (qAbs(mY2 - mY1) < qAbs(mX2 - mX1) / 2) {
		setX1andY1(alignedCoordinate(mX1, coefX, indexGrid), mY2);
	} else {
		setX2andY2(alignedCoordinate(mX1, coefX, indexGrid), alignedCoordinate(mY1, coefY, indexGrid));
	}

	mCellNumbX1 = mX1 / indexGrid;
	mCellNumbY1 = mY1 / indexGrid;
}

void LineItem::reshapeEndWithGrid(int indexGrid)
{
	int const coefX = static_cast<int>(mX2) / indexGrid;
	int const coefY = static_cast<int>(mY2) / indexGrid;

	if (qAbs(mY2 - mY1) > 2 * qAbs(mX2 - mX1)) {
		setX2andY2(mX1, alignedCoordinate(mY2, coefY, indexGrid));
	} else if (qAbs(mY2 - mY1) < qAbs(mX2 - mX1) / 2) {
		setX2andY2(alignedCoordinate(mX2, coefX, indexGrid), mY1);
	} else {
		setX2andY2(alignedCoordinate(mX2, coefX, indexGrid), alignedCoordinate(mY2, coefY, indexGrid));
	}

	mCellNumbX2 = mX2 / indexGrid;
	mCellNumbY2 = mY2 / indexGrid;
}

void LineItem::reshapeBeginWithGrid(int indexGrid)
{
	int const coefX = static_cast<int> (mX1) / indexGrid;
	int const coefY = static_cast<int> (mY1) / indexGrid;
	setX1andY1(alignedCoordinate(mX1, coefX, indexGrid), alignedCoordinate(mY1, coefY, indexGrid));
	mCellNumbX1 = mX1 / indexGrid;
	mCellNumbY1 = mY1 / indexGrid;
}

void LineItem::alignTheWall(int indexGrid)
{
	countCellNumbCoordinates(indexGrid);
	setBeginCoordinatesWithGrid(indexGrid);
	setEndCoordinatesWithGrid(indexGrid);
}

void LineItem::countCellNumbCoordinates(int indexGrid)
{
	mCellNumbX1 = mX1 / indexGrid;
	mCellNumbY1 = mY1 / indexGrid;

	if (qAbs(mY2 - mY1) > qAbs(mX2 - mX1)) {
		mCellNumbX2 = mCellNumbX1;
		mCellNumbY2 = mY2 / indexGrid;
	} else {
		mCellNumbX2 = mX2 / indexGrid;
		mCellNumbY2 = mCellNumbY1;
	}
}

void LineItem::setBeginCoordinatesWithGrid(int indexGrid)
{
	setX1andY1(mCellNumbX1 * indexGrid, mCellNumbY1 * indexGrid);
}

void LineItem::setEndCoordinatesWithGrid(int indexGrid)
{
	setX2andY2(mCellNumbX2 * indexGrid, mCellNumbY2 * indexGrid);
}

void LineItem::setDraggedEnd(qreal x, qreal y)
{
	setX2andY2(mX1 - x, mY1 - y);
}

qreal LineItem::alignedCoordinate(qreal coord, int coef, int const indexGrid) const
{
	int const coefSign = coef ? coef / qAbs(coef) : 0;

	if (qAbs(qAbs(coord) - qAbs(coef) * indexGrid) <= indexGrid / 2) {
		return coef * indexGrid;
	} else if (qAbs(qAbs(coord) - (qAbs(coef) + 1) * indexGrid) <= indexGrid / 2) {
		return (coef + coefSign) * indexGrid;
	}

	return coord;
}

QDomElement LineItem::serialize(QDomDocument &document, QPoint const &topLeftPicture)
{
	QDomElement lineNode = setPenBrushToDoc(document, mSerializeName);
	lineNode.setAttribute("begin", QString::number(mX1 + scenePos().x() - topLeftPicture.x())
			+ ":" + QString::number(mY1 + scenePos().y() - topLeftPicture.y()));
	lineNode.setAttribute("end", QString::number(mX2 + scenePos().x() - topLeftPicture.x())
			+ ":" + QString::number(mY2 + scenePos().y() - topLeftPicture.y()));
	return lineNode;
}

void LineItem::deserialize(QDomElement const &element)
{
	QString const beginStr = element.attribute("begin", "0:0");
	QStringList splittedStr = beginStr.split(":");
	int x = splittedStr[0].toInt();
	int y = splittedStr[1].toInt();
	QPointF const begin = QPointF(x, y);

	QString const endStr = element.attribute("end", "0:0");
	splittedStr = endStr.split(":");
	x = splittedStr[0].toInt();
	y = splittedStr[1].toInt();
	QPointF const end = QPointF(x, y);

	mX1 = begin.x();
	mY1 = begin.y();
	mX2 = end.x();
	mY2 = end.y();

	deserializePenBrush(element);
}

void LineItem::deserializePenBrush(QDomElement const &element)
{
	readPenBrush(element);
}

void LineItem::setSerializeName(QString const &name)
{
	mSerializeName = name;
}
<commit_msg>Walls alligned on edges of grid in d2modelwidget<commit_after>#include <QtGui/QPainter>
#include <QtWidgets/QStyle>
#include <QtWidgets/QStyleOptionGraphicsItem>

#include <qrkernel/settingsManager.h>
#include "lineItem.h"
#include "wallItem.h"

using namespace twoDModel::items;
using namespace qReal;
using namespace graphicsUtils;

LineItem::LineItem(QPointF const &begin, QPointF const &end, int cornerRadius)
	: mLineImpl()
	, mCornerRadius(cornerRadius)
	, mCellNumbX1(0)
	, mCellNumbY1(0)
	, mCellNumbX2(0)
	, mCellNumbY2(0)
{
	mX1 = begin.x();
	mY1 = begin.y();
	mX2 = end.x();
	mY2 = end.y();
	setFlags(ItemIsSelectable | ItemIsMovable);
	setPrivateData();
}

void LineItem::setPrivateData()
{
	mPen.setColor(Qt::green);
	mPen.setStyle(Qt::SolidLine);
	mSerializeName = "line";
}

QRectF LineItem::boundingRect() const
{
	return mLineImpl.boundingRect(mX1, mY1, mX2, mY2, mPen.width(), drift);
}

void LineItem::drawItem(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
	Q_UNUSED(option);
	Q_UNUSED(widget);
	mLineImpl.drawItem(painter, mX1, mY1, mX2, mY2);
}

void LineItem::drawExtractionForItem(QPainter* painter)
{
	mLineImpl.drawPointExtractionForItem(painter, mX1, mY1, mX2, mY2);
	setPenBrushDriftRect(painter);
	mLineImpl.drawExtractionForItem(painter, mX1, mY1, mX2, mY2, drift);
	mLineImpl.drawFieldForResizeItem(painter, resizeDrift, mX1, mY1, mX2, mY2);

	painter->setPen(QPen(Qt::red));
	painter->setBrush(QBrush(Qt::SolidPattern));
}

QPainterPath LineItem::shape() const
{
	return mLineImpl.shape(drift, mX1, mY1, mX2, mY2);
}

void LineItem::resizeItem(QGraphicsSceneMouseEvent *event)
{
	if (event->modifiers() & Qt::ShiftModifier) {
		mX2=event->scenePos().x();
		mY2=event->scenePos().y();
		reshapeRectWithShift();
	} else {
		if (SettingsManager::value("2dShowGrid").toBool()
				&& (mDragState == TopLeft || mDragState == BottomRight)
				&& dynamic_cast<WallItem *>(this))
		{
			calcResizeItem(event, SettingsManager::value("2dGridCellSize").toInt());
		} else {
			if (mDragState == TopLeft || mDragState == BottomRight) {
				AbstractItem::resizeItem(event);
			} else {
				setFlag(QGraphicsItem::ItemIsMovable, true);
			}
		}
	}
}

void LineItem::calcResizeItem(QGraphicsSceneMouseEvent *event, int indexGrid)
{
	qreal const x = mapFromScene(event->scenePos()).x();
	qreal const y = mapFromScene(event->scenePos()).y();
	if (mDragState != None) {
		setFlag(QGraphicsItem::ItemIsMovable, false);
	}
	if (mDragState == TopLeft) {
		mX1 = x;
		mY1 = y;
		resizeBeginWithGrid(indexGrid);
	} else if (mDragState == BottomRight) {
		mX2 = x;
		mY2 = y;
		reshapeEndWithGrid(indexGrid);
	}
}

void LineItem::reshapeRectWithShift()
{
	qreal differenceX = abs(mX2 - mX1);
	qreal differenceY = abs(mY2 - mY1);
	qreal differenceXY = abs(differenceX - differenceY);
	qreal size = qMax(differenceX, differenceY);
	const int delta = size / 2;
	if (differenceXY > delta) {
		QPair<qreal, qreal> res = mLineImpl.reshapeRectWithShiftForLine(mX1, mY1, mX2, mY2, differenceX, differenceY, size);
		setX2andY2(res.first, res.second);
	} else
		AbstractItem::reshapeRectWithShift();
}

void LineItem::resizeBeginWithGrid(int indexGrid)
{
	int const coefX = static_cast<int>(mX1) / indexGrid;
	int const coefY = static_cast<int>(mY1) / indexGrid;

	setX1andY1(alignedCoordinate(mX1, coefX, indexGrid), alignedCoordinate(mY1, coefY, indexGrid));

	mCellNumbX1 = mX1 / indexGrid;
	mCellNumbY1 = mY1 / indexGrid;
}

void LineItem::reshapeEndWithGrid(int indexGrid)
{
	int const coefX = static_cast<int>(mX2) / indexGrid;
	int const coefY = static_cast<int>(mY2) / indexGrid;

	setX2andY2(alignedCoordinate(mX2, coefX, indexGrid), alignedCoordinate(mY2, coefY, indexGrid));

	mCellNumbX2 = mX2 / indexGrid;
	mCellNumbY2 = mY2 / indexGrid;
}

void LineItem::reshapeBeginWithGrid(int indexGrid)
{
	int const coefX = static_cast<int> (mX1) / indexGrid;
	int const coefY = static_cast<int> (mY1) / indexGrid;
	setX1andY1(alignedCoordinate(mX1, coefX, indexGrid), alignedCoordinate(mY1, coefY, indexGrid));
	mCellNumbX1 = mX1 / indexGrid;
	mCellNumbY1 = mY1 / indexGrid;
}

void LineItem::alignTheWall(int indexGrid)
{
	countCellNumbCoordinates(indexGrid);
	setBeginCoordinatesWithGrid(indexGrid);
	setEndCoordinatesWithGrid(indexGrid);
}

void LineItem::countCellNumbCoordinates(int indexGrid)
{
	mCellNumbX1 = mX1 / indexGrid;
	mCellNumbY1 = mY1 / indexGrid;

	if (qAbs(mY2 - mY1) > qAbs(mX2 - mX1)) {
		mCellNumbX2 = mCellNumbX1;
		mCellNumbY2 = mY2 / indexGrid;
	} else {
		mCellNumbX2 = mX2 / indexGrid;
		mCellNumbY2 = mCellNumbY1;
	}
}

void LineItem::setBeginCoordinatesWithGrid(int indexGrid)
{
	setX1andY1(mCellNumbX1 * indexGrid, mCellNumbY1 * indexGrid);
}

void LineItem::setEndCoordinatesWithGrid(int indexGrid)
{
	setX2andY2(mCellNumbX2 * indexGrid, mCellNumbY2 * indexGrid);
}

void LineItem::setDraggedEnd(qreal x, qreal y)
{
	setX2andY2(mX1 - x, mY1 - y);
}

qreal LineItem::alignedCoordinate(qreal coord, int coef, int const indexGrid) const
{
	int const coefSign = coef ? coef / qAbs(coef) : 0;

	if (qAbs(qAbs(coord) - qAbs(coef) * indexGrid) <= indexGrid / 2) {
		return coef * indexGrid;
	} else if (qAbs(qAbs(coord) - (qAbs(coef) + 1) * indexGrid) <= indexGrid / 2) {
		return (coef + coefSign) * indexGrid;
	}

	return coord;
}

QDomElement LineItem::serialize(QDomDocument &document, QPoint const &topLeftPicture)
{
	QDomElement lineNode = setPenBrushToDoc(document, mSerializeName);
	lineNode.setAttribute("begin", QString::number(mX1 + scenePos().x() - topLeftPicture.x())
			+ ":" + QString::number(mY1 + scenePos().y() - topLeftPicture.y()));
	lineNode.setAttribute("end", QString::number(mX2 + scenePos().x() - topLeftPicture.x())
			+ ":" + QString::number(mY2 + scenePos().y() - topLeftPicture.y()));
	return lineNode;
}

void LineItem::deserialize(QDomElement const &element)
{
	QString const beginStr = element.attribute("begin", "0:0");
	QStringList splittedStr = beginStr.split(":");
	int x = splittedStr[0].toInt();
	int y = splittedStr[1].toInt();
	QPointF const begin = QPointF(x, y);

	QString const endStr = element.attribute("end", "0:0");
	splittedStr = endStr.split(":");
	x = splittedStr[0].toInt();
	y = splittedStr[1].toInt();
	QPointF const end = QPointF(x, y);

	mX1 = begin.x();
	mY1 = begin.y();
	mX2 = end.x();
	mY2 = end.y();

	deserializePenBrush(element);
}

void LineItem::deserializePenBrush(QDomElement const &element)
{
	readPenBrush(element);
}

void LineItem::setSerializeName(QString const &name)
{
	mSerializeName = name;
}
<|endoftext|>