<commit_before>#include "HaxeRuntime.h"
#if WITH_EDITOR

#include "uhx/DynamicClass.h"

#include "Misc/Paths.h"
#include "uhx/expose/HxcppRuntime.h"

#ifndef UHX_NO_UOBJECT

static int uhx_uniqueId = 0;

static TMap<FName, uint32> getCrcMapPvt() {
  TMap<FName, uint32> map;
  FString path = FPaths::ConvertRelativePathToFull(FPaths::GameDir()) + TEXT("/Binaries/Haxe/gameCrcs.data");
  auto file = FPlatformFileManager::Get().GetPlatformFile().OpenRead(*path, false);
  if (file == nullptr) {
    return map;
  }

  uint8 classNameSize = 0;
  char className[257];
  uint32 crc = 0;
  bool success = true;
  int magic = 0;
  if (!file->Read((uint8*) &magic, 4) || magic != 0xC5CC991A) {
    UE_LOG(HaxeLog, Error, TEXT("Invalid gameCrcs magic"));
    success = false;
  }

  int ntry = 0;

  if (!success || !file->Read((uint8*) &ntry, 4)) {
    success = false;
  }
  uhx_uniqueId = ntry;

#define READ(destination, bytesToRead) if (!file->Read(destination, bytesToRead)) { success = false; break; }

  while(success) {
    READ(&classNameSize, 1);
    if (classNameSize == 0) {
      break;
    }

    READ((uint8 *) className, classNameSize);
    className[classNameSize] = 0;
    READ((uint8 *) &crc, 4);
    // crc += ntry;
    FName classFName = FName( UTF8_TO_TCHAR(className) );
    if (crc == 0) {
      UE_LOG(HaxeLog, Error, TEXT("Unreal.hx CRC for class %s was 0"), *classFName.ToString());
    }
    map.Add(classFName, crc);
  }

#undef READ

  if (!success) {
    UE_LOG(HaxeLog,Error,TEXT("Unreal.hx CRC data was corrupt"));
  }

  delete file;
  return map;
}

TMap<FName, uint32>& ::uhx::DynamicClassHelper::getCrcMap() {
  static TMap<FName, uint32> map = getCrcMapPvt();
  return map;
}

TMap<FName, UClass *>& ::uhx::DynamicClassHelper::getDynamicsMap() {
  static TMap<FName, UClass *> map;
  return map;
}

#endif

#if (WITH_EDITOR && !NO_DYNAMIC_UCLASS)

/**
 * In order to add cppia dynamic class support, we need to be able to call `addDynamicProperties` in a very precise location - which is
 * right before the CDO is created. We must call this before the class CDO is created because otherwise the CDO will have the wrong size,
 * and bad things will happen. This UHxBootstrap class implements an intrinsic class so we can have a callback right when the classes
 * are registering, which is the exact place where we should add the dynamic properties
 **/
class UHxBootstrap : public UObject {
#if UE_VER >= 416
#define UHX_HOTRELOAD 1
#else
#define UHX_HOTRELOAD WITH_HOT_RELOAD_CTORS
#endif

#if UHX_HOTRELOAD
  DECLARE_CASTED_CLASS_INTRINSIC_NO_CTOR_NO_VTABLE_CTOR(UHxBootstrap, UObject, 0, TEXT("/Script/HaxeRuntime"), 0, HAXERUNTIME_API)

  UHxBootstrap(FVTableHelper& Helper) : UObject(Helper) {
  }
#else
  DECLARE_CASTED_CLASS_INTRINSIC_NO_CTOR(UHxBootstrap, UObject, 0, HaxeRuntime, 0, HAXERUNTIME_API)
#endif
  UHxBootstrap(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()) : UObject(ObjectInitializer) {
    static bool endLoadingDynamicCalled = false;
    if (!endLoadingDynamicCalled) {
      endLoadingDynamicCalled = true;
      uhx::expose::HxcppRuntime::endLoadingDynamic();
    }
  }

#undef UHX_HOTRELOAD
};

// make sure that UHxBootstrap is always hot reloaded, as its CRC constantly changes
template<>
struct TClassCompiledInDefer<UHxBootstrap> : public FFieldCompiledInInfo
{
  TClassCompiledInDefer(const TCHAR* InName, SIZE_T InClassSize, uint32 InCrc)
    : FFieldCompiledInInfo(InClassSize, InCrc)
  {
    static FName className = FName("UHxBootstrap");
    ::uhx::DynamicClassHelper::getCrcMap(); // make sure that the crc map is initialized
    this->Crc = uhx_uniqueId;
    UClassCompiledInDefer(this, InName, InClassSize, this->Crc);
  }
  virtual UClass* Register() const override {
    return UHxBootstrap::StaticClass();
  }

#if UE_VER >= 416
  const TCHAR* ClassPackage() const {
    return UHxBootstrap::StaticPackage();
  }

#endif
};

#if UE_VER >= 416
#define UHX_IMPLEMENT_INTRINSIC_CLASS(TClass, TRequiredAPI, TSuperClass, TSuperRequiredAPI, InitCode) IMPLEMENT_INTRINSIC_CLASS(TClass, TRequiredAPI, TSuperClass, TSuperRequiredAPI, "/Script/HaxeRuntime", InitCode)
#else
#define UHX_IMPLEMENT_INTRINSIC_CLASS(TClass, TRequiredAPI, TSuperClass, TSuperRequiredAPI, InitCode) IMPLEMENT_INTRINSIC_CLASS(TClass, TRequiredAPI, TSuperClass, TSuperRequiredAPI, InitCode)
#endif

UHX_IMPLEMENT_INTRINSIC_CLASS(UHxBootstrap, HAXERUNTIME_API, UObject, COREUOBJECT_API,
{
  check_hx_init();
  uhx::expose::HxcppRuntime::startLoadingDynamic();
  for (auto It = ::uhx::DynamicClassHelper::getDynamicsMap().CreateIterator(); It; ++It) {
    UClass *val = It.Value();
    uhx::expose::HxcppRuntime::setDynamicNative((unreal::UIntPtr) val, TCHAR_TO_UTF8(*It.Key().ToString()));
  }
  uhx::expose::HxcppRuntime::setNativeTypes();
  for (auto It = ::uhx::DynamicClassHelper::getDynamicsMap().CreateIterator(); It; ++It) {
    UClass *val = It.Value();
    uhx::expose::HxcppRuntime::addDynamicProperties((unreal::UIntPtr) val, TCHAR_TO_UTF8(*It.Key().ToString()));
  }
});

#undef UHX_IMPLEMENT_INTRINSIC_CLASS

#endif

#endif // WITH_EDITOR
<commit_msg>[CL-14383] Update to latest perforce change Change 14383 by waneck@wnk-asus-win-ls on 2017/12/06 22:37:05<commit_after>#include "HaxeRuntime.h"
#if WITH_EDITOR

#include "uhx/DynamicClass.h"

#include "Misc/Paths.h"
#include "uhx/expose/HxcppRuntime.h"

#ifndef UHX_NO_UOBJECT

static int uhx_uniqueId = 0;

static TMap<FName, uint32> getCrcMapPvt() {
  TMap<FName, uint32> map;
  FString path = FPaths::ConvertRelativePathToFull(FPaths::GameDir()) + TEXT("/Binaries/Haxe/gameCrcs.data");
  auto file = FPlatformFileManager::Get().GetPlatformFile().OpenRead(*path, false);
  if (file == nullptr) {
    return map;
  }

  uint8 classNameSize = 0;
  char className[257];
  uint32 crc = 0;
  bool success = true;
  int magic = 0;
  if (!file->Read((uint8*) &magic, 4) || magic != 0xC5CC991A) {
    UE_LOG(HaxeLog, Error, TEXT("Invalid gameCrcs magic"));
    success = false;
  }

  int ntry = 0;

  if (!success || !file->Read((uint8*) &ntry, 4)) {
    success = false;
  }
  uhx_uniqueId = ntry;

#define READ(destination, bytesToRead) if (!file->Read(destination, bytesToRead)) { success = false; break; }

  while(success) {
    READ(&classNameSize, 1);
    if (classNameSize == 0) {
      break;
    }

    READ((uint8 *) className, classNameSize);
    className[classNameSize] = 0;
    READ((uint8 *) &crc, 4);
    // crc += ntry;
    FName classFName = FName( UTF8_TO_TCHAR(className) );
    if (crc == 0) {
      UE_LOG(HaxeLog, Error, TEXT("Unreal.hx CRC for class %s was 0"), *classFName.ToString());
    }
    map.Add(classFName, crc);
  }

#undef READ

  if (!success) {
    UE_LOG(HaxeLog,Error,TEXT("Unreal.hx CRC data was corrupt"));
  }

  delete file;
  return map;
}

TMap<FName, uint32>& ::uhx::DynamicClassHelper::getCrcMap() {
  static TMap<FName, uint32> map = getCrcMapPvt();
  return map;
}

TMap<FName, UClass *>& ::uhx::DynamicClassHelper::getDynamicsMap() {
  static TMap<FName, UClass *> map;
  return map;
}

#endif

#if (WITH_EDITOR && !NO_DYNAMIC_UCLASS)

/**
 * In order to add cppia dynamic class support, we need to be able to call `addDynamicProperties` in a very precise location - which is
 * right before the CDO is created. We must call this before the class CDO is created because otherwise the CDO will have the wrong size,
 * and bad things will happen. This UHxBootstrap class implements an intrinsic class so we can have a callback right when the classes
 * are registering, which is the exact place where we should add the dynamic properties
 **/
class UHxBootstrap : public UObject {
#if UE_VER >= 416
#define UHX_HOTRELOAD 1
#else
#define UHX_HOTRELOAD WITH_HOT_RELOAD_CTORS
#endif

#if UHX_HOTRELOAD
  DECLARE_CASTED_CLASS_INTRINSIC_NO_CTOR_NO_VTABLE_CTOR(UHxBootstrap, UObject, 0, TEXT("/Script/HaxeRuntime"), 0, HAXERUNTIME_API)

  UHxBootstrap(FVTableHelper& Helper) : UObject(Helper) {
  }
#else
  DECLARE_CASTED_CLASS_INTRINSIC_NO_CTOR(UHxBootstrap, UObject, 0, HaxeRuntime, 0, HAXERUNTIME_API)
#endif
  UHxBootstrap(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()) : UObject(ObjectInitializer) {
    static bool endLoadingDynamicCalled = false;
    if (!endLoadingDynamicCalled) {
      endLoadingDynamicCalled = true;
      uhx::expose::HxcppRuntime::endLoadingDynamic();
    }
  }

#undef UHX_HOTRELOAD
};

// make sure that UHxBootstrap is always hot reloaded, as its CRC constantly changes
template<>
struct TClassCompiledInDefer<UHxBootstrap> : public FFieldCompiledInInfo
{
  TClassCompiledInDefer(const TCHAR* InName, SIZE_T InClassSize, uint32 InCrc)
    : FFieldCompiledInInfo(InClassSize, InCrc)
  {
    static FName className = FName("UHxBootstrap");
    ::uhx::DynamicClassHelper::getCrcMap(); // make sure that the crc map is initialized
    this->Crc = uhx_uniqueId;
    UClassCompiledInDefer(this, InName, InClassSize, this->Crc);
  }
  virtual UClass* Register() const override {
    check_hx_init();
    return UHxBootstrap::StaticClass();
  }

#if UE_VER >= 416
  const TCHAR* ClassPackage() const {
    return UHxBootstrap::StaticPackage();
  }

#endif
};

#if UE_VER >= 416
#define UHX_IMPLEMENT_INTRINSIC_CLASS(TClass, TRequiredAPI, TSuperClass, TSuperRequiredAPI, InitCode) IMPLEMENT_INTRINSIC_CLASS(TClass, TRequiredAPI, TSuperClass, TSuperRequiredAPI, "/Script/HaxeRuntime", InitCode)
#else
#define UHX_IMPLEMENT_INTRINSIC_CLASS(TClass, TRequiredAPI, TSuperClass, TSuperRequiredAPI, InitCode) IMPLEMENT_INTRINSIC_CLASS(TClass, TRequiredAPI, TSuperClass, TSuperRequiredAPI, InitCode)
#endif

