<commit_before>// Gavin Kyte
// Thu Nov  2 16:08:49 2017

#include <iostream>
#include <iomanip>
using namespace std;

template <class T> class ComparisonTree {
public:
  struct Node {
    Node* parent;
    Node* left;
    Node* right;
    T value;
    int height;
    static const int numTypes = 2;
    int typeCounter[2];

    Node(T value, Node* parent) {
      this->value = value;
      this->parent = parent;
      left = nullptr;
      right = nullptr;
      height = 0;
      typeCounter[0] = 0;
      typeCounter[1] = 0;
    }
  };
  Node* root;
  int size;
  ComparisonTree() {
    root = nullptr;
    size = 0;
  }

  // Takes value and type number for future comparison
  void insert(T value, int type) {
    if(!root) {
      root = new Node(value, nullptr);
    }
    Node* nomad = root;
    while(1) {
      if(value < nomad->value && nomad->left){
        nomad = nomad->left;
      } else if(value < nomad->value && !nomad->left){
        nomad->left = new Node(value, nomad);
      } else if(value > nomad->value && nomad->right){
        nomad = nomad->right;
      } else if(value > nomad->value && !nomad->right){
        nomad->right = new Node(value, nomad);
      } else if(value == nomad->value) { // Always last case
        nomad->typeCounter[type]++;
        break;
      }
    }
    while(nomad->parent) {
      nomad->height++;
      Node* sibling = nomad->sibling();
      // balance calculated after nomad height is increased,
      // and the initial difference can't be more than 1,
      // thus the nomad is always +0, +1, or +2 relative to sibling
      int balance = diff(nomad, sibling);
      if(balance == 0) { // No change in parent's height factor
        break;
      } else if(balance == 1) { // Change parent's height
        nomad = nomad->parent;
      } else { // balance == 2
        rotate(nomad->parent);
        break;
      }
    }
    size++;
  }

  /**
   * Help method to calculate absolute value of height difference
   * requires child to be non-null Node ptr, but sibling can be null
   * returns +value which is likely 0, 1, or 2 if used correctly.
   */
  int diff(Node* child, Node* sibling) {
    int cHeight = child->height;
    int sHeight = 0;
    if(sibling) {
      sHeight = sibling->height;
    }
    int difference = cHeight - sHeight;
    if(difference < 0) { // Is this ever going to happen?
      difference = -1 * difference;
    }
    return difference;
  }

  void rotate(Node* parent) {
    // Determine rotation type
    int lHeight = parent->left->height;
    int rHeight = parent->right->height;
    Node* child;
    if(parent->left->height > parent->right->height) {
      child = parent->left;
      if(child->left->height > child->right->height)
        llRotation(parent);
      else
        lrRotation(parent);
    } else {
      child = parent->right;
      if(child->left->height > child->right->height)
        rlRotation(parent);
      else
        rrRotation(parent);
    }
  }

  void llRotation(Node* parent) {
    Node* tmp = parent->left;
    tmp->parent = parent->parent;
    parent->left = tmp->right;
    tmp->right = parent;
    parent->height--;
  }
  void lrRotation(Node* parent) {

  }
  void rlRotation(Node* parent) {

  }
  void rrRotation(Node* parent) {
    Node* tmp = parent->right;
    tmp->parent = parent->parent;
    parent->right = tmp->left;
    tmp->left = parent;
    parent->height--;
  }

  /**
   * Display tree
   */
  void display(Node *ptr, int level) {
    int i;
    if(ptr!=NULL) {
      display(ptr->right, level + 1);
      printf("\n");
      if (ptr == root)
      cout<<"Root -> ";
      for (i = 0; i < level && ptr != root; i++)
      cout<<"        ";
      cout<<ptr->value<<"("<<ptr->typeCounter[0]<<","<<ptr->typeCounter[1]<<")";
      display(ptr->left, level + 1);
    }
  }

  void showANotB(Node* parent) {
    if(!parent)
      return;
    if(parent->left) showANotB(parent->left);
    for (int count = parent->typeCounter[0] - parent->typeCounter[1]; count > 0; count--) {
      cout<<parent->value<<endl;
    }
    if(parent->right) showANotB(parent->right);
  }
  void showBNotA(Node* parent) {
    if(!parent)
      return;
    if(parent->left) showBNotA(parent->left);
    for (int count = parent->typeCounter[1] - parent->typeCounter[0]; count > 0; count--) {
      cout<<parent->value<<endl;
    }
    if(parent->right) showBNotA(parent->right);
  }
  void showAAndB(Node* parent) {
    if(!parent)
      return;
    if(parent->left) showAAndB(parent->left);
    for (int count = 0; count < parent->typeCounter[0] && count < parent->typeCounter[1]; count++) {
      cout<<parent->value<<endl;
    }
    if(parent->right) showAAndB(parent->right);
  }
};
<commit_msg>Fill in code for AVL rotations and Height tracking<commit_after>// Gavin Kyte
// Thu Nov  2 16:08:49 2017

#include <iostream>
#include <iomanip>
using namespace std;

template <class T> class AVLComparisonTree {
public:
  struct Node {
    Node* parent;
    Node* left;
    Node* right;
    T value;
    int height;
    static const int numTypes = 2;
    int typeCounter[2];

    Node* sibling() {
      Node* sib = nullptr;
      if(this->parent) {
        if(this->parent->value < this->value) {
          sib = this->parent->right;
        } else {
          sib = this->parent->left;
        }
      }
      return sib;
    }
    Node(T value, Node* parent) {
      this->value = value;
      this->parent = parent;
      left = nullptr;
      right = nullptr;
      height = 0;
      typeCounter[0] = 0;
      typeCounter[1] = 0;
    }
  };
  Node* root;
  int size;
  AVLComparisonTree() {
    root = nullptr;
    size = 0;
  }

  // Takes value and type number for future comparison
  void insert(T value, int type) {
    if(!root) {
      root = new Node(value, nullptr);
    }
    Node* nomad = root;
    while(1) {
      if(value < nomad->value && nomad->left){
        nomad = nomad->left;
      } else if(value < nomad->value && !nomad->left){
        nomad->left = new Node(value, nomad);
      } else if(value > nomad->value && nomad->right){
        nomad = nomad->right;
      } else if(value > nomad->value && !nomad->right){
        nomad->right = new Node(value, nomad);
      } else if(value == nomad->value) { // Always last case
        nomad->typeCounter[type]++;
        break;
      }
    }
    while(nomad->parent) {
      nomad->height++;
      Node* sibling = nomad->sibling();
      // balance calculated after nomad height is increased,
      // and the initial difference can't be more than 1,
      // thus the nomad is always +0, +1, or +2 relative to sibling
      int balance = diff(nomad, sibling);
      if(balance == 0) { // No change in parent's height factor
        break;
      } else if(balance == 1) { // Change parent's height
        nomad = nomad->parent;
      } else { // balance == 2
        rotate(nomad->parent);
      }
    }
    size++;
  }

  /**
   * Help method to calculate absolute value of height difference
   * requires child to be non-null Node ptr, but sibling can be null
   * returns +value which is likely 0, 1, or 2 if used correctly.
   */
  int diff(Node* child, Node* sibling) {
    int cHeight = child->height;
    int sHeight = 0;
    if(sibling) {
      sHeight = sibling->height;
    }
    int difference = cHeight - sHeight;
    if(difference < 0) { // Is this ever going to happen?
      difference = -1 * difference;
    }
    return difference;
  }

  void rotate(Node* parent) {
    // Determine rotation type
    Node* child;
    if(parent->left->height > parent->right->height) {
      child = parent->left;
      if(child->left->height > child->right->height)
        llRotation(parent);
      else
        lrRotation(parent);
    } else {
      child = parent->right;
      if(child->left->height > child->right->height)
        rlRotation(parent);
      else
        rrRotation(parent);
    }
  }

  void llRotation(Node* parent) {
    Node* tmp = parent->left;
    tmp->parent = parent->parent;
    parent->parent = tmp;
    parent->left = tmp->right;
    tmp->right = parent;
    if(tmp->value < tmp->parent->value) {
      tmp->parent->left = tmp;
    } else {
      tmp->parent->right = tmp;
    }
    parent->height--;
  }
  void lrRotation(Node* parent) {
    rrRotation(parent->left);
    llRotation(parent);
  }
  void rlRotation(Node* parent) {
    llRotation(parent->right);
    rrRotation(parent);
  }
  void rrRotation(Node* parent) {
    Node* tmp = parent->right;
    tmp->parent = parent->parent;
    parent->parent = tmp;
    parent->right = tmp->left;
    tmp->left = parent;
    if(tmp->value < tmp->parent->value) {
      tmp->parent->left = tmp;
    } else {
      tmp->parent->right = tmp;
    }
    parent->height--;
  }

  /**
   * Display tree
   */
  void display(Node *ptr, int level) {
    int i;
    if(ptr!=NULL) {
      display(ptr->right, level + 1);
      printf("\n");
      if (ptr == root)
      cout<<"Root -> ";
      for (i = 0; i < level && ptr != root; i++)
      cout<<"        ";
      cout<<ptr->value<<"("<<ptr->typeCounter[0]<<","<<ptr->typeCounter[1]<<")-h:"<<ptr->height;
      display(ptr->left, level + 1);
    }
  }

  void showANotB(Node* parent) {
    if(!parent)
      return;
    if(parent->left) showANotB(parent->left);
    for (int count = parent->typeCounter[0] - parent->typeCounter[1]; count > 0; count--) {
      cout<<parent->value<<endl;
    }
    if(parent->right) showANotB(parent->right);
  }
  void showBNotA(Node* parent) {
    if(!parent)
      return;
    if(parent->left) showBNotA(parent->left);
    for (int count = parent->typeCounter[1] - parent->typeCounter[0]; count > 0; count--) {
      cout<<parent->value<<endl;
    }
    if(parent->right) showBNotA(parent->right);
  }
  void showAAndB(Node* parent) {
    if(!parent)
      return;
    if(parent->left) showAAndB(parent->left);
    for (int count = 0; count < parent->typeCounter[0] && count < parent->typeCounter[1]; count++) {
      cout<<parent->value<<endl;
    }
    if(parent->right) showAAndB(parent->right);
  }
};
<|endoftext|>