UHX_IMPLEMENT_INTRINSIC_CLASS(UHxBootstrap, HAXERUNTIME_API, UObject, COREUOBJECT_API,
{
  check_hx_init();
  uhx::expose::HxcppRuntime::startLoadingDynamic();
  for (auto It = ::uhx::DynamicClassHelper::getDynamicsMap().CreateIterator(); It; ++It) {
    UClass *val = It.Value();
    uhx::expose::HxcppRuntime::setDynamicNative((unreal::UIntPtr) val, TCHAR_TO_UTF8(*It.Key().ToString()));
  }
  uhx::expose::HxcppRuntime::setNativeTypes();
  for (auto It = ::uhx::DynamicClassHelper::getDynamicsMap().CreateIterator(); It; ++It) {
    UClass *val = It.Value();
    uhx::expose::HxcppRuntime::addDynamicProperties((unreal::UIntPtr) val, TCHAR_TO_UTF8(*It.Key().ToString()));
  }
});

#undef UHX_IMPLEMENT_INTRINSIC_CLASS

#endif

#endif // WITH_EDITOR
<|endoftext|>


<commit_before>/* Copyright (c) 2013-2014 Jeffrey Pfau
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ConfigController.h"

#include "GameController.h"

#include <QAction>
#include <QMenu>

extern "C" {
#include "platform/commandline.h"
}

using namespace QGBA;

ConfigOption::ConfigOption(QObject* parent)
	: QObject(parent)
{
}

void ConfigOption::connect(std::function<void(const QVariant&)> slot) {
	m_slot = slot;
}

QAction* ConfigOption::addValue(const QString& text, const QVariant& value, QMenu* parent) {
	QAction* action = new QAction(text, parent);
	action->setCheckable(true);
	QObject::connect(action, &QAction::triggered, [this, value]() {
		emit valueChanged(value);
	});
	parent->addAction(action);
	m_actions.append(qMakePair(action, value));
	return action;
}

QAction* ConfigOption::addValue(const QString& text, const char* value, QMenu* parent) {
	return addValue(text, QString(value), parent);
}

QAction* ConfigOption::addBoolean(const QString& text, QMenu* parent) {
	QAction* action = new QAction(text, parent);
	action->setCheckable(true);
	QObject::connect(action, &QAction::triggered, [this, action]() {
		emit valueChanged(action->isChecked());
	});
	parent->addAction(action);
	m_actions.append(qMakePair(action, 1));
	return action;
}

void ConfigOption::setValue(bool value) {
	setValue(QVariant(value));
}

void ConfigOption::setValue(int value) {
	setValue(QVariant(value));
}

void ConfigOption::setValue(unsigned value) {
	setValue(QVariant(value));
}

void ConfigOption::setValue(const char* value) {
	setValue(QVariant(QString(value)));
}

void ConfigOption::setValue(const QVariant& value) {
	QPair<QAction*, QVariant> action;
	foreach(action, m_actions) {
		bool signalsEnabled = action.first->blockSignals(true);
		action.first->setChecked(value == action.second);
		action.first->blockSignals(signalsEnabled);
	}
	m_slot(value);
}

ConfigController::ConfigController(QObject* parent)
	: QObject(parent)
	, m_opts()
{
	GBAConfigInit(&m_config, PORT);

	m_opts.audioSync = GameController::AUDIO_SYNC;
	m_opts.videoSync = GameController::VIDEO_SYNC;
	m_opts.fpsTarget = 60;
	m_opts.audioBuffers = 2048;
	GBAConfigLoadDefaults(&m_config, &m_opts);
	GBAConfigLoad(&m_config);
	GBAConfigMap(&m_config, &m_opts);
}

ConfigController::~ConfigController() {
	write();

	GBAConfigDeinit(&m_config);
	GBAConfigFreeOpts(&m_opts);
}

bool ConfigController::parseArguments(GBAArguments* args, int argc, char* argv[]) {
	return ::parseArguments(args, &m_config, argc, argv, 0);
}

ConfigOption* ConfigController::addOption(const char* key) {
	QString optionName(key);

	if (m_optionSet.contains(optionName)) {
		return m_optionSet[optionName];
	}
	ConfigOption* newOption = new ConfigOption(this);
	m_optionSet[optionName] = newOption;
	connect(newOption, &ConfigOption::valueChanged, [this, key](const QVariant& value) {
		setOption(key, value);
	});
	return newOption;
}

void ConfigController::updateOption(const char* key) {
	if (!key) {
		return;
	}

	QString optionName(key);

	if (!m_optionSet.contains(optionName)) {
		return;
	}
	m_optionSet[optionName]->setValue(GBAConfigGetValue(&m_config, key));
}

void ConfigController::setOption(const char* key, bool value) {
	GBAConfigSetIntValue(&m_config, key, value);
	ConfigOption* option = m_optionSet[QString(key)];
	if (option) {
		option->setValue(value);
	}
}

void ConfigController::setOption(const char* key, int value) {
	GBAConfigSetIntValue(&m_config, key, value);
	ConfigOption* option = m_optionSet[QString(key)];
	if (option) {
		option->setValue(value);
	}
}

void ConfigController::setOption(const char* key, unsigned value) {
	GBAConfigSetUIntValue(&m_config, key, value);
	ConfigOption* option = m_optionSet[QString(key)];
	if (option) {
		option->setValue(value);
	}
}

void ConfigController::setOption(const char* key, const char* value) {
	GBAConfigSetValue(&m_config, key, value);
	ConfigOption* option = m_optionSet[QString(key)];
	if (option) {
		option->setValue(value);
	}
}

void ConfigController::setOption(const char* key, const QVariant& value) {
	if (value.type() == QVariant::Bool) {
		setOption(key, value.toBool());
		return;
	}
	QString stringValue(value.toString());
	setOption(key, stringValue.toLocal8Bit().constData());
}

void ConfigController::write() {
	GBAConfigSave(&m_config);
}
<commit_msg>Qt: Fix config options being erroneously added as null<commit_after>/* Copyright (c) 2013-2014 Jeffrey Pfau
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ConfigController.h"

#include "GameController.h"

#include <QAction>
#include <QMenu>

extern "C" {
#include "platform/commandline.h"
}

using namespace QGBA;

ConfigOption::ConfigOption(QObject* parent)
	: QObject(parent)
{
}

void ConfigOption::connect(std::function<void(const QVariant&)> slot) {
	m_slot = slot;
}

QAction* ConfigOption::addValue(const QString& text, const QVariant& value, QMenu* parent) {
	QAction* action = new QAction(text, parent);
	action->setCheckable(true);
	QObject::connect(action, &QAction::triggered, [this, value]() {
		emit valueChanged(value);
	});
	parent->addAction(action);
	m_actions.append(qMakePair(action, value));
	return action;
}

QAction* ConfigOption::addValue(const QString& text, const char* value, QMenu* parent) {
	return addValue(text, QString(value), parent);
}

QAction* ConfigOption::addBoolean(const QString& text, QMenu* parent) {
	QAction* action = new QAction(text, parent);
	action->setCheckable(true);
	QObject::connect(action, &QAction::triggered, [this, action]() {
		emit valueChanged(action->isChecked());
	});
	parent->addAction(action);
	m_actions.append(qMakePair(action, 1));
	return action;
}

void ConfigOption::setValue(bool value) {
	setValue(QVariant(value));
}

void ConfigOption::setValue(int value) {
	setValue(QVariant(value));
}

void ConfigOption::setValue(unsigned value) {
	setValue(QVariant(value));
}

void ConfigOption::setValue(const char* value) {
	setValue(QVariant(QString(value)));
}

void ConfigOption::setValue(const QVariant& value) {
	QPair<QAction*, QVariant> action;
	foreach(action, m_actions) {
		bool signalsEnabled = action.first->blockSignals(true);
		action.first->setChecked(value == action.second);
		action.first->blockSignals(signalsEnabled);
	}
	m_slot(value);
}

ConfigController::ConfigController(QObject* parent)
	: QObject(parent)
	, m_opts()
{
	GBAConfigInit(&m_config, PORT);

	m_opts.audioSync = GameController::AUDIO_SYNC;
	m_opts.videoSync = GameController::VIDEO_SYNC;
	m_opts.fpsTarget = 60;
	m_opts.audioBuffers = 2048;
	GBAConfigLoadDefaults(&m_config, &m_opts);
	GBAConfigLoad(&m_config);
	GBAConfigMap(&m_config, &m_opts);
}

ConfigController::~ConfigController() {
	write();

	GBAConfigDeinit(&m_config);
	GBAConfigFreeOpts(&m_opts);
}

bool ConfigController::parseArguments(GBAArguments* args, int argc, char* argv[]) {
	return ::parseArguments(args, &m_config, argc, argv, 0);
}

ConfigOption* ConfigController::addOption(const char* key) {
	QString optionName(key);

	if (m_optionSet.contains(optionName)) {
		return m_optionSet[optionName];
	}
	ConfigOption* newOption = new ConfigOption(this);
	m_optionSet[optionName] = newOption;
	connect(newOption, &ConfigOption::valueChanged, [this, key](const QVariant& value) {
		setOption(key, value);
	});
	return newOption;
}

void ConfigController::updateOption(const char* key) {
	if (!key) {
		return;
	}

	QString optionName(key);

	if (!m_optionSet.contains(optionName)) {
		return;
	}
	m_optionSet[optionName]->setValue(GBAConfigGetValue(&m_config, key));
}

void ConfigController::setOption(const char* key, bool value) {
	GBAConfigSetIntValue(&m_config, key, value);
	QString optionName(key);
	if (m_optionSet.contains(optionName)) {
		m_optionSet[optionName]->setValue(value);
	}
}

void ConfigController::setOption(const char* key, int value) {
	GBAConfigSetIntValue(&m_config, key, value);
	QString optionName(key);
	if (m_optionSet.contains(optionName)) {
		m_optionSet[optionName]->setValue(value);
	}
}

void ConfigController::setOption(const char* key, unsigned value) {
	GBAConfigSetUIntValue(&m_config, key, value);
	QString optionName(key);
	if (m_optionSet.contains(optionName)) {
		m_optionSet[optionName]->setValue(value);
	}
}

void ConfigController::setOption(const char* key, const char* value) {
	GBAConfigSetValue(&m_config, key, value);
	QString optionName(key);
	if (m_optionSet.contains(optionName)) {
		m_optionSet[optionName]->setValue(value);
	}
}

void ConfigController::setOption(const char* key, const QVariant& value) {
	if (value.type() == QVariant::Bool) {
		setOption(key, value.toBool());
		return;
	}
	QString stringValue(value.toString());
	setOption(key, stringValue.toLocal8Bit().constData());
}

void ConfigController::write() {
	GBAConfigSave(&m_config);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdexcept>

#include "Token.hpp"
#include "TokenStream.hpp"
#include "Calculator.hpp"

int main(int argc, char* argv[])
{
    if(argc < 2)
    {
        std::cout << "There aren't any operations send to Calculator" << std::endl;
        return 1;
    }

    std::cout << ">> " << argv[1] << std::endl;

    std::string expression{argv[1]};
    TokenStream tokenStream{expression + END_OF_EXPR + QUIT};

    try
    {
        double value = 0;
        Calculator parser{tokenStream};
        while (std::cin)
        {
            try
            {
                Token token = tokenStream.get();
                while (token.kind == END_OF_EXPR)
                {
                    token = tokenStream.get();
                }
                if(token.kind == QUIT)
                {
                    return 0;
                }
                tokenStream.putback(token);
                value = parser.expression();
                std::cout << "= " << value << std::endl;
            }
            catch (std::logic_error& error)
            {
                std::cerr << error.what() << std::endl;
                clean(tokenStream);
            }
        }
        return 0;
    }
    catch (std::logic_error& error)
    {
        std::cerr << error.what() << std::endl;
        return 1;
    }
    catch (...)
    {
        std::cerr << "Unexpected exception";
        return 2;
    }
    return 0;
}

<commit_msg>Splitting body of main into functions<commit_after>#include <iostream>
#include <stdexcept>

#include "Token.hpp"
#include "TokenStream.hpp"
#include "Calculator.hpp"

void calculate(ITokenStream& tokenStream)
{
    double value = 0;
    Calculator parser{tokenStream};
    while (std::cin)
    {
        Token token = tokenStream.get();
        while (token.kind == END_OF_EXPR)
        {
            token = tokenStream.get();
        }
        if(token.kind == QUIT)
        {
            return;
        }
        tokenStream.putback(token);
        value = parser.expression();
        std::cout << "= " << value << std::endl;
    }
}

TokenStream passArgsToTokenStream(const char* argv[])
{
    std::cout << ">> " << argv[1] << std::endl;

    std::string expression{argv[1]};
    TokenStream tokenStream{expression + END_OF_EXPR + QUIT};
    return tokenStream;
}

int main(int argc, const char* argv[])
{
    if(argc < 2)
    {
        std::cout << "There aren't any operations send to Calculator" << std::endl;
        return 1;
    }

    TokenStream tokenStream = passArgsToTokenStream(argv);

    try
    {
        calculate(tokenStream);
        return 0;
    }
    catch (std::logic_error& error)
    {
        std::cerr << error.what() << std::endl;
        clean(tokenStream);
        return 1;
    }
    catch (...)
    {
        std::cerr << "Unexpected exception";
        return 2;
    }

}

<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "stackwindow.h"
#include "stackhandler.h"

#include "debuggeractions.h"
#include "debuggercore.h"
#include "debuggerengine.h"
#include "debuggerdialogs.h"
#include "memoryagent.h"

#include <utils/qtcassert.h>
#include <utils/savedaction.h>

#include <QtCore/QDebug>

#include <QtGui/QApplication>
#include <QtGui/QClipboard>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QHeaderView>
#include <QtGui/QMenu>

namespace Debugger {
namespace Internal {

static DebuggerEngine *currentEngine()
{
    return debuggerCore()->currentEngine();
}

StackWindow::StackWindow(QWidget *parent)
    : BaseWindow(parent)
{
    setWindowTitle(tr("Stack"));
    setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustStackColumnWidths));

    connect(debuggerCore()->action(UseAddressInStackView), SIGNAL(toggled(bool)),
        SLOT(showAddressColumn(bool)));
    connect(debuggerCore()->action(ExpandStack), SIGNAL(triggered()),
        SLOT(reloadFullStack()));
    connect(debuggerCore()->action(MaximalStackDepth), SIGNAL(triggered()),
        SLOT(reloadFullStack()));
    showAddressColumn(false);
}

void StackWindow::showAddressColumn(bool on)
{
    setColumnHidden(4, !on);
}

void StackWindow::rowActivated(const QModelIndex &index)
{
    currentEngine()->activateFrame(index.row());
}

void StackWindow::setModel(QAbstractItemModel *model)
{
    BaseWindow::setModel(model);
    resizeColumnToContents(0);
    resizeColumnToContents(3);
}

void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
{
    DebuggerEngine *engine = currentEngine();
    StackHandler *handler = engine->stackHandler();
    const QModelIndex index = indexAt(ev->pos());
    const int row = index.row();
    const unsigned engineCapabilities = engine->debuggerCapabilities();
    StackFrame frame;
    if (row >= 0 && row < handler->stackSize())
        frame = handler->frameAt(row);
    const quint64 address = frame.address;

    QMenu menu;
    menu.addAction(debuggerCore()->action(ExpandStack));

    QAction *actCopyContents = menu.addAction(tr("Copy Contents to Clipboard"));
    actCopyContents->setEnabled(model() != 0);

    if (engineCapabilities & CreateFullBacktraceCapability)
        menu.addAction(debuggerCore()->action(CreateFullBacktrace));

    QAction *actShowMemory = menu.addAction(QString());
    if (address == 0) {
        actShowMemory->setText(tr("Open Memory Editor"));
        actShowMemory->setEnabled(false);
    } else {
        actShowMemory->setText(tr("Open Memory Editor at 0x%1").arg(address, 0, 16));
        actShowMemory->setEnabled(engineCapabilities & ShowMemoryCapability);
    }

    QAction *actShowDisassemblerAt = menu.addAction(QString());
    QAction *actShowDisassembler = menu.addAction(tr("Open Disassembler..."));
    actShowDisassembler->setEnabled(engineCapabilities & DisassemblerCapability);
    if (address == 0) {
        actShowDisassemblerAt->setText(tr("Open Disassembler"));
        actShowDisassemblerAt->setEnabled(false);
    } else {
        actShowDisassemblerAt->setText(tr("Open Disassembler at 0x%1").arg(address, 0, 16));
        actShowDisassemblerAt->setEnabled(engineCapabilities & DisassemblerCapability);
    }

    QAction *actLoadSymbols = 0;
    if (engineCapabilities & ShowModuleSymbolsCapability)
        actLoadSymbols = menu.addAction(tr("Try to Load Unknown Symbols"));

    menu.addSeparator();
#if 0 // @TODO: not implemented
    menu.addAction(debuggerCore()->action(UseToolTipsInStackView));
#endif
    menu.addAction(debuggerCore()->action(UseAddressInStackView));

    addBaseContextActions(&menu);

    QAction *act = menu.exec(ev->globalPos());

    if (act == actCopyContents)
        copyContentsToClipboard();
    else if (act == actShowMemory) {
        const QString title = tr("Memory at Frame #%1 (%2) 0x%3").
        arg(row).arg(frame.function).arg(address, 0, 16);
        QList<MemoryMarkup> ml;
        ml.push_back(MemoryMarkup(address, 1, QColor(Qt::blue).lighter(),
                                  tr("Frame #%1 (%2)").arg(row).arg(frame.function)));
        engine->openMemoryView(address, 0, ml, QPoint(), title);
    } else if (act == actShowDisassembler) {
        AddressDialog dialog;
        if (address)
            dialog.setAddress(address);
        if (dialog.exec() == QDialog::Accepted)
            currentEngine()->openDisassemblerView(Location(dialog.address()));
    } else if (act == actShowDisassemblerAt)
        engine->openDisassemblerView(frame);
    else if (act == actLoadSymbols)
        engine->loadSymbolsForStack();
    else
        handleBaseContextAction(act);
}

void StackWindow::copyContentsToClipboard()
{
    QString str;
    int n = model()->rowCount();
    int m = model()->columnCount();
    for (int i = 0; i != n; ++i) {
        for (int j = 0; j != m; ++j) {
            QModelIndex index = model()->index(i, j);
            str += model()->data(index).toString();
            str += '\t';
        }
        str += '\n';
    }
    QClipboard *clipboard = QApplication::clipboard();
#    ifdef Q_WS_X11
    clipboard->setText(str, QClipboard::Selection);
#    endif
    clipboard->setText(str, QClipboard::Clipboard);
}

void StackWindow::reloadFullStack()
{
    currentEngine()->reloadFullStack();
}

} // namespace Internal
} // namespace Debugger
<commit_msg>Debugger: Show/Hide Address Column in Stack Window<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "stackwindow.h"
#include "stackhandler.h"

#include "debuggeractions.h"
#include "debuggercore.h"
#include "debuggerengine.h"
#include "debuggerdialogs.h"
#include "memoryagent.h"

#include <utils/qtcassert.h>
#include <utils/savedaction.h>

#include <QtCore/QDebug>

#include <QtGui/QApplication>
#include <QtGui/QClipboard>
#include <QtGui/QContextMenuEvent>
#include <QtGui/QHeaderView>
#include <QtGui/QMenu>

namespace Debugger {
namespace Internal {

static DebuggerEngine *currentEngine()
{
    return debuggerCore()->currentEngine();
}

StackWindow::StackWindow(QWidget *parent)
    : BaseWindow(parent)
{
    setWindowTitle(tr("Stack"));
    setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustStackColumnWidths));

    connect(debuggerCore()->action(UseAddressInStackView), SIGNAL(toggled(bool)),
        SLOT(showAddressColumn(bool)));
    connect(debuggerCore()->action(ExpandStack), SIGNAL(triggered()),
        SLOT(reloadFullStack()));
    connect(debuggerCore()->action(MaximalStackDepth), SIGNAL(triggered()),
        SLOT(reloadFullStack()));
    showAddressColumn(false);
}

void StackWindow::showAddressColumn(bool on)
{
    setColumnHidden(4, !on);
}

void StackWindow::rowActivated(const QModelIndex &index)
{
    currentEngine()->activateFrame(index.row());
}

void StackWindow::setModel(QAbstractItemModel *model)
{
    BaseWindow::setModel(model);
    resizeColumnToContents(0);
    resizeColumnToContents(3);
    showAddressColumn(debuggerCore()->action(UseAddressInStackView)->isChecked());
}

void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
{
    DebuggerEngine *engine = currentEngine();
    StackHandler *handler = engine->stackHandler();
    const QModelIndex index = indexAt(ev->pos());
    const int row = index.row();
    const unsigned engineCapabilities = engine->debuggerCapabilities();
    StackFrame frame;
    if (row >= 0 && row < handler->stackSize())
        frame = handler->frameAt(row);
    const quint64 address = frame.address;

    QMenu menu;
    menu.addAction(debuggerCore()->action(ExpandStack));

    QAction *actCopyContents = menu.addAction(tr("Copy Contents to Clipboard"));
    actCopyContents->setEnabled(model() != 0);

    if (engineCapabilities & CreateFullBacktraceCapability)
        menu.addAction(debuggerCore()->action(CreateFullBacktrace));

    QAction *actShowMemory = menu.addAction(QString());
    if (address == 0) {
        actShowMemory->setText(tr("Open Memory Editor"));
        actShowMemory->setEnabled(false);
    } else {
        actShowMemory->setText(tr("Open Memory Editor at 0x%1").arg(address, 0, 16));
        actShowMemory->setEnabled(engineCapabilities & ShowMemoryCapability);
    }

    QAction *actShowDisassemblerAt = menu.addAction(QString());
    QAction *actShowDisassembler = menu.addAction(tr("Open Disassembler..."));
    actShowDisassembler->setEnabled(engineCapabilities & DisassemblerCapability);
    if (address == 0) {
        actShowDisassemblerAt->setText(tr("Open Disassembler"));
        actShowDisassemblerAt->setEnabled(false);
    } else {
        actShowDisassemblerAt->setText(tr("Open Disassembler at 0x%1").arg(address, 0, 16));
        actShowDisassemblerAt->setEnabled(engineCapabilities & DisassemblerCapability);
    }

    QAction *actLoadSymbols = 0;
    if (engineCapabilities & ShowModuleSymbolsCapability)
        actLoadSymbols = menu.addAction(tr("Try to Load Unknown Symbols"));

    menu.addSeparator();
#if 0 // @TODO: not implemented
    menu.addAction(debuggerCore()->action(UseToolTipsInStackView));
#endif
    menu.addAction(debuggerCore()->action(UseAddressInStackView));

    addBaseContextActions(&menu);

    QAction *act = menu.exec(ev->globalPos());

    if (act == actCopyContents)
        copyContentsToClipboard();
    else if (act == actShowMemory) {
        const QString title = tr("Memory at Frame #%1 (%2) 0x%3").
        arg(row).arg(frame.function).arg(address, 0, 16);
        QList<MemoryMarkup> ml;
        ml.push_back(MemoryMarkup(address, 1, QColor(Qt::blue).lighter(),
                                  tr("Frame #%1 (%2)").arg(row).arg(frame.function)));
        engine->openMemoryView(address, 0, ml, QPoint(), title);
    } else if (act == actShowDisassembler) {
        AddressDialog dialog;
        if (address)
            dialog.setAddress(address);
        if (dialog.exec() == QDialog::Accepted)
            currentEngine()->openDisassemblerView(Location(dialog.address()));
    } else if (act == actShowDisassemblerAt)
        engine->openDisassemblerView(frame);
    else if (act == actLoadSymbols)
        engine->loadSymbolsForStack();
    else
        handleBaseContextAction(act);
}

void StackWindow::copyContentsToClipboard()
{
    QString str;
    int n = model()->rowCount();
    int m = model()->columnCount();
    for (int i = 0; i != n; ++i) {
        for (int j = 0; j != m; ++j) {
            QModelIndex index = model()->index(i, j);
            str += model()->data(index).toString();
            str += '\t';
        }
        str += '\n';
    }
    QClipboard *clipboard = QApplication::clipboard();
#    ifdef Q_WS_X11
    clipboard->setText(str, QClipboard::Selection);
#    endif
    clipboard->setText(str, QClipboard::Clipboard);
}

void StackWindow::reloadFullStack()
{
    currentEngine()->reloadFullStack();
}

} // namespace Internal
} // namespace Debugger
<|endoftext|>


<commit_before>#include "pipeline.h"
#include <iostream>

int main()
{
   using namespace pipeline;

   auto for_each = [](auto&& rng){
      return source([rng](auto&& sink){
         for (auto const& x : rng) if (!sink(x)) return;
      });
   };

   auto pipeline = []{
      return filter     ([](auto x){ return x>3; })
           | transform  ([](auto x){ return x*x; })
           | filter     ([](auto x){ return x<150; })
           | transform  ([](auto x){ return x-10; })
           | take(3)
           | repeat(2)
           ;
   };

   auto p = pipeline() | sink([](auto x) { std::cout << "sink: " << x << std::endl; return true; });

   int n = 0;
   do { std::cout << "source: " << n << std::endl; }
   while ( p(n++) );

   std::cout << "cancelled" << std::endl;

   for_each(std::initializer_list<int>{1,2,3,4,5,6,7,8,9,10,11})
           | pipeline()
           | sink([](auto x) { std::cout << "sink: " << x << std::endl; return true; });;

   std::cout << "cancelled" << std::endl;
}
<commit_msg>fixing for_each source to not capture range by value.<commit_after>#include "pipeline.h"
#include <iostream>

int main()
{
   using namespace pipeline;

   auto for_each = [](auto&& rng){
      return source([&rng](auto&& sink){
         for (auto const& x : rng) if (!sink(x)) return;
      });
   };

   auto pipeline = []{
      return filter     ([](auto x){ return x>3; })
           | transform  ([](auto x){ return x*x; })
           | filter     ([](auto x){ return x<150; })
           | transform  ([](auto x){ return x-10; })
           | take(3)
           | repeat(2)
           ;
   };

   auto p = pipeline() | sink([](auto x) { std::cout << "sink: " << x << std::endl; return true; });

   int n = 0;
   do { std::cout << "source: " << n << std::endl; }
   while ( p(n++) );

   std::cout << "cancelled" << std::endl;

   for_each(std::initializer_list<int>{1,2,3,4,5,6,7,8,9,10,11})
           | pipeline()
           | sink([](auto x) { std::cout << "sink: " << x << std::endl; return true; });;

   std::cout << "cancelled" << std::endl;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2022.  All rights reserved
 */
#ifndef _Stroika_Foundation_Execution_IntervalTimer_inl_
#define _Stroika_Foundation_Execution_IntervalTimer_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

namespace Stroika::Foundation::Execution {

    /*
     ********************************************************************************
     *************************** IntervalTimer::Manager *****************************
     ********************************************************************************
     */
    inline IntervalTimer::Manager::Manager (const shared_ptr<IRep>& rep)
        : fRep_{rep}
    {
    }
    inline void IntervalTimer::Manager::AddOneShot (const TimerCallback& intervalTimer, const Time::Duration& when)
    {
        AssertNotNull (fRep_); // If this fails, and its accessed through IntervalTimer::Manager::sThe, its probably because of lack of construction of IntervalTimer::Manager::Active object.
        fRep_->AddOneShot (intervalTimer, when);
    }
    inline void IntervalTimer::Manager ::AddRepeating (const TimerCallback& intervalTimer, const Time::Duration& repeatInterval, const optional<Time::Duration>& hysteresis)
    {
        AssertNotNull (fRep_); // If this fails, and its accessed through IntervalTimer::Manager::sThe, its probably because of lack of construction of IntervalTimer::Manager::Active object.
        fRep_->AddRepeating (intervalTimer, repeatInterval, hysteresis);
    }
    inline void IntervalTimer::Manager::RemoveRepeating (const TimerCallback& intervalTimer) noexcept
    {
        AssertNotNull (fRep_); // If this fails, and its accessed through IntervalTimer::Manager::sThe, its probably because of lack of construction of IntervalTimer::Manager::Active object.
        fRep_->RemoveRepeating (intervalTimer);
    }
    inline IntervalTimer::Manager IntervalTimer::Manager::sThe{nullptr};