<commit_before>/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include "gm.h"
#include "SkBlurMask.h"
#include "SkBlurMaskFilter.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkLayerDrawLooper.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkPoint.h"
#include "SkRect.h"
#include "SkRRect.h"
#include "SkString.h"
#include "SkXfermode.h"

// This GM mimics a blurred RR seen in the wild.
class BlurRoundRectGM : public skiagm::GM {
public:
    BlurRoundRectGM(int width, int height, int radius)
        : fName("blurroundrect")
    {
        SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
        fRRect.setRectXY(r, SkIntToScalar(radius), SkIntToScalar(radius));
        fName.appendf("-WH[%ix%i]-corner[%i]", width, height, radius);
    }

    BlurRoundRectGM(int width, int height)
        : fName("blurroundrect") {
        fName.appendf("-WH[%ix%i]-unevenCorners",
                      width,  height);
        SkVector radii[4];
        radii[0].set(SkIntToScalar(30), SkIntToScalar(30));
        radii[1].set(SkIntToScalar(10), SkIntToScalar(10));
        radii[2].set(SkIntToScalar(30), SkIntToScalar(30));
        radii[3].set(SkIntToScalar(10), SkIntToScalar(10));
        SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
        fRRect.setRectRadii(r, radii);
    }

    virtual uint32_t onGetFlags() const SK_OVERRIDE {
        return kSkipTiled_Flag;
    }

    virtual SkString onShortName() SK_OVERRIDE {
        return fName;
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(SkScalarCeilToInt(fRRect.rect().width()),
                             SkScalarCeilToInt(fRRect.rect().height()));
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkLayerDrawLooper::Builder looperBuilder;
        {
            SkLayerDrawLooper::LayerInfo info;
            info.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit
                              | SkLayerDrawLooper::kColorFilter_Bit;
            info.fColorMode = SkXfermode::kSrc_Mode;
            info.fOffset = SkPoint::Make(SkIntToScalar(-1), SkIntToScalar(0));
            info.fPostTranslate = false;
            SkPaint* paint = looperBuilder.addLayerOnTop(info);
            SkMaskFilter* maskFilter = SkBlurMaskFilter::Create(
                    kNormal_SkBlurStyle,
                    SkBlurMask::ConvertRadiusToSigma(SK_ScalarHalf),
                    SkBlurMaskFilter::kHighQuality_BlurFlag);
            paint->setMaskFilter(maskFilter)->unref();
            SkColorFilter* colorFilter = SkColorFilter::CreateModeFilter(SK_ColorLTGRAY,
                    SkXfermode::kSrcIn_Mode);
            paint->setColorFilter(colorFilter)->unref();
            paint->setColor(SK_ColorGRAY);
        }
        {
            SkLayerDrawLooper::LayerInfo info;
            looperBuilder.addLayerOnTop(info);
        }
        SkPaint paint;
        canvas->drawRect(fRRect.rect(), paint);

        paint.setLooper(looperBuilder.detachLooper())->unref();
        paint.setColor(SK_ColorCYAN);
        paint.setAntiAlias(true);

        canvas->drawRRect(fRRect, paint);
    }

private:
    SkString        fName;
    SkRRect         fRRect;

    typedef skiagm::GM INHERITED;
};

// Simpler blurred RR test cases where all the radii are the same.
class SimpleBlurRoundRectGM : public skiagm::GM {
public:
    SimpleBlurRoundRectGM()
        : fName("simpleblurroundrect") {
    }

protected:
    virtual uint32_t onGetFlags() const SK_OVERRIDE {
        return kSkipTiled_Flag;
    }

    virtual SkString onShortName() SK_OVERRIDE {
        return fName;
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(950, 950);
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        canvas->scale(1.5f, 1.5f);
        canvas->translate(50,50);

        const float blurRadii[] = { 1,5,10,20 };
        const int cornerRadii[] = { 1,5,10,20 };
        const SkRect r = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
        for (size_t i = 0; i < SK_ARRAY_COUNT(blurRadii); ++i) {
            SkAutoCanvasRestore autoRestore(canvas, true);
            canvas->translate(0, (r.height() + SkIntToScalar(50)) * i);
            for (size_t j = 0; j < SK_ARRAY_COUNT(cornerRadii); ++j) {
                SkMaskFilter* filter = SkBlurMaskFilter::Create(
                    kNormal_SkBlurStyle,
                    SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(blurRadii[i])),
                    SkBlurMaskFilter::kHighQuality_BlurFlag);
                SkPaint paint;
                paint.setColor(SK_ColorBLACK);
                paint.setMaskFilter(filter)->unref();

                SkRRect rrect;
                rrect.setRectXY(r, SkIntToScalar(cornerRadii[j]), SkIntToScalar(cornerRadii[j]));
                canvas->drawRRect(rrect, paint);
                canvas->translate(r.width() + SkIntToScalar(50), 0);
            }
        }
    }
private:
    const SkString  fName;

    typedef         skiagm::GM INHERITED;
};

// Create one with dimensions/rounded corners based on the skp
//
// TODO(scroggo): Disabled in an attempt to rememdy
// https://code.google.com/p/skia/issues/detail?id=1801 ('Win7 Test bots all failing GenerateGMs:
// ran wrong number of tests')
//DEF_GM(return new BlurRoundRectGM(600, 5514, 6);)

// Rounded rect with two opposite corners with large radii, the other two
// small.
DEF_GM(return new BlurRoundRectGM(100, 100);)

DEF_GM(return new SimpleBlurRoundRectGM();)
<commit_msg>Remove brackets from gm names.<commit_after>/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include "gm.h"
#include "SkBlurMask.h"
#include "SkBlurMaskFilter.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkLayerDrawLooper.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkPoint.h"
#include "SkRect.h"
#include "SkRRect.h"
#include "SkString.h"
#include "SkXfermode.h"

// This GM mimics a blurred RR seen in the wild.
class BlurRoundRectGM : public skiagm::GM {
public:
    BlurRoundRectGM(int width, int height, int radius)
        : fName("blurroundrect")
    {
        SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
        fRRect.setRectXY(r, SkIntToScalar(radius), SkIntToScalar(radius));
        fName.appendf("-WH-%ix%i-corner-%i", width, height, radius);
    }

    BlurRoundRectGM(int width, int height)
        : fName("blurroundrect") {
        fName.appendf("-WH-%ix%i-unevenCorners", width,  height);
        SkVector radii[4];
        radii[0].set(SkIntToScalar(30), SkIntToScalar(30));
        radii[1].set(SkIntToScalar(10), SkIntToScalar(10));
        radii[2].set(SkIntToScalar(30), SkIntToScalar(30));
        radii[3].set(SkIntToScalar(10), SkIntToScalar(10));
        SkRect r = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
        fRRect.setRectRadii(r, radii);
    }

    virtual uint32_t onGetFlags() const SK_OVERRIDE {
        return kSkipTiled_Flag;
    }

    virtual SkString onShortName() SK_OVERRIDE {
        return fName;
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(SkScalarCeilToInt(fRRect.rect().width()),
                             SkScalarCeilToInt(fRRect.rect().height()));
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        SkLayerDrawLooper::Builder looperBuilder;
        {
            SkLayerDrawLooper::LayerInfo info;
            info.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit
                              | SkLayerDrawLooper::kColorFilter_Bit;
            info.fColorMode = SkXfermode::kSrc_Mode;
            info.fOffset = SkPoint::Make(SkIntToScalar(-1), SkIntToScalar(0));
            info.fPostTranslate = false;
            SkPaint* paint = looperBuilder.addLayerOnTop(info);
            SkMaskFilter* maskFilter = SkBlurMaskFilter::Create(
                    kNormal_SkBlurStyle,
                    SkBlurMask::ConvertRadiusToSigma(SK_ScalarHalf),
                    SkBlurMaskFilter::kHighQuality_BlurFlag);
            paint->setMaskFilter(maskFilter)->unref();
            SkColorFilter* colorFilter = SkColorFilter::CreateModeFilter(SK_ColorLTGRAY,
                    SkXfermode::kSrcIn_Mode);
            paint->setColorFilter(colorFilter)->unref();
            paint->setColor(SK_ColorGRAY);
        }
        {
            SkLayerDrawLooper::LayerInfo info;
            looperBuilder.addLayerOnTop(info);
        }
        SkPaint paint;
        canvas->drawRect(fRRect.rect(), paint);

        paint.setLooper(looperBuilder.detachLooper())->unref();
        paint.setColor(SK_ColorCYAN);
        paint.setAntiAlias(true);

        canvas->drawRRect(fRRect, paint);
    }

private:
    SkString        fName;
    SkRRect         fRRect;

    typedef skiagm::GM INHERITED;
};

// Simpler blurred RR test cases where all the radii are the same.
class SimpleBlurRoundRectGM : public skiagm::GM {
public:
    SimpleBlurRoundRectGM()
        : fName("simpleblurroundrect") {
    }

protected:
    virtual uint32_t onGetFlags() const SK_OVERRIDE {
        return kSkipTiled_Flag;
    }

    virtual SkString onShortName() SK_OVERRIDE {
        return fName;
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(950, 950);
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        canvas->scale(1.5f, 1.5f);
        canvas->translate(50,50);

        const float blurRadii[] = { 1,5,10,20 };
        const int cornerRadii[] = { 1,5,10,20 };
        const SkRect r = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
        for (size_t i = 0; i < SK_ARRAY_COUNT(blurRadii); ++i) {
            SkAutoCanvasRestore autoRestore(canvas, true);
            canvas->translate(0, (r.height() + SkIntToScalar(50)) * i);
            for (size_t j = 0; j < SK_ARRAY_COUNT(cornerRadii); ++j) {
                SkMaskFilter* filter = SkBlurMaskFilter::Create(
                    kNormal_SkBlurStyle,
                    SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(blurRadii[i])),
                    SkBlurMaskFilter::kHighQuality_BlurFlag);
                SkPaint paint;
                paint.setColor(SK_ColorBLACK);
                paint.setMaskFilter(filter)->unref();

                SkRRect rrect;
                rrect.setRectXY(r, SkIntToScalar(cornerRadii[j]), SkIntToScalar(cornerRadii[j]));
                canvas->drawRRect(rrect, paint);
                canvas->translate(r.width() + SkIntToScalar(50), 0);
            }
        }
    }
private:
    const SkString  fName;

    typedef         skiagm::GM INHERITED;
};

// Create one with dimensions/rounded corners based on the skp
//
// TODO(scroggo): Disabled in an attempt to rememdy
// https://code.google.com/p/skia/issues/detail?id=1801 ('Win7 Test bots all failing GenerateGMs:
// ran wrong number of tests')
//DEF_GM(return new BlurRoundRectGM(600, 5514, 6);)

// Rounded rect with two opposite corners with large radii, the other two
// small.
DEF_GM(return new BlurRoundRectGM(100, 100);)

DEF_GM(return new SimpleBlurRoundRectGM();)
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	ファイル・入出力クラス @n
			※ fopen 系の機能を提供するクラス。@n
			※ FATFS が必要
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#ifndef FAT_FS
#  error "file_io.hpp requires FAT_FS to be defined and include FATFS module"
#endif

#include "ff12b/src/diskio.h"
#include "ff12b/src/ff.h"