    /*
     ********************************************************************************
     ***************************** IntervalTimer::Adder *****************************
     ********************************************************************************
     */
    inline IntervalTimer::Adder::Adder (IntervalTimer::Manager& manager, const Function<void (void)>& f, const Time::Duration& repeatInterval, RunImmediatelyFlag runImmediately, const optional<Time::Duration>& hysteresis)
        : fRepeatInterval_{repeatInterval}
        , fHysteresis_{hysteresis}
        , fManager_{&manager}
        , fFunction_{f}
    {
        Manager::sThe.AddRepeating (fFunction_, repeatInterval, hysteresis);
        if (runImmediately == RunImmediatelyFlag::eRunImmediately) {
            fFunction_ ();
        }
    }
    inline IntervalTimer::Adder::Adder (const Function<void (void)>& f, const Time::Duration& repeatInterval, RunImmediatelyFlag runImmediately, const optional<Time::Duration>& hysteresis)
        : Adder{Manager::sThe, f, repeatInterval, runImmediately, hysteresis}
    {
    }
    inline IntervalTimer::Adder::Adder (IntervalTimer::Manager& manager, const Function<void (void)>& f, const Time::Duration& repeatInterval, RunImmediatelyFlag runImmediately)
        : Adder{manager, f, repeatInterval, runImmediately, nullopt}
    {
    }
    inline IntervalTimer::Adder::Adder (const Function<void (void)>& f, const Time::Duration& repeatInterval, RunImmediatelyFlag runImmediately)
        : Adder{f, repeatInterval, runImmediately, nullopt}
    {
    }
    inline IntervalTimer::Adder::Adder (IntervalTimer::Manager& manager, const Function<void (void)>& f, const Time::Duration& repeatInterval, const optional<Time::Duration>& hysteresis)
        : Adder{manager, f, repeatInterval, RunImmediatelyFlag::eDontRunImmediately, hysteresis}
    {
    }
    inline IntervalTimer::Adder::Adder (const Function<void (void)>& f, const Time::Duration& repeatInterval, const optional<Time::Duration>& hysteresis)
        : Adder{Manager::sThe, f, repeatInterval, RunImmediatelyFlag::eDontRunImmediately, hysteresis}
    {
    }
    inline IntervalTimer::Adder::Adder (Adder&& src)
        : fRepeatInterval_{move (src.fRepeatInterval_)}
        , fHysteresis_{move (src.fHysteresis_)}
        , fManager_{src.fManager_}
        , fFunction_{move (src.fFunction_)}
    {
        // Move does not trigger re-add to manager
        src.fManager_ = nullptr; // so its DTOR does nothing
    }
    inline IntervalTimer::Adder::~Adder ()
    {
        if (fManager_ != nullptr) { // null check cuz Adder can be moved
            fManager_->RemoveRepeating (fFunction_);
        }
    }
    inline IntervalTimer::Adder& IntervalTimer::Adder::operator= (Adder&& rhs)
    {
        if (this != &rhs) {
            if (fManager_ != nullptr) { // null check cuz Adder can be moved
                fManager_->RemoveRepeating (fFunction_);
            }
            fManager_     = rhs.fManager_;
            rhs.fManager_ = nullptr; // so its DTOR doesnt remove
            fFunction_    = move (rhs.fFunction_);
            Manager::sThe.AddRepeating (fFunction_, fRepeatInterval_, fHysteresis_);
        }
        return *this;
    }
    inline Function<void (void)> IntervalTimer::Adder::GetCallback () const
    {
        return fFunction_;
    }

}

#endif /*_Stroika_Foundation_Execution_IntervalTimer_inl_*/
<commit_msg>tweak last checkin<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2022.  All rights reserved
 */
#ifndef _Stroika_Foundation_Execution_IntervalTimer_inl_
#define _Stroika_Foundation_Execution_IntervalTimer_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

namespace Stroika::Foundation::Execution {

    /*
     ********************************************************************************
     *************************** IntervalTimer::Manager *****************************
     ********************************************************************************
     */
    inline IntervalTimer::Manager::Manager (const shared_ptr<IRep>& rep)
        : fRep_{rep}
    {
    }
    inline void IntervalTimer::Manager::AddOneShot (const TimerCallback& intervalTimer, const Time::Duration& when)
    {
        AssertNotNull (fRep_); // If this fails, and its accessed through IntervalTimer::Manager::sThe, its probably because of lack of construction of IntervalTimer::Manager::Active object.
        fRep_->AddOneShot (intervalTimer, when);
    }
    inline void IntervalTimer::Manager ::AddRepeating (const TimerCallback& intervalTimer, const Time::Duration& repeatInterval, const optional<Time::Duration>& hysteresis)
    {
        AssertNotNull (fRep_); // If this fails, and its accessed through IntervalTimer::Manager::sThe, its probably because of lack of construction of IntervalTimer::Manager::Active object.
        fRep_->AddRepeating (intervalTimer, repeatInterval, hysteresis);
    }
    inline void IntervalTimer::Manager::RemoveRepeating (const TimerCallback& intervalTimer) noexcept
    {
        AssertNotNull (fRep_); // If this fails, and its accessed through IntervalTimer::Manager::sThe, its probably because of lack of construction of IntervalTimer::Manager::Active object.
        fRep_->RemoveRepeating (intervalTimer);
    }
    inline IntervalTimer::Manager IntervalTimer::Manager::sThe{nullptr};

    /*
     ********************************************************************************
     ***************************** IntervalTimer::Adder *****************************
     ********************************************************************************
     */
    inline IntervalTimer::Adder::Adder (IntervalTimer::Manager& manager, const Function<void (void)>& f, const Time::Duration& repeatInterval, RunImmediatelyFlag runImmediately, const optional<Time::Duration>& hysteresis)
        : fRepeatInterval_{repeatInterval}
        , fHysteresis_{hysteresis}
        , fManager_{&manager}
        , fFunction_{f}
    {
        Manager::sThe.AddRepeating (fFunction_, repeatInterval, hysteresis);
        if (runImmediately == RunImmediatelyFlag::eRunImmediately) {
            IgnoreExceptionsExceptThreadAbortForCall (fFunction_ ());
        }
    }
    inline IntervalTimer::Adder::Adder (const Function<void (void)>& f, const Time::Duration& repeatInterval, RunImmediatelyFlag runImmediately, const optional<Time::Duration>& hysteresis)
        : Adder{Manager::sThe, f, repeatInterval, runImmediately, hysteresis}
    {
    }
    inline IntervalTimer::Adder::Adder (IntervalTimer::Manager& manager, const Function<void (void)>& f, const Time::Duration& repeatInterval, RunImmediatelyFlag runImmediately)
        : Adder{manager, f, repeatInterval, runImmediately, nullopt}
    {
    }
    inline IntervalTimer::Adder::Adder (const Function<void (void)>& f, const Time::Duration& repeatInterval, RunImmediatelyFlag runImmediately)
        : Adder{f, repeatInterval, runImmediately, nullopt}
    {
    }
    inline IntervalTimer::Adder::Adder (IntervalTimer::Manager& manager, const Function<void (void)>& f, const Time::Duration& repeatInterval, const optional<Time::Duration>& hysteresis)
        : Adder{manager, f, repeatInterval, RunImmediatelyFlag::eDontRunImmediately, hysteresis}
    {
    }
    inline IntervalTimer::Adder::Adder (const Function<void (void)>& f, const Time::Duration& repeatInterval, const optional<Time::Duration>& hysteresis)
        : Adder{Manager::sThe, f, repeatInterval, RunImmediatelyFlag::eDontRunImmediately, hysteresis}
    {
    }
    inline IntervalTimer::Adder::Adder (Adder&& src)
        : fRepeatInterval_{move (src.fRepeatInterval_)}
        , fHysteresis_{move (src.fHysteresis_)}
        , fManager_{src.fManager_}
        , fFunction_{move (src.fFunction_)}
    {
        // Move does not trigger re-add to manager
        src.fManager_ = nullptr; // so its DTOR does nothing
    }
    inline IntervalTimer::Adder::~Adder ()
    {
        if (fManager_ != nullptr) { // null check cuz Adder can be moved
            fManager_->RemoveRepeating (fFunction_);
        }
    }
    inline IntervalTimer::Adder& IntervalTimer::Adder::operator= (Adder&& rhs)
    {
        if (this != &rhs) {
            if (fManager_ != nullptr) { // null check cuz Adder can be moved
                fManager_->RemoveRepeating (fFunction_);
            }
            fManager_     = rhs.fManager_;
            rhs.fManager_ = nullptr; // so its DTOR doesnt remove
            fFunction_    = move (rhs.fFunction_);
            Manager::sThe.AddRepeating (fFunction_, fRepeatInterval_, fHysteresis_);
        }
        return *this;
    }
    inline Function<void (void)> IntervalTimer::Adder::GetCallback () const
    {
        return fFunction_;
    }

}