extern "C" {
	int make_full_path(const char* src, char* dst, uint16_t dsz);
	void utf8_to_sjis(const char* src, char* dst, uint32_t dsz);
};

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	ファイル入出力クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class file_io {
	public:

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        /*!
            @brief  SEEK タイプ
        */
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        enum class SEEK {
			SET,	///< 先頭からのオフセット
			CUR,	///< 現在位置からのオフセット
			END		///< 終端からのオフセット
        };

	private:
		FIL			fp_;
		bool		open_;

	public:
		//-------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		*/
		//-------------------------------------------------------------//
		file_io() noexcept :
			fp_(),
			open_(false)
		{ }

		//-------------------------------------------------------------//
		/*!
			@brief	デストラクター
		*/
		//-------------------------------------------------------------//
		~file_io() { close(); }

		//-------------------------------------------------------------//
		/*!
			@brief	ファイルを開く
			@param[in]	filename	ファイル名
			@param[in]	mode		オープン・モード
			@return 成功なら「true」
		*/
		//-------------------------------------------------------------//
		bool open(const char* filename, const char* mode) noexcept
		{
			if(filename == nullptr || mode == nullptr) return false;

			BYTE mdf = 0;
			if(strchr(mode, 'r') != nullptr) {
				mdf = FA_READ | FA_OPEN_EXISTING;
			}
			if(strchr(mode, 'w') != nullptr) {
				mdf = FA_WRITE;
				mdf |= FA_CREATE_NEW;
//				if(flags & O_TRUNC) mode |= FA_CREATE_ALWAYS;
			}
//			else if(rwm == O_RDWR) mode = FA_READ | FA_WRITE;
			if(strchr(mode, 'a') != nullptr) {
				mdf |= FA_OPEN_APPEND;
			}

			char tmp[_MAX_LFN + 1];
			if(!make_full_path(filename, tmp, sizeof(tmp))) {
				return false;
			}

			utf8_to_sjis(tmp, tmp, sizeof(tmp));
			FRESULT res = f_open(&fp_, tmp, mdf);
			if(res != FR_OK) {
				return false;
			}
			open_ = true;
			return true;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	ファイル・ディスクリプタへの参照
			@return ファイル・ディスクリプタ
		*/
		//-------------------------------------------------------------//
		FIL& at_fd() noexcept { return fp_; }

		//-------------------------------------------------------------//
		/*!
			@brief	オープンの確認
			@return オープンなら「true」
		*/
		//-------------------------------------------------------------//
		bool is_open() const noexcept { return open_; }

		//-------------------------------------------------------------//
		/*!
			@brief	ファイルをクローズする
			@return 成功なら「true」
		*/
		//-------------------------------------------------------------//
		bool close() noexcept
		{
			if(!open_) {
				return false;
			}
			open_ = false;
			return f_close(&fp_) == FR_OK;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	リード
			@param[out]	dst		読込先
			@param[in]	num		読み込みサイズ
			@return 読み込みサイズ
		*/
		//-------------------------------------------------------------//
		uint32_t read(void* dst, uint32_t len) noexcept
		{
			if(!open_) return 0;

			UINT rl = 0;
			FRESULT res = f_read(&fp_, dst, len, &rl);
			if(res != FR_OK) {
				return 0;
			}
			return rl;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	リード
			@param[out]	dst		読込先
			@param[in]	block	ブロックサイズ
			@param[in]	num		個数
			@return 読み込みサイズ
		*/
		//-------------------------------------------------------------//
		uint32_t read(void* dst, uint32_t block, uint32_t num) noexcept
		{
			return read(dst, block * num);
		}

		//-------------------------------------------------------------//
		/*!
			@brief	１文字取得
			@param[out]	ch	文字（参照）
			@return 正常なら「true」
		*/
		//-------------------------------------------------------------//
		bool get_char(char& ch) noexcept
		{
			char tmp[1];
			if(read(tmp, 1) != 1) {
				return false;
			}
			ch = tmp[0];
			return true;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	ライト
			@param[in]	src		ソース
			@param[in]	num		書き込みサイズ
			@return 書き込みサイズ
		*/
		//-------------------------------------------------------------//
		uint32_t write(const void* src, uint32_t len) noexcept
		{
			if(!open_) return 0;

			UINT wl = 0;
			FRESULT res = f_write(&fp_, src, len, &wl);
			if(res != FR_OK) {
				return 0;
			}
			return wl;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	シーク（fseek 準拠）
			@param[in]	seek	シーク形式
			@param[in]	ofs		オフセット
			@return 成功なら「true」
		*/
		//-------------------------------------------------------------//
		bool seek(SEEK seek, int32_t ofs) noexcept
		{
			if(!open_) return false;
			FRESULT ret;
			switch(seek) {
			case SEEK::SET:
				ret = f_lseek(&fp_, ofs);
				break;
			case SEEK::CUR:
				{
					int32_t pos = tell();
					pos += ofs;
					ret = f_lseek(&fp_, pos);
				}
				break;
			case SEEK::END:
				{
					int32_t pos = get_file_size();
					pos -= ofs;
					ret = f_lseek(&fp_, pos);
				}
				break;
			default:
				return false;
				break;
			}
			return ret == FR_OK;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	ファイル位置を返す
			@return ファイル位置
		*/
		//-------------------------------------------------------------//
		uint32_t tell() const noexcept
		{
			if(!open_) return false;
			return f_tell(&fp_);
		}

		//-------------------------------------------------------------//
		/*!
			@brief	ファイルの終端か検査
			@return ファイルの終端なら「true」
		*/
		//-------------------------------------------------------------//
		bool eof() const noexcept
		{
			if(!open_) return false;
			return f_eof(&fp_);
		}

		//-------------------------------------------------------------//
		/*!
			@brief	ファイルサイズを返す
			@return ファイルサイズ
		*/
		//-------------------------------------------------------------//
		uint32_t get_file_size() const noexcept
		{
			if(!open_) return 0;
			return f_size(&fp_);
		}
	};
}
<commit_msg>fix: read block num<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	ファイル・入出力クラス @n
			※ fopen 系の機能を提供するクラス。@n
			※ FATFS が必要
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#ifndef FAT_FS
#  error "file_io.hpp requires FAT_FS to be defined and include FATFS module"
#endif

#include "ff12b/src/diskio.h"
#include "ff12b/src/ff.h"

extern "C" {
	int make_full_path(const char* src, char* dst, uint16_t dsz);
	void utf8_to_sjis(const char* src, char* dst, uint32_t dsz);
};

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	ファイル入出力クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class file_io {
	public:

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        /*!
            @brief  SEEK タイプ
        */
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        enum class SEEK {
			SET,	///< 先頭からのオフセット
			CUR,	///< 現在位置からのオフセット
			END		///< 終端からのオフセット
        };

	private:
		FIL			fp_;
		bool		open_;

	public:
		//-------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		*/
		//-------------------------------------------------------------//
		file_io() noexcept :
			fp_(),
			open_(false)
		{ }

		//-------------------------------------------------------------//
		/*!
			@brief	デストラクター
		*/
		//-------------------------------------------------------------//
		~file_io() { close(); }

		//-------------------------------------------------------------//
		/*!
			@brief	ファイルを開く
			@param[in]	filename	ファイル名
			@param[in]	mode		オープン・モード
			@return 成功なら「true」
		*/
		//-------------------------------------------------------------//
		bool open(const char* filename, const char* mode) noexcept
		{
			if(filename == nullptr || mode == nullptr) return false;

			BYTE mdf = 0;
			if(strchr(mode, 'r') != nullptr) {
				mdf = FA_READ | FA_OPEN_EXISTING;
			}
			if(strchr(mode, 'w') != nullptr) {
				mdf = FA_WRITE;
				mdf |= FA_CREATE_NEW;
//				if(flags & O_TRUNC) mode |= FA_CREATE_ALWAYS;
			}
//			else if(rwm == O_RDWR) mode = FA_READ | FA_WRITE;
			if(strchr(mode, 'a') != nullptr) {
				mdf |= FA_OPEN_APPEND;
			}

			char tmp[_MAX_LFN + 1];
			if(!make_full_path(filename, tmp, sizeof(tmp))) {
				return false;
			}

			utf8_to_sjis(tmp, tmp, sizeof(tmp));
			FRESULT res = f_open(&fp_, tmp, mdf);
			if(res != FR_OK) {
				return false;
			}
			open_ = true;
			return true;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	ファイル・ディスクリプタへの参照
			@return ファイル・ディスクリプタ
		*/
		//-------------------------------------------------------------//
		FIL& at_fd() noexcept { return fp_; }

		//-------------------------------------------------------------//
		/*!
			@brief	オープンの確認
			@return オープンなら「true」
		*/
		//-------------------------------------------------------------//
		bool is_open() const noexcept { return open_; }

		//-------------------------------------------------------------//
		/*!
			@brief	ファイルをクローズする
			@return 成功なら「true」
		*/
		//-------------------------------------------------------------//
		bool close() noexcept
		{
			if(!open_) {
				return false;
			}
			open_ = false;
			return f_close(&fp_) == FR_OK;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	リード
			@param[out]	dst		読込先
			@param[in]	num		読み込みサイズ
			@return 読み込みサイズ
		*/
		//-------------------------------------------------------------//
		uint32_t read(void* dst, uint32_t len) noexcept
		{
			if(!open_) return 0;

			UINT rl = 0;
			FRESULT res = f_read(&fp_, dst, len, &rl);
			if(res != FR_OK) {
				return 0;
			}
			return rl;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	リード
			@param[out]	dst		読込先
			@param[in]	block	ブロックサイズ
			@param[in]	num		個数
			@return 読み込みサイズ
		*/
		//-------------------------------------------------------------//
		uint32_t read(void* dst, uint32_t block, uint32_t num) noexcept
		{
			return read(dst, block * num) / block;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	１文字取得
			@param[out]	ch	文字（参照）
			@return 正常なら「true」
		*/
		//-------------------------------------------------------------//
		bool get_char(char& ch) noexcept
		{
			char tmp[1];
			if(read(tmp, 1) != 1) {
				return false;
			}
			ch = tmp[0];
			return true;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	ライト
			@param[in]	src		ソース
			@param[in]	num		書き込みサイズ
			@return 書き込みサイズ
		*/
		//-------------------------------------------------------------//
		uint32_t write(const void* src, uint32_t len) noexcept
		{
			if(!open_) return 0;

			UINT wl = 0;
			FRESULT res = f_write(&fp_, src, len, &wl);
			if(res != FR_OK) {
				return 0;
			}
			return wl;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	シーク（fseek 準拠）
			@param[in]	seek	シーク形式
			@param[in]	ofs		オフセット
			@return 成功なら「true」
		*/
		//-------------------------------------------------------------//
		bool seek(SEEK seek, int32_t ofs) noexcept
		{
			if(!open_) return false;
			FRESULT ret;
			switch(seek) {
			case SEEK::SET:
				ret = f_lseek(&fp_, ofs);
				break;
			case SEEK::CUR:
				{
					int32_t pos = tell();
					pos += ofs;
					ret = f_lseek(&fp_, pos);
				}
				break;
			case SEEK::END:
				{
					int32_t pos = get_file_size();
					pos -= ofs;
					ret = f_lseek(&fp_, pos);
				}
				break;
			default:
				return false;
				break;
			}
			return ret == FR_OK;
		}

		//-------------------------------------------------------------//
		/*!
			@brief	ファイル位置を返す
			@return ファイル位置
		*/
		//-------------------------------------------------------------//
		uint32_t tell() const noexcept
		{
			if(!open_) return false;
			return f_tell(&fp_);
		}

		//-------------------------------------------------------------//
		/*!
			@brief	ファイルの終端か検査
			@return ファイルの終端なら「true」
		*/
		//-------------------------------------------------------------//
		bool eof() const noexcept
		{
			if(!open_) return false;
			return f_eof(&fp_);
		}

		//-------------------------------------------------------------//
		/*!
			@brief	ファイルサイズを返す
			@return ファイルサイズ
		*/
		//-------------------------------------------------------------//
		uint32_t get_file_size() const noexcept
		{
			if(!open_) return 0;
			return f_size(&fp_);
		}
	};
}
<|endoftext|>


<commit_before>#ifndef INCLUDE_AL_REVERB_HPP
#define INCLUDE_AL_REVERB_HPP

/*	Allocore --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2006-2008. The Regents of the University of California (REGENTS).
	All Rights Reserved.

	Permission to use, copy, modify, distribute, and distribute modified versions
	of this software and its documentation without fee and without a signed
	licensing agreement, is hereby granted, provided that the above copyright
	notice, the list of contributors, this paragraph and the following two paragraphs
	appear in all copies, modifications, and distributions.

	IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
	SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
	OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
	BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

	REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
	HEREUNDER IS PROVIDED "AS IS". REGENTS HAS  NO OBLIGATION TO PROVIDE
	MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

	File description:
	Mono-to-stereo reverberator

	File author(s):
	Lance Putnam, 2010, putnam.lance@gmail.com
*/

#include <cmath>
#include <stdlib.h>
#include <string.h>

namespace al{

/// Delay-line whose maximum size is fixed

/// The advantage of using a static versus dynamic array is that its elements
/// can be laid out in a predictable location in memory. This can improve
/// access speeds if many delay-lines are used within another object, like a
/// reverb.
template <int N, class T>
class StaticDelayLine {
public:

	StaticDelayLine(): mPos(0){ zero(); }

	/// Get size of delay-line
	static int size(){ return N; }

	/// Get element at back
	const T& back() const { return mBuf[indexBack()]; }

	/// Get index of back element
	int indexBack() const {
		int i = pos()+1;
		return (i < size()) ? i : 0;
	}

	/// Get absolute index of write tap
	int pos() const { return mPos; }

	/// Read value at delay i
	const T& read(int i) const {
		int ind = pos()-i;
		if(ind < 0) ind += size();
		//else if(ind >= size()) ind -= size();
		return mBuf[ind];
	}

	/// Write value to delay
	void write(const T& v){
		mBuf[pos()] = v;
		++mPos; if(mPos >= size()) mPos=0;
	}

	/// Write new value and return oldest value
	T operator()(const T& v){
		T r = mBuf[pos()];
		write(v);
		return r;
	}

	/// Comb filter input using a delay time equal to the maximum size of the delay-line
	T comb(const T& v, const T& ffd, const T& fbk){
		T d = mBuf[pos()];
		T r = v + d*fbk;
		write(r);
		return d + r*ffd;
	}

	/// Allpass filter input using a delay time equal to the maximum size of the delay-line
	T allpass(const T& v, const T& ffd){
		return comb(v, ffd,-ffd);
	}

	/// Zeroes all elements (byte-wise)
	void zero(){ ::memset(&mBuf, 0, sizeof(mBuf)); }

protected:
	int mPos;
	T mBuf[N];
};

/// Plate reverberator

/// Design from:
/// Dattorro, J. (1997). Effect design: Part 1: Reverberator and other filters.
/// Journal of the Audio Engineering Society, 45(9):660–684.
/// https://ccrma.stanford.edu/~dattorro/EffectDesignPart1.pdf
template <class T = float>
class Reverb{
public:

	Reverb(){
		bandwidth(0.9995);
		decay(0.85);
		damping(0.4);
		diffusion(0.76, 0.666, 0.707, 0.571);
	}

	/// Set input signal bandwidth, in [0,1]

	/// This sets the cutoff frequency of a one-pole low-pass filter on the
	/// input signal.
	Reverb& bandwidth(T v){ mOPIn.damping(T(1)-v); return *this; }

	/// Set high-frequency damping amount, in [0, 1]

	/// Higher amounts will dampen the diffusive sound more quickly.
	/// Note: values in [-1, 0] create an inverse effect that attentuates low
	/// rather than high frequencies.
	Reverb& damping(T v){ mOP1.damping(v); mOP2.damping(v); return *this; }

	/// Set decay factor, in [0, 1)
	Reverb& decay(T v){ mDecay=v; return *this; }

	/// Set diffusion amounts, in [0, 1)

	/// Values near 0.7 are recommended. Moving further away from 0.7 will lead
	/// to more distinct echoes.
	Reverb& diffusion(T in1, T in2, T decay1, T decay2){
		mDfIn1=in1;	mDfIn2=in2; mDfDcy1=decay1; mDfDcy2=decay2;
		return *this;
	}

	/// Set input diffusion 1 amount, [0,1)
	Reverb& diffusionIn1(const T& v){ mDfIn1=v; return *this; }

	/// Set input diffusion 2 amount, [0,1)
	Reverb& diffusionIn2(const T& v){ mDfIn2=v; return *this; }

	/// Set tank decay diffusion 1 amount, [0,1)
	Reverb& diffusionDecay1(const T& v){ mDfDcy1=v; return *this; }

	/// Set tank decay diffusion 2 amount, [0,1)
	Reverb& diffusionDecay2(const T& v){ mDfDcy2=v; return *this; }

	/// Compute wet stereo output from dry mono input

	/// @param[ in] in		dry input sample
	/// @param[out] out1	wet output sample 1
	/// @param[out] out2	wet output sample 2
	/// @param[ in] gain	gain of output
	void operator()(const T& in, T& out1, T& out2, T gain = T(0.6)){
		T v = mPreDelay(in * T(0.5));
		v = mOPIn(v);
		v = mAPIn1.allpass(v, mDfIn1);
		v = mAPIn2.allpass(v, mDfIn1);
		v = mAPIn3.allpass(v, mDfIn2);
		v = mAPIn4.allpass(v, mDfIn2);

		T a = v + mDly22.back() * mDecay;
		T b = v + mDly12.back() * mDecay;

		a = mAPDecay11.allpass(a,-mDfDcy1);
		a = mDly11(a);
		a = mOP1(a) * mDecay;
		a = mAPDecay12.allpass(a, mDfDcy2);
		mDly12.write(a);

		b = mAPDecay21.allpass(b,-mDfDcy1);
		b = mDly21(b);
		b = mOP2(b) * mDecay;
		b = mAPDecay22.allpass(b, mDfDcy2);
		mDly22.write(b);

		out1 = (  mDly21.read(266)
				+ mDly21.read(2974)
				- mAPDecay22.read(1913)
				+ mDly22.read(1996)
				- mDly11.read(1990)
				- mAPDecay12.read(187)
				- mDly12.read(1066)) * gain;

		out2 = (  mDly11.read(353)
				+ mDly11.read(3627)
				- mAPDecay12.read(1228)
				+ mDly12.read(2673)
				- mDly21.read(2111)
				- mAPDecay22.read(335)
				- mDly22.read(121)) * gain;
	}

	/// Compute wet/dry mix stereo output from dry mono input

	/// @param[inout] inout1		the input sample and wet/dry output 1
	/// @param[  out]   out2		wet/dry output 2
	/// @param[in   ] wetAmt		wet mix amount
	/// \returns dry input sample
	T mix(T& inout1, T& out2, T wetAmt){
		T s = inout1;
		(*this)(s, inout1, out2, wetAmt*T(0.6));
		inout1 += s;
		  out2 += s;
		return s;
	}

protected:

	class OnePole{
	public:
		OnePole(): mO1(0), mA0(1), mB1(0){}
		void damping(T v){ coef(v); }
		void coef(T v){ mA0=T(1)-std::abs(v); mB1=v; }
		T operator()(const T& i0){ return mO1 = i0*mA0 + mO1*mB1; }
	protected:
		T mO1, mA0, mB1;
	};

	T mDfIn1, mDfIn2, mDfDcy1, mDfDcy2, mDecay;

	StaticDelayLine<  10,T> mPreDelay;
	OnePole mOPIn;
	StaticDelayLine< 142,T> mAPIn1;
	StaticDelayLine< 107,T> mAPIn2;
	StaticDelayLine< 379,T> mAPIn3;
	StaticDelayLine< 277,T> mAPIn4;
	StaticDelayLine< 672,T> mAPDecay11;
	StaticDelayLine<1800,T> mAPDecay12;
	StaticDelayLine<4453,T> mDly11;
	StaticDelayLine<3720,T> mDly12;
	OnePole mOP1;
	StaticDelayLine< 908,T> mAPDecay21;
	StaticDelayLine<2656,T> mAPDecay22;
	StaticDelayLine<4217,T> mDly21;
	StaticDelayLine<3163,T> mDly22;
	OnePole mOP2;
};

} // al::
#endif
<commit_msg>high-pass diffusion<commit_after>#ifndef INCLUDE_AL_REVERB_HPP
#define INCLUDE_AL_REVERB_HPP

/*	Allocore --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2006-2008. The Regents of the University of California (REGENTS).
	All Rights Reserved.

	Permission to use, copy, modify, distribute, and distribute modified versions
	of this software and its documentation without fee and without a signed
	licensing agreement, is hereby granted, provided that the above copyright
	notice, the list of contributors, this paragraph and the following two paragraphs
	appear in all copies, modifications, and distributions.

	IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
	SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
	OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
	BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

	REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
	HEREUNDER IS PROVIDED "AS IS". REGENTS HAS  NO OBLIGATION TO PROVIDE
	MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

	File description:
	Mono-to-stereo reverberator

	File author(s):
	Lance Putnam, 2010, putnam.lance@gmail.com
*/

#include <cmath>
#include <stdlib.h>
#include <string.h>

namespace al{

/// Delay-line whose maximum size is fixed

/// The advantage of using a static versus dynamic array is that its elements
/// can be laid out in a predictable location in memory. This can improve
/// access speeds if many delay-lines are used within another object, like a
/// reverb.
template <int N, class T>
class StaticDelayLine {
public:

	StaticDelayLine(): mPos(0){ zero(); }

	/// Get size of delay-line
	static int size(){ return N; }

	/// Get element at back
	const T& back() const { return mBuf[indexBack()]; }

	/// Get index of back element
	int indexBack() const {
		int i = pos()+1;
		return (i < size()) ? i : 0;
	}

	/// Get absolute index of write tap
	int pos() const { return mPos; }

	/// Read value at delay i
	const T& read(int i) const {
		int ind = pos()-i;
		if(ind < 0) ind += size();
		//else if(ind >= size()) ind -= size();
		return mBuf[ind];
	}

	/// Write value to delay
	void write(const T& v){
		mBuf[pos()] = v;
		++mPos; if(mPos >= size()) mPos=0;
	}

	/// Write new value and return oldest value
	T operator()(const T& v){
		T r = mBuf[pos()];
		write(v);
		return r;
	}

	/// Comb filter input using a delay time equal to the maximum size of the delay-line
	T comb(const T& v, const T& ffd, const T& fbk){
		T d = mBuf[pos()];
		T r = v + d*fbk;
		write(r);
		return d + r*ffd;
	}

	/// Allpass filter input using a delay time equal to the maximum size of the delay-line
	T allpass(const T& v, const T& ffd){
		return comb(v, ffd,-ffd);
	}

	/// Zeroes all elements (byte-wise)
	void zero(){ ::memset(&mBuf, 0, sizeof(mBuf)); }

protected:
	int mPos;
	T mBuf[N];
};

/// Plate reverberator

/// Design from:
/// Dattorro, J. (1997). Effect design: Part 1: Reverberator and other filters.
/// Journal of the Audio Engineering Society, 45(9):660–684.
/// https://ccrma.stanford.edu/~dattorro/EffectDesignPart1.pdf
template <class T = float>
class Reverb{
public:

	Reverb(){
		bandwidth(0.9995);
		decay(0.85);
		damping(0.4);
		diffusion(0.76, 0.666, 0.707, 0.571);
	}

	/// Set input signal bandwidth, in [0,1]

	/// This sets the cutoff frequency of a one-pole low-pass filter on the
	/// input signal.
	Reverb& bandwidth(T v){ mOPIn.damping(T(1)-v); return *this; }

	/// Set high-frequency damping amount, in [0, 1]

	/// Higher amounts will dampen the diffusive sound more quickly.
	/// Note: values in [-1, 0] create an inverse effect that attentuates low
	/// rather than high frequencies.
	Reverb& damping(T v){ mOP1.damping(v); mOP2.damping(v); return *this; }

	/// Set decay factor, in [0, 1)
	Reverb& decay(T v){ mDecay=v; return *this; }

	/// Set diffusion amounts, in [0, 1)

	/// Values near 0.7 are recommended. Moving further away from 0.7 will lead
	/// to more distinct echoes.
	Reverb& diffusion(T in1, T in2, T decay1, T decay2){
		mDfIn1=in1;	mDfIn2=in2; mDfDcy1=decay1; mDfDcy2=decay2;
		return *this;
	}

	/// Set input diffusion 1 amount, [0,1)
	Reverb& diffusionIn1(T v){ mDfIn1=v; return *this; }

	/// Set input diffusion 2 amount, [0,1)
	Reverb& diffusionIn2(T v){ mDfIn2=v; return *this; }

	/// Set tank decay diffusion 1 amount, [0,1)
	Reverb& diffusionDecay1(T v){ mDfDcy1=v; return *this; }

	/// Set tank decay diffusion 2 amount, [0,1)
	Reverb& diffusionDecay2(T v){ mDfDcy2=v; return *this; }

	/// Compute wet stereo output from dry mono input

	/// @param[ in] in		dry input sample
	/// @param[out] out1	wet output sample 1
	/// @param[out] out2	wet output sample 2
	/// @param[ in] gain	gain of output
	void operator()(T in, T& out1, T& out2, T gain = T(0.6)){
		T v = mPreDelay(in * T(0.5));
		v = mOPIn(v);
		v = mAPIn1.allpass(v, mDfIn1);
		v = mAPIn2.allpass(v, mDfIn1);
		v = mAPIn3.allpass(v, mDfIn2);
		v = mAPIn4.allpass(v, mDfIn2);

		T a = v + mDly22.back() * mDecay;
		T b = v + mDly12.back() * mDecay;

		a = mAPDecay11.allpass(a,-mDfDcy1);
		a = mDly11(a);
		a = mOP1(a) * mDecay;
		a = mAPDecay12.allpass(a, mDfDcy2);
		mDly12.write(a);

		b = mAPDecay21.allpass(b,-mDfDcy1);
		b = mDly21(b);
		b = mOP2(b) * mDecay;
		b = mAPDecay22.allpass(b, mDfDcy2);
		mDly22.write(b);

		out1 = (  mDly21.read(266)
				+ mDly21.read(2974)
				- mAPDecay22.read(1913)
				+ mDly22.read(1996)
				- mDly11.read(1990)
				- mAPDecay12.read(187)
				- mDly12.read(1066)) * gain;

		out2 = (  mDly11.read(353)
				+ mDly11.read(3627)
				- mAPDecay12.read(1228)
				+ mDly12.read(2673)
				- mDly21.read(2111)
				- mAPDecay22.read(335)
				- mDly22.read(121)) * gain;
	}

	/// Compute wet/dry mix stereo output from dry mono input

	/// @param[inout] inout1		the input sample and wet/dry output 1
	/// @param[  out]   out2		wet/dry output 2
	/// @param[in   ] wetAmt		wet mix amount
	/// \returns dry input sample
	T mix(T& inout1, T& out2, T wetAmt){
		T s = inout1;
		(*this)(s, inout1, out2, wetAmt*T(0.6));
		inout1 += s;
		  out2 += s;
		return s;
	}

protected:

	class OnePole{
	public:
		OnePole(): mO1(0), mA0(1), mB1(0){}
		void damping(T v){ coef(v); }
		void coef(T v){ mA0=T(1)-std::abs(v); mB1=v; }
		T operator()(T i0){ return mO1 = i0*mA0 + mO1*mB1; }
	protected:
		T mO1, mA0, mB1;
	};

	T mDfIn1, mDfIn2, mDfDcy1, mDfDcy2, mDecay;

	StaticDelayLine<  10,T> mPreDelay;
	OnePole mOPIn;
	StaticDelayLine< 142,T> mAPIn1;
	StaticDelayLine< 107,T> mAPIn2;
	StaticDelayLine< 379,T> mAPIn3;
	StaticDelayLine< 277,T> mAPIn4;
	StaticDelayLine< 672,T> mAPDecay11;
	StaticDelayLine<1800,T> mAPDecay12;
	StaticDelayLine<4453,T> mDly11;
	StaticDelayLine<3720,T> mDly12;
	OnePole mOP1;
	StaticDelayLine< 908,T> mAPDecay21;
	StaticDelayLine<2656,T> mAPDecay22;
	StaticDelayLine<4217,T> mDly21;
	StaticDelayLine<3163,T> mDly22;
	OnePole mOP2;
};

} // al::
#endif
<|endoftext|>


<commit_before>#include "catch.hpp"

#include <shadow.hpp>

REGISTER_TYPE_BEGIN()
REGISTER_TYPE_END()

SHADOW_INIT()

TEST_CASE("test special member functions of shadow::variable", "[variable]")
{
    shadow::variable a;

    REQUIRE(a.has_value() == false);
}
<commit_msg>Add unit tests for default constructing shadow::variable. 	modified:   tests/test_variable_api.cpp<commit_after>#include "catch.hpp"

#include <shadow.hpp>
#include <utility>

namespace tv_space
{
REGISTER_TYPE_BEGIN()
REGISTER_TYPE_END()

SHADOW_INIT()
}

TEST_CASE("default construct a variable", "[variable]")
{
    shadow::variable a;

    REQUIRE(a.has_value() == false);

    SECTION("copy construct another variable from a")
    {
        shadow::variable b = a;

        REQUIRE(b.has_value() == false);
    }

    SECTION("move construct another variable from a")
    {
        shadow::variable b = std::move(a);
    }

    SECTION("default constructo another variable")
    {
        shadow::variable b;

        SECTION("copy assign a to b")
        {
            b = a;

            REQUIRE(b.has_value() == false);
        }

        SECTION("move assign a to b")
        {
            b = std::move(a);

            REQUIRE(b.has_value() == false);
        }
    }
}
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2001-2014.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//!@file
//!@brief a central place for global configuration switches
// ***************************************************************************

#ifndef BOOST_TEST_CONFIG_HPP_071894GER
#define BOOST_TEST_CONFIG_HPP_071894GER

// Boost
#include <boost/config.hpp> // compilers workarounds
#include <boost/detail/workaround.hpp>

#if defined(_WIN32) && !defined(BOOST_DISABLE_WIN32) &&                  \
    (!defined(__COMO__) && !defined(__MWERKS__) && !defined(__GNUC__) || \
    BOOST_WORKAROUND(__MWERKS__, >= 0x3000))
#  define BOOST_SEH_BASED_SIGNAL_HANDLING
#endif

#if defined(__COMO__) && defined(_MSC_VER)
// eh.h uses type_info without declaring it.
class type_info;
#  define BOOST_SEH_BASED_SIGNAL_HANDLING
#endif

//____________________________________________________________________________//

#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)) || \
    BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))     || \
    (defined __sgi && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(730)))
#  define BOOST_TEST_SHIFTED_LINE
#endif

//____________________________________________________________________________//

#if defined(BOOST_MSVC) || (defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32))
#  define BOOST_TEST_CALL_DECL __cdecl
#else
#  define BOOST_TEST_CALL_DECL /**/
#endif

//____________________________________________________________________________//

#if !defined(BOOST_NO_STD_LOCALE) && !defined(__MWERKS__)
#  define BOOST_TEST_USE_STD_LOCALE 1
#endif

//____________________________________________________________________________//

#if BOOST_WORKAROUND(__BORLANDC__, <= 0x570)            || \
    BOOST_WORKAROUND( __COMO__, <= 0x433 )              || \
    BOOST_WORKAROUND( __INTEL_COMPILER, <= 800 )        || \
    defined(__sgi) && _COMPILER_VERSION <= 730          || \
    BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))  || \
    defined(__DECCXX)                                   || \
    defined(__DMC__)
#  define BOOST_TEST_NO_PROTECTED_USING
#endif

//____________________________________________________________________________//

#if defined(__GNUC__) || BOOST_WORKAROUND(BOOST_MSVC, == 1400)
#define BOOST_TEST_PROTECTED_VIRTUAL virtual
#else
#define BOOST_TEST_PROTECTED_VIRTUAL
#endif

//____________________________________________________________________________//

#if !defined(__BORLANDC__) && !BOOST_WORKAROUND( __SUNPRO_CC, < 0x5100 )
#define BOOST_TEST_SUPPORT_TOKEN_ITERATOR 1
#endif

//____________________________________________________________________________//

#if defined(BOOST_ALL_DYN_LINK) && !defined(BOOST_TEST_DYN_LINK)
#  define BOOST_TEST_DYN_LINK
#endif

#if defined(BOOST_TEST_INCLUDED)
#  undef BOOST_TEST_DYN_LINK
#endif

#if defined(BOOST_TEST_DYN_LINK)
#  define BOOST_TEST_ALTERNATIVE_INIT_API

#  ifdef BOOST_TEST_SOURCE
#    define BOOST_TEST_DECL BOOST_SYMBOL_EXPORT
#  else
#    define BOOST_TEST_DECL BOOST_SYMBOL_IMPORT
#  endif  // BOOST_TEST_SOURCE
#else
#  define BOOST_TEST_DECL
#endif

#if !defined(BOOST_TEST_MAIN) && defined(BOOST_AUTO_TEST_MAIN)
#define BOOST_TEST_MAIN BOOST_AUTO_TEST_MAIN
#endif

#if !defined(BOOST_TEST_MAIN) && defined(BOOST_TEST_MODULE)
#define BOOST_TEST_MAIN BOOST_TEST_MODULE
#endif

#ifdef __PGI
#define BOOST_PP_VARIADICS 1
#endif

#if BOOST_CLANG
#define BOOST_PP_VARIADICS 1
#endif

#if defined(BOOST_GCC) && (BOOST_GCC >= 4 * 10000 + 8 * 100)
#define BOOST_PP_VARIADICS 1
#endif

#endif // BOOST_TEST_CONFIG_HPP_071894GER
<commit_msg>fixup! do not enforce the support of PP_VARIADIC if already defined<commit_after>//  (C) Copyright Gennadiy Rozental 2001-2014.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//!@file
//!@brief a central place for global configuration switches
// ***************************************************************************

#ifndef BOOST_TEST_CONFIG_HPP_071894GER
#define BOOST_TEST_CONFIG_HPP_071894GER

// Boost
#include <boost/config.hpp> // compilers workarounds
#include <boost/detail/workaround.hpp>

#if defined(_WIN32) && !defined(BOOST_DISABLE_WIN32) &&                  \
    (!defined(__COMO__) && !defined(__MWERKS__) && !defined(__GNUC__) || \
    BOOST_WORKAROUND(__MWERKS__, >= 0x3000))
#  define BOOST_SEH_BASED_SIGNAL_HANDLING
#endif

#if defined(__COMO__) && defined(_MSC_VER)
// eh.h uses type_info without declaring it.
class type_info;
#  define BOOST_SEH_BASED_SIGNAL_HANDLING
#endif

//____________________________________________________________________________//

#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)) || \
    BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))     || \
    (defined __sgi && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(730)))
#  define BOOST_TEST_SHIFTED_LINE
#endif

//____________________________________________________________________________//

#if defined(BOOST_MSVC) || (defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32))
#  define BOOST_TEST_CALL_DECL __cdecl
#else
#  define BOOST_TEST_CALL_DECL /**/
#endif

//____________________________________________________________________________//

#if !defined(BOOST_NO_STD_LOCALE) && !defined(__MWERKS__)
#  define BOOST_TEST_USE_STD_LOCALE 1
#endif

//____________________________________________________________________________//

#if BOOST_WORKAROUND(__BORLANDC__, <= 0x570)            || \
    BOOST_WORKAROUND( __COMO__, <= 0x433 )              || \
    BOOST_WORKAROUND( __INTEL_COMPILER, <= 800 )        || \
    defined(__sgi) && _COMPILER_VERSION <= 730          || \
    BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))  || \
    defined(__DECCXX)                                   || \
    defined(__DMC__)
#  define BOOST_TEST_NO_PROTECTED_USING
#endif

//____________________________________________________________________________//

#if defined(__GNUC__) || BOOST_WORKAROUND(BOOST_MSVC, == 1400)
#define BOOST_TEST_PROTECTED_VIRTUAL virtual
#else
#define BOOST_TEST_PROTECTED_VIRTUAL
#endif

//____________________________________________________________________________//

#if !defined(__BORLANDC__) && !BOOST_WORKAROUND( __SUNPRO_CC, < 0x5100 )
#define BOOST_TEST_SUPPORT_TOKEN_ITERATOR 1
#endif

//____________________________________________________________________________//

#if defined(BOOST_ALL_DYN_LINK) && !defined(BOOST_TEST_DYN_LINK)
#  define BOOST_TEST_DYN_LINK
#endif

#if defined(BOOST_TEST_INCLUDED)
#  undef BOOST_TEST_DYN_LINK
#endif

#if defined(BOOST_TEST_DYN_LINK)
#  define BOOST_TEST_ALTERNATIVE_INIT_API

#  ifdef BOOST_TEST_SOURCE
#    define BOOST_TEST_DECL BOOST_SYMBOL_EXPORT
#  else
#    define BOOST_TEST_DECL BOOST_SYMBOL_IMPORT
#  endif  // BOOST_TEST_SOURCE
#else
#  define BOOST_TEST_DECL
#endif