#endif /*_Stroika_Foundation_Execution_IntervalTimer_inl_*/
<|endoftext|>


<commit_before>
#include <arpa/inet.h>
#include <string>

#include "format.h"
#include "config.h"
#include "error.h"
#include "udp_socket.h"
#include "strutils.h"

////////////////////////////////////////

std::string pack_name( const std::string &name )
{
	std::string ret;
	size_t loc = 0;
	ret.push_back( '\0' );
	for ( size_t i = 0; i < name.size(); ++i )
	{
		if ( std::isalnum( name[i] ) )
		{
			ret.push_back( name[i] );
			ret[loc]++;
		}
		else if ( name[i] == '.' )
		{
			loc = ret.size();
			ret.push_back( '\0' );
		}
		else if ( !std::isspace( name[i] ) )
			error( "Invalid character in domain name" );
	}

	if ( ret.back() == '\0' )
		error( "Domain name ended with '.'" );

	if ( ret.empty() )
		error( "Domain name is empty." );

	ret.push_back( '\0' );

	return ret;
}

////////////////////////////////////////

void unpack_names( const std::string &str, std::vector<std::string> &n )
{
	std::string ret;

	for ( size_t i = 0; i < str.size(); )
	{
		uint8_t s = str[i++];
		if ( s == 0 )
		{
			if ( !ret.empty() )
				n.push_back( ret );
			ret.clear();
		}
		else
		{
			if ( !ret.empty() )
				ret.push_back( '.' );
			ret += str.substr( i, s );
			i += s;
		}
	}

	if ( !ret.empty() )
		n.push_back( ret );
}

////////////////////////////////////////

std::string from_hex( const std::string &h )
{
	std::string ret;
	for ( size_t i = 0; i+1 < h.size(); i += 2 )
		ret.push_back( std::stoul( h.substr( i, 2 ), NULL, 16 ) );
	return ret;
}

////////////////////////////////////////

std::string parse_mac( const std::string &opt )
{
	std::string ret( 6, '\0' );

	size_t p = 0;
	for ( size_t i = 0; i < ret.size(); ++i )
	{
		size_t tmp = p;
		uint32_t v = std::stoi( opt.substr( p ), &tmp, 16 );
		ret[i] = v;
		p += tmp + 1;
	}

	return ret;
}

////////////////////////////////////////

std::string parse_option( const std::string &opt )
{
	std::string name;
	std::vector<std::string> args;

	parse_function( opt, name, args );

	if ( dhcp_options.find( name ) == dhcp_options.end() )
		error( format( "Unknown DHCP option '{0}'", name ) );

	int o = dhcp_options[name];
	std::vector<Type> &argtypes = dhcp_args[o];

	if ( argtypes.back() == TYPE_MORE )
	{
		argtypes.pop_back();
		while ( argtypes.size() < args.size() )
			argtypes.push_back( argtypes.back() );
	}
	if ( argtypes.size() == 1 && argtypes[0] == TYPE_NAMES )
	{
		while ( argtypes.size() < args.size() )
			argtypes.push_back( argtypes.back() );
	}

	if ( argtypes.size() != args.size() )
		error( format( "Expected {0} arguments, got {1} instead", argtypes.size(), args.size() ) );

	std::string ret;
	ret.push_back( o );
	ret.push_back( '\0' );

	size_t size = 0;

	for ( size_t i = 0; i < args.size(); ++i )
	{
		switch ( argtypes[i] )
		{
			case TYPE_ADDRESS:
			{
				size += 4;
				uint32_t ip = dns_lookup( args[i].c_str() );
				ret.append( std::string( reinterpret_cast<const char*>(&ip), 4 ) );
				break;
			}

			case TYPE_HWADDR:
				error( "Not yet implemented" );
				break;

			case TYPE_STRING:
				size += args[i].size();
				ret.append( args[i] );
				break;

			case TYPE_NAMES:
			{
				std::string tmp = pack_name( args[i] );
				ret.append( tmp );
				size += tmp.size();
				break;
			}

			case TYPE_UINT32:
			{
				size += 4;
				uint32_t ip = std::stoul( args[i] );
				ret.append( reinterpret_cast<const char *>(&ip), 4 );
				break;
			}

			case TYPE_UINT16:
			{
				size += 2;
				uint16_t n = htons( std::stoul( args[i] ) );
				ret.append( reinterpret_cast<const char*>( &n ), 2 );
				break;
			}

			case TYPE_UINT8:
			{
				size += 1;
				uint32_t n = std::stoul( args[0] );
				if ( n > 255 )
					error( format( "Number (argument {0}) too large for option {1}", i, name ) );
				ret.push_back( n );
				break;
			}

			case TYPE_HEX:
			{
				std::string hex = from_hex( args[i] );
				ret.push_back( hex.size() );
				ret.append( hex );
				break;
			}

			default:
				error( "Unknown option type" );
				break;
		}
	}

	ret[1] = size;

	return ret;
}

////////////////////////////////////////

std::string print_options( const std::string &opt )
{
	std::string ret;

	if ( opt.empty() )
		error( "Invalid empty option" );

	auto name = dhcp_names.find( uint8_t(opt[0]) );
	if ( name == dhcp_names.end() )
	{
		ret = format( "{0,B16,w2,f0}", as_hex<char>( opt ) );
		return ret;
	}

	ret += name->second;
	ret.push_back( '(' );

	std::vector<Type> &argtypes = dhcp_args[uint8_t(opt[0])];

	size_t p = 2;
	Type last = TYPE_MORE;
	for ( size_t i = 0; i < argtypes.size(); ++i )
	{
		if ( i > 0 )
			ret.push_back( ',' );
		ret.push_back( ' ' );

		Type atype = argtypes[i];
		if ( atype == TYPE_MORE )
			atype = last;

		if ( atype == TYPE_MORE )
			error( "Invalid option specification" );

		switch ( atype )
		{
			case TYPE_ADDRESS:
				if ( p+4 > opt.size() )
					error( "Not enough data for IP address" );
				ret += format( "{0}", as_hex<char>( &opt[p], 4, '.' ) );
				break;

			case TYPE_HWADDR:
				error( "Not yet implemented" );
				break;

			case TYPE_UINT32:
			{
				if ( p+4 > opt.size() )
					error( "Not enough data for uint32" );
				uint32_t n = 0;
				for ( int i = 0; i < 4; ++i )
					n = ( n << 8 ) + uint8_t(opt[p+i]);
				ret += format( "{0}", n );
				break;
			}

			case TYPE_UINT16:
			{
				if ( p+2 > opt.size() )
					error( "Not enough data for uint16" );
				uint32_t n = 0;
				for ( int i = 0; i < 2; ++i )
					n = ( n << 8 ) + uint8_t(opt[p+i]);
				ret += format( "{0}", n );
				break;
			}

			case TYPE_UINT8:
			{
				if ( p+1 > opt.size() )
					error( "Not enough data for uint8" );
				uint32_t n = uint8_t(opt[p]);
				ret += format( "{0}", n );
				break;
			}

			case TYPE_STRING:
				ret += opt.substr( p, size_t(uint8_t(opt[1])) );
				break;

			case TYPE_HEX:
			{
				if ( opt.size() < 3 )
					error( format( "Invalid option size {0}", opt.size() ) );
				ret += format( "{0,B16,w2,f0}", as_hex<char>( opt.substr( 2, opt[1] ) ) );
				break;
			}

			case TYPE_NAMES:
			{
				std::vector<std::string> names;
				unpack_names( opt.substr( p, size_t(uint8_t(opt[1])) ), names );
				for ( size_t i = 0; i < names.size(); ++i )
				{
					if ( i > 0 )
						ret.append( ", " );
					ret += names[i];
				}
				break;
			}

			default:
				error( "Unknown option type" );
				break;
		}
		last = atype;
	}
	ret += " )";

	return ret;
}

<commit_msg>Fixed various bugs when printing options.<commit_after>
#include <arpa/inet.h>
#include <string>

#include "format.h"
#include "config.h"
#include "error.h"
#include "udp_socket.h"
#include "strutils.h"

////////////////////////////////////////

std::string pack_name( const std::string &name )
{
	std::string ret;
	size_t loc = 0;
	ret.push_back( '\0' );
	for ( size_t i = 0; i < name.size(); ++i )
	{
		if ( std::isalnum( name[i] ) )
		{
			ret.push_back( name[i] );
			ret[loc]++;
		}
		else if ( name[i] == '.' )
		{
			loc = ret.size();
			ret.push_back( '\0' );
		}
		else if ( !std::isspace( name[i] ) )
			error( "Invalid character in domain name" );
	}

	if ( ret.back() == '\0' )
		error( "Domain name ended with '.'" );

	if ( ret.empty() )
		error( "Domain name is empty." );

	ret.push_back( '\0' );

	return ret;
}

////////////////////////////////////////

void unpack_names( const std::string &str, std::vector<std::string> &n )
{
	std::string ret;

	for ( size_t i = 0; i < str.size(); )
	{
		uint8_t s = str[i++];
		if ( s == 0 )
		{
			if ( !ret.empty() )
				n.push_back( ret );
			ret.clear();
		}
		else
		{
			if ( !ret.empty() )
				ret.push_back( '.' );
			ret += str.substr( i, s );
			i += s;
		}
	}

	if ( !ret.empty() )
		n.push_back( ret );
}

////////////////////////////////////////

std::string from_hex( const std::string &h )
{
	std::string ret;
	for ( size_t i = 0; i+1 < h.size(); i += 2 )
		ret.push_back( std::stoul( h.substr( i, 2 ), NULL, 16 ) );
	return ret;
}

////////////////////////////////////////

std::string parse_mac( const std::string &opt )
{
	std::string ret( 6, '\0' );

	size_t p = 0;
	for ( size_t i = 0; i < ret.size(); ++i )
	{
		size_t tmp = p;
		uint32_t v = std::stoi( opt.substr( p ), &tmp, 16 );
		ret[i] = v;
		p += tmp + 1;
	}

	return ret;
}

////////////////////////////////////////

std::string parse_option( const std::string &opt )
{
	std::string name;
	std::vector<std::string> args;

	parse_function( opt, name, args );

	if ( dhcp_options.find( name ) == dhcp_options.end() )
		error( format( "Unknown DHCP option '{0}'", name ) );

	int o = dhcp_options[name];
	std::vector<Type> argtypes = dhcp_args[o];

	if ( argtypes.back() == TYPE_MORE )
	{
		argtypes.pop_back();
		while ( argtypes.size() < args.size() )
			argtypes.push_back( argtypes.back() );
	}
	if ( argtypes.size() == 1 && argtypes[0] == TYPE_NAMES )
	{
		while ( argtypes.size() < args.size() )
			argtypes.push_back( argtypes.back() );
	}

	if ( argtypes.size() != args.size() )
		error( format( "Expected {0} arguments, got {1} instead", argtypes.size(), args.size() ) );

	std::string ret;
	ret.push_back( o );
	ret.push_back( '\0' );

	size_t size = 0;

	for ( size_t i = 0; i < args.size(); ++i )
	{
		switch ( argtypes[i] )
		{
			case TYPE_ADDRESS:
			{
				size += 4;
				uint32_t ip = dns_lookup( args[i].c_str() );
				ret.append( std::string( reinterpret_cast<const char*>(&ip), 4 ) );
				break;
			}

			case TYPE_HWADDR:
				error( "Not yet implemented" );
				break;

			case TYPE_STRING:
				size += args[i].size();
				ret.append( args[i] );
				break;

			case TYPE_NAMES:
			{
				std::string tmp = pack_name( args[i] );
				ret.append( tmp );
				size += tmp.size();
				break;
			}

			case TYPE_UINT32:
			{
				size += 4;
				uint32_t ip = std::stoul( args[i] );
				ret.append( reinterpret_cast<const char *>(&ip), 4 );
				break;
			}

			case TYPE_UINT16:
			{
				size += 2;
				uint16_t n = htons( std::stoul( args[i] ) );
				ret.append( reinterpret_cast<const char*>( &n ), 2 );
				break;
			}

			case TYPE_UINT8:
			{
				size += 1;
				uint32_t n = std::stoul( args[i] );
				if ( n > 255 )
					error( format( "Number (argument {0}) too large for option {1}", i, name ) );
				ret.push_back( n );
				break;
			}

			case TYPE_HEX:
			{
				std::string hex = from_hex( args[i] );
				ret.push_back( hex.size() );
				ret.append( hex );
				break;
			}

			default:
				error( "Unknown option type" );
				break;
		}
	}

	ret[1] = size;

	return ret;
}

////////////////////////////////////////

std::string print_options( const std::string &opt )
{
	std::string ret;

	if ( opt.empty() )
		error( "Invalid empty option" );

	auto name = dhcp_names.find( uint8_t(opt[0]) );
	if ( name == dhcp_names.end() )
	{
		ret = format( "{0,B16,w2,f0}", as_hex<char>( opt ) );
		return ret;
	}

	ret += name->second;
	ret.push_back( '(' );

	std::vector<Type> argtypes = dhcp_args[uint8_t(opt[0])];

	size_t p = 2;
	Type last = TYPE_MORE;
	for ( size_t i = 0; i < argtypes.size() && p != opt.size(); ++i )
	{
		if ( i > 0 )
			ret.push_back( ',' );
		ret.push_back( ' ' );

		Type atype = argtypes[i];
		if ( atype == TYPE_MORE )
		{
			atype = last;
			argtypes.push_back( TYPE_MORE );
		}

		if ( atype == TYPE_MORE )
			error( "Invalid option specification" );

		switch ( atype )
		{
			case TYPE_ADDRESS:
				if ( p+4 > opt.size() )
					error( "Not enough data for IP address" );
				ret += format( "{0}", as_hex<char>( &opt[p], 4, '.' ) );
				p += 4;
				break;

			case TYPE_HWADDR:
				error( "Not yet implemented" );
				break;

			case TYPE_UINT32:
			{
				if ( p+4 > opt.size() )
					error( "Not enough data for uint32" );
				uint32_t n = 0;
				for ( int i = 0; i < 4; ++i )
					n = ( n << 8 ) + uint8_t(opt[p+i]);
				ret += format( "{0}", n );
				p += 4;
				break;
			}

			case TYPE_UINT16:
			{
				if ( p+2 > opt.size() )
					error( "Not enough data for uint16" );
				uint32_t n = 0;
				for ( int i = 0; i < 2; ++i )
					n = ( n << 8 ) + uint8_t(opt[p+i]);
				ret += format( "{0}", n );
				p += 2;
				break;
			}

			case TYPE_UINT8:
			{
				if ( p+1 > opt.size() )
					error( "Not enough data for uint8" );
				uint32_t n = uint8_t(opt[p]);
				ret += format( "{0}", n );
				p += 1;
				break;
			}

			case TYPE_STRING:
			{
				size_t size = uint8_t( opt[1] );
				ret += opt.substr( p, size );
				p += size;
				break;
			}

			case TYPE_HEX:
			{
				if ( opt.size() < 3 )
					error( format( "Invalid option size {0}", opt.size() ) );

				size_t size = uint8_t( opt[1] );
				ret += format( "{0,B16,w2,f0}", as_hex<char>( opt.substr( 2, size ) ) );
				p += size;
				break;
			}

			case TYPE_NAMES:
			{
				std::vector<std::string> names;

				size_t size = uint8_t( opt[1] );
				unpack_names( opt.substr( p, size ), names );
				for ( size_t i = 0; i < names.size(); ++i )
				{
					if ( i > 0 )
						ret.append( ", " );
					ret += names[i];
				}
				p += size;
				break;
			}

			default:
				error( "Unknown option type" );
				break;
		}
		last = atype;
	}
	ret += " )";

	return ret;
}

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_SmallStackBuffer_inl_
#define _Stroika_Foundation_Memory_SmallStackBuffer_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include <algorithm>
#include <cstring>
#include <type_traits>

#include "../Debug/Assertions.h"
#include "../Execution/Exceptions.h"
#include "Common.h"

namespace Stroika::Foundation::Memory {