#if !defined(BOOST_TEST_MAIN) && defined(BOOST_AUTO_TEST_MAIN)
#define BOOST_TEST_MAIN BOOST_AUTO_TEST_MAIN
#endif

#if !defined(BOOST_TEST_MAIN) && defined(BOOST_TEST_MODULE)
#define BOOST_TEST_MAIN BOOST_TEST_MODULE
#endif

#ifndef BOOST_PP_VARIADICS /* we can change this only if not already defined) */

#ifdef __PGI
#define BOOST_PP_VARIADICS 1
#endif

#if BOOST_CLANG
#define BOOST_PP_VARIADICS 1
#endif

#if defined(BOOST_GCC) && (BOOST_GCC >= 4 * 10000 + 8 * 100)
#define BOOST_PP_VARIADICS 1
#endif

#endif /* ifndef BOOST_PP_VARIADICS */

#endif // BOOST_TEST_CONFIG_HPP_071894GER
<|endoftext|>


<commit_before>/**
 * These codes are licensed under the Unlicense.
 * http://unlicense.org
 */

#ifndef COMMATA_GUARD_815C71AA_E8EC_4B62_98C0_03D99230C7BB
#define COMMATA_GUARD_815C71AA_E8EC_4B62_98C0_03D99230C7BB

#include <type_traits>
#include <utility>