    /*
     ********************************************************************************
     ************************* SmallStackBuffer<T, BUF_SIZE> ************************
     ********************************************************************************
     */
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer ()
        : fLiveData_ (BufferAsT_ ())
    {
#if qDebug
        ::memcpy (fGuard1_, kGuard1_, sizeof (kGuard1_));
        ::memcpy (fGuard2_, kGuard2_, sizeof (kGuard2_));
#endif
        Invariant ();
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer (size_t nElements)
        : SmallStackBuffer ()
    {
        resize (nElements);
        Invariant ();
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer (UninitializedConstructorFlag, size_t nElements)
        : SmallStackBuffer ()
    {
        static_assert (is_trivially_default_constructible_v<T>);
        resize_uninitialized (nElements);
        Invariant ();
    }
    template <typename T, size_t BUF_SIZE>
    template <typename ITERATOR_OF_T, enable_if_t<Configuration::is_iterator_v<ITERATOR_OF_T>, char>*>
    SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer (ITERATOR_OF_T start, ITERATOR_OF_T end)
        : SmallStackBuffer (distance (start, end))
    {
#if qCompilerAndStdLib_uninitialized_copy_n_Warning_Buggy
        Configuration::uninitialized_copy_MSFT_BWA (start, end, this->begin ());
#else
        uninitialized_copy (start, end, this->begin ());
#endif
        Invariant ();
    }
    template <typename T, size_t BUF_SIZE>
    template <size_t FROM_BUF_SIZE>
    SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer (const SmallStackBuffer<T, FROM_BUF_SIZE>& from)
        : SmallStackBuffer (from.begin (), from.end ())
    {
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer (const SmallStackBuffer& from)
        : SmallStackBuffer (from.begin (), from.end ())
    {
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::~SmallStackBuffer ()
    {
        Invariant ();
        DestroyElts_ (this->begin (), this->end ());
        if (fLiveData_ != BufferAsT_ ()) {
            // we must have used the heap...
            Deallocate_ (LiveDataAsAllocatedBytes_ ());
        }
    }
    template <typename T, size_t BUF_SIZE>
    template <size_t FROM_BUF_SIZE>
    SmallStackBuffer<T, BUF_SIZE>& SmallStackBuffer<T, BUF_SIZE>::operator= (const SmallStackBuffer<T, FROM_BUF_SIZE>& rhs)
    {
        Invariant ();
        // @todo this simple implementation could be more efficient
        DestroyElts_ (this->begin (), this->end ());
        fSize_ = 0;
        ReserveAtLeast (rhs.size ());
#if qCompilerAndStdLib_uninitialized_copy_n_Warning_Buggy
        Configuration::uninitialized_copy_MSFT_BWA (rhs.begin (), rhs.end (), this->begin ());
#else
        uninitialized_copy (rhs.begin (), rhs.end (), this->begin ());
#endif
        Invariant ();
        return *this;
    }
    template <typename T, size_t BUF_SIZE>
    SmallStackBuffer<T, BUF_SIZE>& SmallStackBuffer<T, BUF_SIZE>::operator= (const SmallStackBuffer& rhs)
    {
        Invariant ();
        if (this != &rhs) {
            // @todo this simple implementation could be more efficient
            DestroyElts_ (this->begin (), this->end ());
            fSize_ = 0;
            ReserveAtLeast (rhs.size ());
#if qCompilerAndStdLib_uninitialized_copy_n_Warning_Buggy
            Configuration::uninitialized_copy_MSFT_BWA (rhs.begin (), rhs.end (), this->begin ());
#else
            uninitialized_copy (rhs.begin (), rhs.end (), this->begin ());
#endif
            Invariant ();
        }
        return *this;
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::GrowToSize (size_t nElements)
    {
        if (nElements > size ()) {
            resize (nElements);
        }
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::GrowToSize_uninitialized (size_t nElements)
    {
        static_assert (is_trivially_default_constructible_v<T>);
        if (nElements > size ()) {
            resize_uninitialized (nElements);
        }
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::resize (size_t nElements)
    {
        if (nElements > fSize_) {
            // Growing
            if (nElements > capacity ()) {
                /*
                 *   If we REALLY must grow, the double in size so unlikely we'll have to grow/malloc/copy again.
                 */
                reserve (max (nElements, capacity () * 2));
            }
            uninitialized_fill (this->begin () + fSize_, this->begin () + nElements, T{});
            fSize_ = nElements;
        }
        else if (nElements < fSize_) {
            // Shrinking
            DestroyElts_ (this->begin () + nElements, this->end ());
            fSize_ = nElements;
        }
        Assert (fSize_ == nElements);
        Ensure (size () <= capacity ());
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::resize_uninitialized (size_t nElements)
    {
        static_assert (is_trivially_default_constructible_v<T>);
        if (nElements > fSize_) {
            // Growing
            if (nElements > capacity ())
                [[UNLIKELY_ATTR]]
                {
                    /*
                 *   If we REALLY must grow, the double in size so unlikely we'll have to grow/malloc/copy again.
                 */
                    reserve (max (nElements, capacity () * 2));
                }
            fSize_ = nElements;
        }
        else if (nElements < fSize_) {
            // Shrinking
            DestroyElts_ (this->begin () + nElements, this->end ());
            fSize_ = nElements;
        }
        Assert (fSize_ == nElements);
        Ensure (size () <= capacity ());
    }
    template <typename T, size_t BUF_SIZE>
    void SmallStackBuffer<T, BUF_SIZE>::reserve_ (size_t nElements)
    {
        Assert (nElements >= size ());
        Invariant ();
        size_t oldEltCount = capacity ();
        if (nElements != oldEltCount) {
            bool oldInPlaceBuffer = oldEltCount <= BUF_SIZE;
            bool newInPlaceBuffer = nElements <= BUF_SIZE;
            // Only if we changed if using inplace buffer, or if was and is using ramBuffer, and eltCount changed do we need to do anything
            if (oldInPlaceBuffer != newInPlaceBuffer or (not newInPlaceBuffer)) {
                bool          memoryAllocationNeeded = not newInPlaceBuffer;
                Memory::Byte* newPtr                 = memoryAllocationNeeded ? Allocate_ (SizeInBytes_ (nElements)) : std::begin (fInlinePreallocatedBuffer_);

                // Initialize new memory from old
                Assert (this->begin () != reinterpret_cast<T*> (newPtr));
#if qCompilerAndStdLib_uninitialized_copy_n_Warning_Buggy
                Configuration::uninitialized_copy_MSFT_BWA (this->begin (), this->end (), reinterpret_cast<T*> (newPtr));
#else
                uninitialized_copy (this->begin (), this->end (), reinterpret_cast<T*> (newPtr));
#endif

                // destroy objects in old memory
                DestroyElts_ (this->begin (), this->end ());

                // free old memory if needed
                if (not oldInPlaceBuffer) {
                    Assert (fLiveData_ != BufferAsT_ ());
                    Deallocate_ (LiveDataAsAllocatedBytes_ ());
                }

                fLiveData_ = reinterpret_cast<T*> (newPtr);
                if (not newInPlaceBuffer) {
                    fCapacityOfFreeStoreAllocation_ = nElements;
                }
            }
        }
        Ensure ((nElements <= BUF_SIZE && capacity () == BUF_SIZE) or (nElements > BUF_SIZE and nElements == capacity ()));
        Invariant ();
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::iterator SmallStackBuffer<T, BUF_SIZE>::begin ()
    {
        return fLiveData_;
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::iterator SmallStackBuffer<T, BUF_SIZE>::end ()
    {
        return fLiveData_ + fSize_;
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::const_iterator SmallStackBuffer<T, BUF_SIZE>::begin () const
    {
        return fLiveData_;
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::const_iterator SmallStackBuffer<T, BUF_SIZE>::end () const
    {
        return fLiveData_ + fSize_;
    }
    template <typename T, size_t BUF_SIZE>
    inline size_t SmallStackBuffer<T, BUF_SIZE>::capacity () const
    {
        return (fLiveData_ == BufferAsT_ ()) ? BUF_SIZE : fCapacityOfFreeStoreAllocation_; // @see class Design Note
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::reserve (size_t newCapacity)
    {
        Require (newCapacity >= size ());
        reserve_ (newCapacity);
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::ReserveAtLeast (size_t newCapacity)
    {
        if (newCapacity > capacity ()) {
            reserve_ (newCapacity);
        }
    }
    template <typename T, size_t BUF_SIZE>
    inline size_t SmallStackBuffer<T, BUF_SIZE>::GetSize () const
    {
        Ensure (fSize_ <= capacity ());
        return fSize_;
    }
    template <typename T, size_t BUF_SIZE>
    inline size_t SmallStackBuffer<T, BUF_SIZE>::size () const
    {
        Ensure (fSize_ <= capacity ());
        return fSize_;
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::reference SmallStackBuffer<T, BUF_SIZE>::at (size_t i)
    {
        Require (i < fSize_);
        return *(fLiveData_ + i);
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::const_reference SmallStackBuffer<T, BUF_SIZE>::at (size_t i) const
    {
        Require (i < fSize_);
        return *(fLiveData_ + i);
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::push_back (Configuration::ArgByValueType<T> e)
    {
        size_t s = size ();
        if (s < capacity ()) {
#if qCompilerAndStdLib_uninitialized_copy_n_Warning_Buggy
            Configuration::uninitialized_copy_MSFT_BWA (&e, &e + 1, this->end ());
#else
            uninitialized_copy (&e, &e + 1, this->end ());
#endif
            this->fSize_++;
        }
        else {
            if constexpr (is_trivially_default_constructible_v<T>) {
                resize_uninitialized (s + 1);
            }
            else {
                resize (s + 1);
            }
            fLiveData_[s] = e;
        }
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::operator T* ()
    {
        AssertNotNull (fLiveData_);
        return fLiveData_;
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::operator const T* () const
    {
        AssertNotNull (fLiveData_);
        return fLiveData_;
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::Invariant () const
    {
#if qDebug
        Invariant_ ();
#endif
    }
#if qDebug
    template <typename T, size_t BUF_SIZE>
    void SmallStackBuffer<T, BUF_SIZE>::Invariant_ () const
    {
        Assert (capacity () >= size ());
        ValidateGuards_ ();
    }
#if qCompiler_cpp17InlineStaticMemberOfTemplateLinkerUndefined_Buggy
    template <typename T, size_t BUF_SIZE>
    constexpr Byte SmallStackBuffer<T, BUF_SIZE>::kGuard1_[8];
    template <typename T, size_t BUF_SIZE>
    constexpr Byte SmallStackBuffer<T, BUF_SIZE>::kGuard2_[8];
#endif
    template <typename T, size_t BUF_SIZE>
    void SmallStackBuffer<T, BUF_SIZE>::ValidateGuards_ () const
    {
        Assert (::memcmp (kGuard1_, fGuard1_, sizeof (kGuard1_)) == 0);
        Assert (::memcmp (kGuard2_, fGuard2_, sizeof (kGuard2_)) == 0);
    }
#endif
    template <typename T, size_t BUF_SIZE>
    inline T* SmallStackBuffer<T, BUF_SIZE>::BufferAsT_ () noexcept
    {
        return reinterpret_cast<T*> (&fInlinePreallocatedBuffer_[0]);
    }
    template <typename T, size_t BUF_SIZE>
    inline const T* SmallStackBuffer<T, BUF_SIZE>::BufferAsT_ () const noexcept
    {
        return reinterpret_cast<const T*> (&fInlinePreallocatedBuffer_[0]);
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::DestroyElts_ (T* start, T* end) noexcept
    {
        for (auto i = start; i != end; ++i) {
            i->~T ();
        }
    }
    template <typename T, size_t BUF_SIZE>
    inline Memory::Byte* SmallStackBuffer<T, BUF_SIZE>::LiveDataAsAllocatedBytes_ ()
    {
        Require (fLiveData_ != BufferAsT_ ());
        return reinterpret_cast<Memory::Byte*> (fLiveData_);
    }
    template <typename T, size_t BUF_SIZE>
    inline Memory::Byte* SmallStackBuffer<T, BUF_SIZE>::Allocate_ (size_t bytes)
    {
        void* p = ::malloc (bytes);
        Execution::ThrowIfNull (p);
        return reinterpret_cast<Memory::Byte*> (p);
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::Deallocate_ (Memory::Byte* bytes)
    {
        if (bytes != nullptr) {
            ::free (bytes);
        }
    }
}

#endif /*_Stroika_Foundation_Memory_SmallStackBuffer_inl_*/
<commit_msg>Cosmetic<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Memory_SmallStackBuffer_inl_
#define _Stroika_Foundation_Memory_SmallStackBuffer_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include <algorithm>
#include <cstring>
#include <type_traits>

#include "../Debug/Assertions.h"
#include "../Execution/Exceptions.h"
#include "Common.h"

namespace Stroika::Foundation::Memory {

    /*
     ********************************************************************************
     ************************* SmallStackBuffer<T, BUF_SIZE> ************************
     ********************************************************************************
     */
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer ()
        : fLiveData_ (BufferAsT_ ())
    {
#if qDebug
        ::memcpy (fGuard1_, kGuard1_, sizeof (kGuard1_));
        ::memcpy (fGuard2_, kGuard2_, sizeof (kGuard2_));
#endif
        Invariant ();
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer (size_t nElements)
        : SmallStackBuffer ()
    {
        resize (nElements);
        Invariant ();
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer (UninitializedConstructorFlag, size_t nElements)
        : SmallStackBuffer ()
    {
        static_assert (is_trivially_default_constructible_v<T>);
        resize_uninitialized (nElements);
        Invariant ();
    }
    template <typename T, size_t BUF_SIZE>
    template <typename ITERATOR_OF_T, enable_if_t<Configuration::is_iterator_v<ITERATOR_OF_T>, char>*>
    SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer (ITERATOR_OF_T start, ITERATOR_OF_T end)
        : SmallStackBuffer (distance (start, end))
    {
#if qCompilerAndStdLib_uninitialized_copy_n_Warning_Buggy
        Configuration::uninitialized_copy_MSFT_BWA (start, end, this->begin ());
#else
        uninitialized_copy (start, end, this->begin ());
#endif
        Invariant ();
    }
    template <typename T, size_t BUF_SIZE>
    template <size_t FROM_BUF_SIZE>
    SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer (const SmallStackBuffer<T, FROM_BUF_SIZE>& from)
        : SmallStackBuffer (from.begin (), from.end ())
    {
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::SmallStackBuffer (const SmallStackBuffer& from)
        : SmallStackBuffer (from.begin (), from.end ())
    {
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::~SmallStackBuffer ()
    {
        Invariant ();
        DestroyElts_ (this->begin (), this->end ());
        if (fLiveData_ != BufferAsT_ ()) {
            // we must have used the heap...
            Deallocate_ (LiveDataAsAllocatedBytes_ ());
        }
    }
    template <typename T, size_t BUF_SIZE>
    template <size_t FROM_BUF_SIZE>
    SmallStackBuffer<T, BUF_SIZE>& SmallStackBuffer<T, BUF_SIZE>::operator= (const SmallStackBuffer<T, FROM_BUF_SIZE>& rhs)
    {
        Invariant ();
        // @todo this simple implementation could be more efficient
        DestroyElts_ (this->begin (), this->end ());
        fSize_ = 0;
        ReserveAtLeast (rhs.size ());
#if qCompilerAndStdLib_uninitialized_copy_n_Warning_Buggy
        Configuration::uninitialized_copy_MSFT_BWA (rhs.begin (), rhs.end (), this->begin ());
#else
        uninitialized_copy (rhs.begin (), rhs.end (), this->begin ());
#endif
        Invariant ();
        return *this;
    }
    template <typename T, size_t BUF_SIZE>
    SmallStackBuffer<T, BUF_SIZE>& SmallStackBuffer<T, BUF_SIZE>::operator= (const SmallStackBuffer& rhs)
    {
        Invariant ();
        if (this != &rhs) {
            // @todo this simple implementation could be more efficient
            DestroyElts_ (this->begin (), this->end ());
            fSize_ = 0;
            ReserveAtLeast (rhs.size ());
#if qCompilerAndStdLib_uninitialized_copy_n_Warning_Buggy
            Configuration::uninitialized_copy_MSFT_BWA (rhs.begin (), rhs.end (), this->begin ());
#else
            uninitialized_copy (rhs.begin (), rhs.end (), this->begin ());
#endif
            Invariant ();
        }
        return *this;
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::GrowToSize (size_t nElements)
    {
        if (nElements > size ()) {
            resize (nElements);
        }
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::GrowToSize_uninitialized (size_t nElements)
    {
        static_assert (is_trivially_default_constructible_v<T>);
        if (nElements > size ()) {
            resize_uninitialized (nElements);
        }
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::resize (size_t nElements)
    {
        if (nElements > fSize_) {
            // Growing
            if (nElements > capacity ()) {
                /*
                 *   If we REALLY must grow, the double in size so unlikely we'll have to grow/malloc/copy again.
                 */
                reserve (max (nElements, capacity () * 2));
            }
            uninitialized_fill (this->begin () + fSize_, this->begin () + nElements, T{});
            fSize_ = nElements;
        }
        else if (nElements < fSize_) {
            // Shrinking
            DestroyElts_ (this->begin () + nElements, this->end ());
            fSize_ = nElements;
        }
        Assert (fSize_ == nElements);
        Ensure (size () <= capacity ());
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::resize_uninitialized (size_t nElements)
    {
        static_assert (is_trivially_default_constructible_v<T>);
        if (nElements > fSize_) {
            // Growing
            if (nElements > capacity ())
                [[UNLIKELY_ATTR]]
                {
                    /*
                     *   If we REALLY must grow, the double in size so unlikely we'll have to grow/malloc/copy again.
                     */
                    reserve (max (nElements, capacity () * 2));
                }
            fSize_ = nElements;
        }
        else if (nElements < fSize_) {
            // Shrinking
            DestroyElts_ (this->begin () + nElements, this->end ());
            fSize_ = nElements;
        }
        Assert (fSize_ == nElements);
        Ensure (size () <= capacity ());
    }
    template <typename T, size_t BUF_SIZE>
    void SmallStackBuffer<T, BUF_SIZE>::reserve_ (size_t nElements)
    {
        Assert (nElements >= size ());
        Invariant ();
        size_t oldEltCount = capacity ();
        if (nElements != oldEltCount) {
            bool oldInPlaceBuffer = oldEltCount <= BUF_SIZE;
            bool newInPlaceBuffer = nElements <= BUF_SIZE;
            // Only if we changed if using inplace buffer, or if was and is using ramBuffer, and eltCount changed do we need to do anything
            if (oldInPlaceBuffer != newInPlaceBuffer or (not newInPlaceBuffer)) {
                bool          memoryAllocationNeeded = not newInPlaceBuffer;
                Memory::Byte* newPtr                 = memoryAllocationNeeded ? Allocate_ (SizeInBytes_ (nElements)) : std::begin (fInlinePreallocatedBuffer_);

                // Initialize new memory from old
                Assert (this->begin () != reinterpret_cast<T*> (newPtr));
#if qCompilerAndStdLib_uninitialized_copy_n_Warning_Buggy
                Configuration::uninitialized_copy_MSFT_BWA (this->begin (), this->end (), reinterpret_cast<T*> (newPtr));
#else
                uninitialized_copy (this->begin (), this->end (), reinterpret_cast<T*> (newPtr));
#endif

                // destroy objects in old memory
                DestroyElts_ (this->begin (), this->end ());

                // free old memory if needed
                if (not oldInPlaceBuffer) {
                    Assert (fLiveData_ != BufferAsT_ ());
                    Deallocate_ (LiveDataAsAllocatedBytes_ ());
                }

                fLiveData_ = reinterpret_cast<T*> (newPtr);
                if (not newInPlaceBuffer) {
                    fCapacityOfFreeStoreAllocation_ = nElements;
                }
            }
        }
        Ensure ((nElements <= BUF_SIZE && capacity () == BUF_SIZE) or (nElements > BUF_SIZE and nElements == capacity ()));
        Invariant ();
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::iterator SmallStackBuffer<T, BUF_SIZE>::begin ()
    {
        return fLiveData_;
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::iterator SmallStackBuffer<T, BUF_SIZE>::end ()
    {
        return fLiveData_ + fSize_;
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::const_iterator SmallStackBuffer<T, BUF_SIZE>::begin () const
    {
        return fLiveData_;
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::const_iterator SmallStackBuffer<T, BUF_SIZE>::end () const
    {
        return fLiveData_ + fSize_;
    }
    template <typename T, size_t BUF_SIZE>
    inline size_t SmallStackBuffer<T, BUF_SIZE>::capacity () const
    {
        return (fLiveData_ == BufferAsT_ ()) ? BUF_SIZE : fCapacityOfFreeStoreAllocation_; // @see class Design Note
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::reserve (size_t newCapacity)
    {
        Require (newCapacity >= size ());
        reserve_ (newCapacity);
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::ReserveAtLeast (size_t newCapacity)
    {
        if (newCapacity > capacity ()) {
            reserve_ (newCapacity);
        }
    }
    template <typename T, size_t BUF_SIZE>
    inline size_t SmallStackBuffer<T, BUF_SIZE>::GetSize () const
    {
        Ensure (fSize_ <= capacity ());
        return fSize_;
    }
    template <typename T, size_t BUF_SIZE>
    inline size_t SmallStackBuffer<T, BUF_SIZE>::size () const
    {
        Ensure (fSize_ <= capacity ());
        return fSize_;
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::reference SmallStackBuffer<T, BUF_SIZE>::at (size_t i)
    {
        Require (i < fSize_);
        return *(fLiveData_ + i);
    }
    template <typename T, size_t BUF_SIZE>
    inline typename SmallStackBuffer<T, BUF_SIZE>::const_reference SmallStackBuffer<T, BUF_SIZE>::at (size_t i) const
    {
        Require (i < fSize_);
        return *(fLiveData_ + i);
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::push_back (Configuration::ArgByValueType<T> e)
    {
        size_t s = size ();
        if (s < capacity ()) {
#if qCompilerAndStdLib_uninitialized_copy_n_Warning_Buggy
            Configuration::uninitialized_copy_MSFT_BWA (&e, &e + 1, this->end ());
#else
            uninitialized_copy (&e, &e + 1, this->end ());
#endif
            this->fSize_++;
        }
        else {
            if constexpr (is_trivially_default_constructible_v<T>) {
                resize_uninitialized (s + 1);
            }
            else {
                resize (s + 1);
            }
            fLiveData_[s] = e;
        }
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::operator T* ()
    {
        AssertNotNull (fLiveData_);
        return fLiveData_;
    }
    template <typename T, size_t BUF_SIZE>
    inline SmallStackBuffer<T, BUF_SIZE>::operator const T* () const
    {
        AssertNotNull (fLiveData_);
        return fLiveData_;
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::Invariant () const
    {
#if qDebug
        Invariant_ ();
#endif
    }
#if qDebug
    template <typename T, size_t BUF_SIZE>
    void SmallStackBuffer<T, BUF_SIZE>::Invariant_ () const
    {
        Assert (capacity () >= size ());
        ValidateGuards_ ();
    }
#if qCompiler_cpp17InlineStaticMemberOfTemplateLinkerUndefined_Buggy
    template <typename T, size_t BUF_SIZE>
    constexpr Byte SmallStackBuffer<T, BUF_SIZE>::kGuard1_[8];
    template <typename T, size_t BUF_SIZE>
    constexpr Byte SmallStackBuffer<T, BUF_SIZE>::kGuard2_[8];
#endif
    template <typename T, size_t BUF_SIZE>
    void SmallStackBuffer<T, BUF_SIZE>::ValidateGuards_ () const
    {
        Assert (::memcmp (kGuard1_, fGuard1_, sizeof (kGuard1_)) == 0);
        Assert (::memcmp (kGuard2_, fGuard2_, sizeof (kGuard2_)) == 0);
    }
#endif
    template <typename T, size_t BUF_SIZE>
    inline T* SmallStackBuffer<T, BUF_SIZE>::BufferAsT_ () noexcept
    {
        return reinterpret_cast<T*> (&fInlinePreallocatedBuffer_[0]);
    }
    template <typename T, size_t BUF_SIZE>
    inline const T* SmallStackBuffer<T, BUF_SIZE>::BufferAsT_ () const noexcept
    {
        return reinterpret_cast<const T*> (&fInlinePreallocatedBuffer_[0]);
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::DestroyElts_ (T* start, T* end) noexcept
    {
        for (auto i = start; i != end; ++i) {
            i->~T ();
        }
    }
    template <typename T, size_t BUF_SIZE>
    inline Memory::Byte* SmallStackBuffer<T, BUF_SIZE>::LiveDataAsAllocatedBytes_ ()
    {
        Require (fLiveData_ != BufferAsT_ ());
        return reinterpret_cast<Memory::Byte*> (fLiveData_);
    }
    template <typename T, size_t BUF_SIZE>
    inline Memory::Byte* SmallStackBuffer<T, BUF_SIZE>::Allocate_ (size_t bytes)
    {
        void* p = ::malloc (bytes);
        Execution::ThrowIfNull (p);
        return reinterpret_cast<Memory::Byte*> (p);
    }
    template <typename T, size_t BUF_SIZE>
    inline void SmallStackBuffer<T, BUF_SIZE>::Deallocate_ (Memory::Byte* bytes)
    {
        if (bytes != nullptr) {
            ::free (bytes);
        }
    }
}

#endif /*_Stroika_Foundation_Memory_SmallStackBuffer_inl_*/
<|endoftext|>


<commit_before>#include "balance.h"

int count = 0;

BalanceState::BalanceState(Adafruit_BNO055* imu)
    : imu(imu),
      drive(&leftServo, &rightServo),
      pid(&pidInput, &pidOutput, &pidTarget, 10, 1, 1, DIRECT) {}

void BalanceState::enter() {
  Serial.println(F("\n\nEntering: Robot Balance State"));

  if (!readConfig(cd)) {
    Serial.println(F("ERROR: Config Not found"));
    stateGoto(NULL);
    return;
  }

  drive.setServoConfig(cd.lconfig, cd.rconfig);
  leftServo.attach(servoLeftPin);
  rightServo.attach(servoRightPin);

  pid.SetTunings(cd.Kp, cd.Ki, cd.Kd);
  pid.SetOutputLimits(-1.0, 1.0);
  pid.SetSampleTime(10);
  drive.drive(0);
  pid.SetMode(AUTOMATIC);
  pidTarget = 0;
}

void BalanceState::action() {
  sensors_event_t event;
  imu->getEvent(&event);

  pidInput = event.orientation.y / 90.0;
  pid.Compute();

  if (event.orientation.y < 10.0 && event.orientation.y > -10.0)
    drive.drive(1000 * pidOutput);
  else
    drive.drive(0);

  delay(5);
  int ch = Serial.read();
  if (ch == 'q') {
    stateGoto(NULL);
  }

  switch (ch) {
    case 'p':
      cd.Kp += 0.1;
      break;
    case 'P':
      cd.Kp -= 0.1;
      break;

    case 'i':
      cd.Ki += 0.1;
      break;
    case 'I':
      cd.Ki -= 0.1;
      break;

    case 'd':
      cd.Kd += 0.1;
      break;
    case 'D':
      cd.Kd -= 0.1;
      break;

    case 'w':
      pidTarget += 0.01;
      break;
    case 's':
      pidTarget -= 0.01;
      break;
  }

  pid.SetTunings(cd.Kp, cd.Ki, cd.Kd);

  if (count == 100) {
    Serial.print("Y: ");
    Serial.print(event.orientation.y, 2);

    Serial.print("\tKp: ");
    Serial.print(cd.Kp, 2);
    Serial.print("\tKi: ");
    Serial.print(cd.Ki, 2);
    Serial.print("\tKd: ");
    Serial.print(cd.Kd, 2);
    Serial.println("");
    count = 0;
  }

  count++;
}

void BalanceState::leave() {
  leftServo.detach();
  rightServo.detach();

  writeConfig(cd);
}
<commit_msg>suspend pid calculation if angle is exceeded<commit_after>#include "balance.h"

int count = 0;

BalanceState::BalanceState(Adafruit_BNO055* imu)
    : imu(imu),
      drive(&leftServo, &rightServo),
      pid(&pidInput, &pidOutput, &pidTarget, 10, 1, 1, DIRECT) {}

void BalanceState::enter() {
  Serial.println(F("\n\nEntering: Robot Balance State"));

  if (!readConfig(cd)) {
    Serial.println(F("ERROR: Config Not found"));
    stateGoto(NULL);
    return;
  }

  drive.setServoConfig(cd.lconfig, cd.rconfig);
  leftServo.attach(servoLeftPin);
  rightServo.attach(servoRightPin);

  pid.SetTunings(cd.Kp, cd.Ki, cd.Kd);
  pid.SetOutputLimits(-1.0, 1.0);
  pid.SetSampleTime(10);
  drive.drive(0);
  pid.SetMode(AUTOMATIC);
  pidTarget = 0;
}

void BalanceState::action() {
  sensors_event_t event;
  imu->getEvent(&event);

  if (event.orientation.y < 10.0 && event.orientation.y > -10.0) {
    pidInput = event.orientation.y / 90.0;
    pid.Compute();

    drive.drive(1000 * pidOutput);
  } else {
    drive.drive(0);
  }

  delay(5);
  int ch = Serial.read();
  if (ch == 'q') {
    stateGoto(NULL);
  }

  switch (ch) {
    case 'p':
      cd.Kp += 0.1;
      break;
    case 'P':
      cd.Kp -= 0.1;
      break;

    case 'i':
      cd.Ki += 0.1;
      break;
    case 'I':
      cd.Ki -= 0.1;
      break;

    case 'd':
      cd.Kd += 0.1;
      break;
    case 'D':
      cd.Kd -= 0.1;
      break;

    case 'w':
      pidTarget += 0.01;
      break;
    case 's':
      pidTarget -= 0.01;
      break;
  }

  pid.SetTunings(cd.Kp, cd.Ki, cd.Kd);

  if (count == 100) {
    Serial.print("Y: ");
    Serial.print(event.orientation.y, 2);

    Serial.print("\tKp: ");
    Serial.print(cd.Kp, 2);
    Serial.print("\tKi: ");
    Serial.print(cd.Ki, 2);
    Serial.print("\tKd: ");
    Serial.print(cd.Kd, 2);
    Serial.println("");
    count = 0;
  }

  count++;
}

void BalanceState::leave() {
  leftServo.detach();
  rightServo.detach();

  writeConfig(cd);
}
<|endoftext|>