namespace commata {
namespace detail {

template <class F, class = void>
class member_like_base;

template <class F>
class member_like_base<F,
    std::enable_if_t<!std::is_reference<F>::value
                  && std::is_final<F>::value>>
{
    F f_;

public:
    member_like_base()
        noexcept(std::is_nothrow_default_constructible<F>::value)
    {}

    explicit member_like_base(const F& f)
        noexcept(std::is_nothrow_copy_constructible<F>::value) :
        f_(f)
    {}

    explicit member_like_base(F&& f)
        noexcept(std::is_nothrow_move_constructible<F>::value) :
        f_(std::move(f))
    {}

    F& get() noexcept
    {
        return f_;
    }

    const F& get() const noexcept
    {
        return f_;
    }
};

template <class F>
class member_like_base<F,
    std::enable_if_t<!std::is_reference<F>::value
                  && !std::is_final<F>::value>> :
    F
{
public:
    member_like_base()
        noexcept(std::is_nothrow_default_constructible<F>::value)
    {}

    explicit member_like_base(const F& f)
        noexcept(std::is_nothrow_copy_constructible<F>::value) :
        F(f)
    {}

    explicit member_like_base(F&& f)
        noexcept(std::is_nothrow_move_constructible<F>::value) :
        F(std::move(f))
    {}

    F& get() noexcept
    {
        return *this;
    }

    const F& get() const noexcept
    {
        return *this;
    }
};

template <class B, class M>
class base_member_pair
{
    struct pair : member_like_base
    {
        M m;

        pair(B base, M member) :
            member_like_base(std::move(base)), m(std::move(member))
        {}
    };

    pair p_;

public:
    base_member_pair(B first, M second) :
        p_(std::move(first), std::move(second))
    {}

    B& base() noexcept
    {
        return p_.get();
    }

    const B& base() const noexcept
    {
        return p_.get();
    }

    M& member() noexcept
    {
        return p_.m;
    }

    const M& member() const noexcept
    {
        return p_.m;
    }
};

}}

#endif
<commit_msg>Apply stricter policies for noexcept on member_like_base and base_member_pair<commit_after>/**
 * These codes are licensed under the Unlicense.
 * http://unlicense.org
 */

#ifndef COMMATA_GUARD_815C71AA_E8EC_4B62_98C0_03D99230C7BB
#define COMMATA_GUARD_815C71AA_E8EC_4B62_98C0_03D99230C7BB

#include <type_traits>
#include <utility>

namespace commata {
namespace detail {

template <class F, class = void>
class member_like_base;

template <class F>
class member_like_base<F,
    std::enable_if_t<!std::is_reference<F>::value
                  && std::is_final<F>::value>>
{
    F f_;

public:
    member_like_base()
        noexcept(std::is_nothrow_default_constructible<F>::value)
    {}

    explicit member_like_base(const F& f)
        noexcept(std::is_nothrow_copy_constructible<F>::value) :
        f_(f)
    {}

    explicit member_like_base(F&& f)
        noexcept(std::is_nothrow_move_constructible<F>::value) :
        f_(std::move(f))
    {}

    F& get() noexcept
    {
        return f_;
    }

    const F& get() const noexcept
    {
        return f_;
    }
};

template <class F>
class member_like_base<F,
    std::enable_if_t<!std::is_reference<F>::value
                  && !std::is_final<F>::value>> :
    F
{
public:
    member_like_base()
        noexcept(std::is_nothrow_default_constructible<F>::value)
    {}

    explicit member_like_base(const F& f)
        noexcept(std::is_nothrow_copy_constructible<F>::value) :
        F(f)
    {}

    explicit member_like_base(F&& f)
        noexcept(std::is_nothrow_move_constructible<F>::value) :
        F(std::move(f))
    {}

    F& get() noexcept
    {
        return *this;
    }

    const F& get() const noexcept
    {
        return *this;
    }
};

template <class B, class M>
class base_member_pair
{
    struct pair : member_like_base
    {
        M m;

        template <class BR, class MR,
            class = std::enable_if_t<
                std::is_constructible::value
             && std::is_constructible<M, MR&&>::value>>
        pair(BR&& base, MR&& member)
            noexcept(std::is_nothrow_constructible::value
                  && std::is_nothrow_constructible<M, MR&&>::value) :
            member_like_base(std::forward
(base)),
            m(std::forward<MR>(member))
        {}
    };

    pair p_;

public:
    template <class BR, class MR,
        std::enable_if_t<
            std::is_constructible::value
         && std::is_constructible<M, MR&&>::value,
            std::nullptr_t> = nullptr>
    base_member_pair(BR&& first, MR&& second)
        noexcept(std::is_nothrow_constructible::value
              && std::is_nothrow_constructible<M, MR&&>::value) :
        p_(std::forward
(first), std::forward<MR>(second))
    {}

    B& base() noexcept
    {
        return p_.get();
    }

    const B& base() const noexcept
    {
        return p_.get();
    }

    M& member() noexcept
    {
        return p_.m;
    }

    const M& member() const noexcept
    {
        return p_.m;
    }
};

}}

#endif
<|endoftext|>


<commit_before>/*
 * This file is part of the Shiboken Python Bindings Generator project.
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 *
 * Contact: PySide team <contact@pyside.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "pysideqmlregistertype.h"
#include <Python.h>
#include <QObject>
#include <QDeclarativeEngine>
#include <QMutex>
#include <typeresolver.h>
#include "qdeclarativeitem_wrapper.h"
#include <sbkdbg.h>

#ifndef PYSIDE_MAX_QML_TYPES
// Maximum number of different types the user cna export to QML using qmlRegisterType.
#define PYSIDE_MAX_QML_TYPES 50
#endif

// All registered python types
static PyObject* pyTypes[PYSIDE_MAX_QML_TYPES];
static void (*createFuncs[PYSIDE_MAX_QML_TYPES])(void*);

/// QDeclarativeItem will create objects using placement new then this pointer is non-null.
void* PySide::nextQmlElementMemoryAddr = 0;
// Mutex used to avoid race condition on PySide::nextQmlElementMemoryAddr
static QMutex nextQmlElementMutex;

template<int N>
struct ElementFactoryBase
{
    static void createInto(void* memory)
    {
        QMutexLocker locker(&nextQmlElementMutex);
        PySide::nextQmlElementMemoryAddr = memory;
        PyObject* obj = PyObject_CallObject(pyTypes[N], 0);
        if (!obj || PyErr_Occurred())
            PyErr_Print();
        PySide::nextQmlElementMemoryAddr = 0;
    }
};

template<int N>
struct ElementFactory : ElementFactoryBase<N>
{
    static void init()
    {
        createFuncs[N] = &ElementFactoryBase<N>::createInto;
        ElementFactory<N-1>::init();
    }
};

template<>
struct  ElementFactory<0> : ElementFactoryBase<0>
{
    static void init()
    {
        createFuncs[0] = &ElementFactoryBase<0>::createInto;
    }
};

void PySide::initQmlSupport()
{
    ElementFactory<PYSIDE_MAX_QML_TYPES - 1>::init();
}

int PySide::qmlRegisterType(PyObject* pyObj, const char* uri, int versionMajor, int versionMinor, const char* qmlName)
{
    using namespace Shiboken;

    static PyTypeObject* declarativeItemType = TypeResolver::get("QDeclarativeItem*")->pythonType();
    assert(declarativeItemType);
    static int nextType = 0;

    if (nextType >= PYSIDE_MAX_QML_TYPES) {
        PyErr_Format(PyExc_TypeError, "QML doesn't really like language bindings, so you can only export %d types to QML.", PYSIDE_MAX_QML_TYPES);
        return -1;
    }

    if (pyObj->ob_type != &SbkObjectType_Type) {
        PyErr_Format(PyExc_TypeError, "A shiboken-based python type expected, got %s.", pyObj->ob_type->tp_name);
        return -1;
    }

    if (!PySequence_Contains(((PyTypeObject*)pyObj)->tp_mro, (PyObject*)declarativeItemType)) {
        PyErr_Format(PyExc_TypeError, "A type inherited from %s expected, got %s.", declarativeItemType->tp_name, ((PyTypeObject*)pyObj)->tp_name);
        return -1;
    }

    QMetaObject* metaObject = reinterpret_cast<QMetaObject*>(ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(pyObj)));
    if (!metaObject) {
        PyErr_SetString(PyExc_TypeError, "FIXME: metaobject not initialized, this error msg should not exists at all!!");
        return -1;
    }

    // All ready... now the ugly code begins... :-)
    pyTypes[nextType] = pyObj;

    // Init proxy object static meta object
    QDeclarativePrivate::RegisterType type;
    type.version = 0;
    type.typeId = qMetaTypeId<QDeclarativeItem*>();
    type.listId = qMetaTypeId<QDeclarativeListProperty<QDeclarativeItem> >();
    type.objectSize = sizeof(QDeclarativeItemWrapper);
    type.create = createFuncs[nextType];
    type.uri = uri;
    type.versionMajor = versionMajor;
    type.versionMinor = versionMinor;
    type.elementName = qmlName;
    type.metaObject = metaObject;

    type.attachedPropertiesFunction = QDeclarativePrivate::attachedPropertiesFunc<QDeclarativeItem>();
    type.attachedPropertiesMetaObject = QDeclarativePrivate::attachedPropertiesMetaObject<QDeclarativeItem>();

    type.parserStatusCast = QDeclarativePrivate::StaticCastSelector<QDeclarativeItem,QDeclarativeParserStatus>::cast();
    type.valueSourceCast = QDeclarativePrivate::StaticCastSelector<QDeclarativeItem,QDeclarativePropertyValueSource>::cast();
    type.valueInterceptorCast = QDeclarativePrivate::StaticCastSelector<QDeclarativeItem,QDeclarativePropertyValueInterceptor>::cast();

    type.extensionObjectCreate = 0;
    type.extensionMetaObject = 0;
    type.customParser = 0;

    int qmlTypeId = QDeclarativePrivate::qmlregister(QDeclarativePrivate::TypeRegistration, &type);
    ++nextType;
    return qmlTypeId;
}
<commit_msg>Replace useless check by a assert.<commit_after>/*
 * This file is part of the Shiboken Python Bindings Generator project.
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 *
 * Contact: PySide team <contact@pyside.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "pysideqmlregistertype.h"
#include <Python.h>
#include <QObject>
#include <QDeclarativeEngine>
#include <QMutex>
#include <typeresolver.h>
#include "qdeclarativeitem_wrapper.h"
#include <sbkdbg.h>

#ifndef PYSIDE_MAX_QML_TYPES
// Maximum number of different types the user cna export to QML using qmlRegisterType.
#define PYSIDE_MAX_QML_TYPES 50
#endif

// All registered python types
static PyObject* pyTypes[PYSIDE_MAX_QML_TYPES];
static void (*createFuncs[PYSIDE_MAX_QML_TYPES])(void*);

/// QDeclarativeItem will create objects using placement new then this pointer is non-null.
void* PySide::nextQmlElementMemoryAddr = 0;
// Mutex used to avoid race condition on PySide::nextQmlElementMemoryAddr
static QMutex nextQmlElementMutex;

template<int N>
struct ElementFactoryBase
{
    static void createInto(void* memory)
    {
        QMutexLocker locker(&nextQmlElementMutex);
        PySide::nextQmlElementMemoryAddr = memory;
        PyObject* obj = PyObject_CallObject(pyTypes[N], 0);
        if (!obj || PyErr_Occurred())
            PyErr_Print();
        PySide::nextQmlElementMemoryAddr = 0;
    }
};

template<int N>
struct ElementFactory : ElementFactoryBase<N>
{
    static void init()
    {
        createFuncs[N] = &ElementFactoryBase<N>::createInto;
        ElementFactory<N-1>::init();
    }
};

template<>
struct  ElementFactory<0> : ElementFactoryBase<0>
{
    static void init()
    {
        createFuncs[0] = &ElementFactoryBase<0>::createInto;
    }
};

void PySide::initQmlSupport()
{
    ElementFactory<PYSIDE_MAX_QML_TYPES - 1>::init();
}

int PySide::qmlRegisterType(PyObject* pyObj, const char* uri, int versionMajor, int versionMinor, const char* qmlName)
{
    using namespace Shiboken;

    static PyTypeObject* declarativeItemType = TypeResolver::get("QDeclarativeItem*")->pythonType();
    assert(declarativeItemType);
    static int nextType = 0;

    if (nextType >= PYSIDE_MAX_QML_TYPES) {
        PyErr_Format(PyExc_TypeError, "QML doesn't really like language bindings, so you can only export %d types to QML.", PYSIDE_MAX_QML_TYPES);
        return -1;
    }

    if (pyObj->ob_type != &SbkObjectType_Type) {
        PyErr_Format(PyExc_TypeError, "A shiboken-based python type expected, got %s.", pyObj->ob_type->tp_name);
        return -1;
    }

    if (!PySequence_Contains(((PyTypeObject*)pyObj)->tp_mro, (PyObject*)declarativeItemType)) {
        PyErr_Format(PyExc_TypeError, "A type inherited from %s expected, got %s.", declarativeItemType->tp_name, ((PyTypeObject*)pyObj)->tp_name);
        return -1;
    }

    QMetaObject* metaObject = reinterpret_cast<QMetaObject*>(ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(pyObj)));
    Q_ASSERT(metaObject);

    // All ready... now the ugly code begins... :-)
    pyTypes[nextType] = pyObj;

    // Init proxy object static meta object
    QDeclarativePrivate::RegisterType type;
    type.version = 0;
    type.typeId = qMetaTypeId<QDeclarativeItem*>();
    type.listId = qMetaTypeId<QDeclarativeListProperty<QDeclarativeItem> >();
    type.objectSize = sizeof(QDeclarativeItemWrapper);
    type.create = createFuncs[nextType];
    type.uri = uri;
    type.versionMajor = versionMajor;
    type.versionMinor = versionMinor;
    type.elementName = qmlName;
    type.metaObject = metaObject;

    type.attachedPropertiesFunction = QDeclarativePrivate::attachedPropertiesFunc<QDeclarativeItem>();
    type.attachedPropertiesMetaObject = QDeclarativePrivate::attachedPropertiesMetaObject<QDeclarativeItem>();

    type.parserStatusCast = QDeclarativePrivate::StaticCastSelector<QDeclarativeItem,QDeclarativeParserStatus>::cast();
    type.valueSourceCast = QDeclarativePrivate::StaticCastSelector<QDeclarativeItem,QDeclarativePropertyValueSource>::cast();
    type.valueInterceptorCast = QDeclarativePrivate::StaticCastSelector<QDeclarativeItem,QDeclarativePropertyValueInterceptor>::cast();

    type.extensionObjectCreate = 0;
    type.extensionMetaObject = 0;
    type.customParser = 0;

    int qmlTypeId = QDeclarativePrivate::qmlregister(QDeclarativePrivate::TypeRegistration, &type);
    ++nextType;
    return qmlTypeId;
}
<|endoftext|>