<commit_before>// RUN: clang-cc -fsyntax-only -verify %s

// This test creates cases where implicit instantiations of various entities
// would cause a diagnostic, but provides expliict specializations for those
// entities that avoid the diagnostic. The specializations are alternately
// declarations and definitions, and the intent of this test is to verify
// that we allow specializations only in the appropriate namespaces (and
// nowhere else).
struct NonDefaultConstructible {
  NonDefaultConstructible(int);
};

// C++ [temp.expl.spec]p1:
//   An explicit specialization of any of the following:

//     -- function template
namespace N0 {
  template<typename T> void f0(T) { // expected-note{{here}}
    T t;
  }

  template<> void f0(NonDefaultConstructible) { }

  void test_f0(NonDefaultConstructible NDC) {
    f0(NDC);
  }

  template<> void f0(int);
  template<> void f0(long);
}

template<> void N0::f0(int) { } // okay

namespace N1 {
  template<> void N0::f0(long) { } // expected-error{{not in a namespace enclosing}}
}

template<> void N0::f0(double) { } // expected-error{{originally be declared}}

struct X1 {
  template<typename T> void f(T);

  template<> void f(int); // expected-error{{in class scope}}
};

//     -- class template
namespace N0 {

template<typename T>
struct X0 { // expected-note 2{{here}}
  static T member; // expected-note{{here}}

  void f1(T t) { // expected-note{{explicitly specialized declaration is here}}
    t = 17;
  }

  struct Inner : public T { }; // expected-note 3{{here}}

  template<typename U>
  struct InnerTemplate : public T { };

  template<typename U>
  void ft1(T t, U u);
};

}

template<typename T>
template<typename U>
void N0::X0<T>::ft1(T t, U u) {
  t = u;
}

template<typename T> T N0::X0<T>::member;

template<> struct N0::X0<void> { }; // expected-error{{originally}}
N0::X0<void> test_X0;

namespace N1 {
  template<> struct N0::X0<const void> { }; // expected-error{{originally}}
}

namespace N0 {
  template<> struct X0<volatile void>;
}

template<> struct N0::X0<volatile void> {
  void f1(void *);
};

//     -- member function of a class template
template<> void N0::X0<void*>::f1(void *) { } // expected-error{{member function specialization}}

void test_spec(N0::X0<void*> xvp, void *vp) {
  xvp.f1(vp);
}

namespace N0 {
  template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}

  template<> void X0<const volatile void*>::f1(const volatile void*);
}

void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
  x0.f1(cvp); // okay: we've explicitly specialized
}

//     -- static data member of a class template
namespace N0 {
  // This actually tests p15; the following is a declaration, not a definition.
  template<>
  NonDefaultConstructible X0<NonDefaultConstructible>::member;

  template<> long X0<long>::member = 17;

  template<> float X0<float>::member;

  template<> double X0<double>::member;
}

NonDefaultConstructible &get_static_member() {
  return N0::X0<NonDefaultConstructible>::member;
}

template<> int N0::X0<int>::member;  // expected-error{{originally}}

template<> float N0::X0<float>::member = 3.14f;

namespace N1 {
  template<> double N0::X0<double>::member = 3.14; // expected-error{{not in a namespace enclosing}}
}

//    -- member class of a class template
namespace N0 {

  template<>
  struct X0<void*>::Inner { };

  template<>
  struct X0<int>::Inner { };

  template<>
  struct X0<unsigned>::Inner;

  template<>
  struct X0<float>::Inner;

  template<>
  struct X0<double>::Inner; // expected-note{{forward declaration}}
}

template<>
struct N0::X0<long>::Inner { }; // expected-error{{originally}}

template<>
struct N0::X0<float>::Inner { };

namespace N1 {
  template<>
  struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}

  template<>
  struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
};

N0::X0<void*>::Inner inner0;
N0::X0<int>::Inner inner1;
N0::X0<long>::Inner inner2;
N0::X0<float>::Inner inner3;
N0::X0<double>::Inner inner4; // expected-error{{incomplete}}

#if 0
// FIXME: update the remainder of this test to check for scopes properly.
//    -- member class template of a class template
template<>
template<>
struct X0<void*>::InnerTemplate<int> { };

X0<void*>::InnerTemplate<int> inner_template0;

//    -- member function template of a class template
template<>
template<>
void X0<void*>::ft1(void*, const void*) { }

void test_func_template(X0<void *> xvp, void *vp, const void *cvp) {
  xvp.ft1(vp, cvp);
}
#endif
<commit_msg>More testing for explicit specializations of member class templates<commit_after>// RUN: clang-cc -fsyntax-only -verify %s

// This test creates cases where implicit instantiations of various entities
// would cause a diagnostic, but provides expliict specializations for those
// entities that avoid the diagnostic. The specializations are alternately
// declarations and definitions, and the intent of this test is to verify
// that we allow specializations only in the appropriate namespaces (and
// nowhere else).
struct NonDefaultConstructible {
  NonDefaultConstructible(int);
};

// C++ [temp.expl.spec]p1:
//   An explicit specialization of any of the following:

//     -- function template
namespace N0 {
  template<typename T> void f0(T) { // expected-note{{here}}
    T t;
  }

  template<> void f0(NonDefaultConstructible) { }

  void test_f0(NonDefaultConstructible NDC) {
    f0(NDC);
  }

  template<> void f0(int);
  template<> void f0(long);
}

template<> void N0::f0(int) { } // okay

namespace N1 {
  template<> void N0::f0(long) { } // expected-error{{not in a namespace enclosing}}
}

template<> void N0::f0(double) { } // expected-error{{originally be declared}}

struct X1 {
  template<typename T> void f(T);

  template<> void f(int); // expected-error{{in class scope}}
};

//     -- class template
namespace N0 {

template<typename T>
struct X0 { // expected-note 2{{here}}
  static T member; // expected-note{{here}}

  void f1(T t) { // expected-note{{explicitly specialized declaration is here}}
    t = 17;
  }

  struct Inner : public T { }; // expected-note 3{{here}}

  template<typename U>
  struct InnerTemplate : public T { }; // expected-note 2{{explicitly specialized}} \
   // expected-error{{base specifier}}

  template<typename U>
  void ft1(T t, U u);
};

}

template<typename T>
template<typename U>
void N0::X0<T>::ft1(T t, U u) {
  t = u;
}

template<typename T> T N0::X0<T>::member;

template<> struct N0::X0<void> { }; // expected-error{{originally}}
N0::X0<void> test_X0;

namespace N1 {
  template<> struct N0::X0<const void> { }; // expected-error{{originally}}
}

namespace N0 {
  template<> struct X0<volatile void>;
}

template<> struct N0::X0<volatile void> {
  void f1(void *);
};

//     -- member function of a class template
template<> void N0::X0<void*>::f1(void *) { } // expected-error{{member function specialization}}

void test_spec(N0::X0<void*> xvp, void *vp) {
  xvp.f1(vp);
}

namespace N0 {
  template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}

  template<> void X0<const volatile void*>::f1(const volatile void*);
}

void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
  x0.f1(cvp); // okay: we've explicitly specialized
}

//     -- static data member of a class template
namespace N0 {
  // This actually tests p15; the following is a declaration, not a definition.
  template<>
  NonDefaultConstructible X0<NonDefaultConstructible>::member;

  template<> long X0<long>::member = 17;

  template<> float X0<float>::member;

  template<> double X0<double>::member;
}

NonDefaultConstructible &get_static_member() {
  return N0::X0<NonDefaultConstructible>::member;
}

template<> int N0::X0<int>::member;  // expected-error{{originally}}

template<> float N0::X0<float>::member = 3.14f;

namespace N1 {
  template<> double N0::X0<double>::member = 3.14; // expected-error{{not in a namespace enclosing}}
}

//    -- member class of a class template
namespace N0 {

  template<>
  struct X0<void*>::Inner { };

  template<>
  struct X0<int>::Inner { };

  template<>
  struct X0<unsigned>::Inner;

  template<>
  struct X0<float>::Inner;

  template<>
  struct X0<double>::Inner; // expected-note{{forward declaration}}
}

template<>
struct N0::X0<long>::Inner { }; // expected-error{{originally}}

template<>
struct N0::X0<float>::Inner { };

namespace N1 {
  template<>
  struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}

  template<>
  struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
};

N0::X0<void*>::Inner inner0;
N0::X0<int>::Inner inner1;
N0::X0<long>::Inner inner2;
N0::X0<float>::Inner inner3;
N0::X0<double>::Inner inner4; // expected-error{{incomplete}}

//    -- member class template of a class template
namespace N0 {
  template<>
  template<>
  struct X0<void*>::InnerTemplate<int> { };

  template<> template<>
  struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}

  template<> template<>
  struct X0<int>::InnerTemplate<long>;

  template<> template<>
  struct X0<int>::InnerTemplate<double>;
}

template<> template<>
struct N0::X0<int>::InnerTemplate<long> { }; // okay

template<> template<>
struct N0::X0<int>::InnerTemplate<float> { }; // expected-error{{class template specialization}}

namespace N1 {
  template<> template<>
  struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
}

N0::X0<void*>::InnerTemplate<int> inner_template0;
N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
N0::X0<int>::InnerTemplate<long> inner_template2;
N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}

#if 0
// FIXME: update the remainder of this test to check for scopes properly.
//    -- member function template of a class template
template<>
template<>
void X0<void*>::ft1(void*, const void*) { }

void test_func_template(X0<void *> xvp, void *vp, const void *cvp) {
  xvp.ft1(vp, cvp);
}
#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <iomanip>
#include "../src/forward.h"
#include "../src/util.h"
#include "../src/jsonutil.h"

int main (int argc, char **argv) {
  if (argc != 4 && argc != 5) {
    cout << "Usage: " << argv[0] << " <sequences> <modelfile> <xtime> [<ytime>]\n";
    exit (EXIT_FAILURE);
  }

  vguard<FastSeq> seqs = readFastSeqs (argv[1]);
  Assert (seqs.size() == 2, "Expected two sequences in file %s", argv[1]);

  RateModel rates;
  ifstream in (argv[2]);
  ParsedJson pj (in);
  rates.read (pj.value);

  ProbModel xprobs (rates, atof (argv[3]));
  ProbModel yprobs (rates, atof (argv[argc > 4 ? 4 : 3]));
  gsl_vector* eqm = rates.insProb;
  PairHMM hmm (xprobs, yprobs, eqm);

  Profile xprof (rates.alphabet, seqs[0], 1);
  Profile yprof (rates.alphabet, seqs[1], 2);
  ForwardMatrix forward (xprof, yprof, hmm, 0, GuideAlignmentEnvelope());
  BackwardMatrix backward (forward);

  cout << "Forward score: " << forward.lpEnd << endl;
  cout << "Backward score: " << backward.lpStart() << endl;

  auto bestCells = backward.bestCells (.5);
  while (!bestCells.empty()) {
    cout << "P" << backward.cellName (bestCells.top()) << " = " << exp(bestCells.top().logPostProb) << endl;
    bestCells.pop();
  }

  exit (EXIT_SUCCESS);
}
<commit_msg>updated method name in testbackward<commit_after>#include <iostream>
#include <fstream>
#include <iomanip>
#include "../src/forward.h"
#include "../src/util.h"
#include "../src/jsonutil.h"

int main (int argc, char **argv) {
  if (argc != 4 && argc != 5) {
    cout << "Usage: " << argv[0] << " <sequences> <modelfile> <xtime> [<ytime>]\n";
    exit (EXIT_FAILURE);
  }

  vguard<FastSeq> seqs = readFastSeqs (argv[1]);
  Assert (seqs.size() == 2, "Expected two sequences in file %s", argv[1]);

  RateModel rates;
  ifstream in (argv[2]);
  ParsedJson pj (in);
  rates.read (pj.value);

  ProbModel xprobs (rates, atof (argv[3]));
  ProbModel yprobs (rates, atof (argv[argc > 4 ? 4 : 3]));
  gsl_vector* eqm = rates.insProb;
  PairHMM hmm (xprobs, yprobs, eqm);

  Profile xprof (rates.alphabet, seqs[0], 1);
  Profile yprof (rates.alphabet, seqs[1], 2);
  ForwardMatrix forward (xprof, yprof, hmm, 0, GuideAlignmentEnvelope());
  BackwardMatrix backward (forward);

  cout << "Forward score: " << forward.lpEnd << endl;
  cout << "Backward score: " << backward.lpStart() << endl;

  auto bestCells = backward.cellsAbovePostProbThreshold (.5);
  while (!bestCells.empty()) {
    cout << "P" << backward.cellName (bestCells.top()) << " = " << exp(bestCells.top().logPostProb) << endl;
    bestCells.pop();
  }

  exit (EXIT_SUCCESS);
}
<|endoftext|>


<commit_before>//
//  RewardedAdSceneTester.cpp
//  ee_x_test_mobile
//
//  Created by eps on 10/7/20.
//

#include "RewardedAdSceneTester.hpp"

#include <cocos2d.h>
#include <ui/CocosGUI.h>

#include <ee/AdMob.hpp>
#include <ee/FacebookAds.hpp>
#include <ee/IronSource.hpp>
#include <ee/UnityAds.hpp>

namespace eetest {
namespace config {
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
constexpr auto iron_source_app = "d8d36e59";
constexpr auto unity_ads_app = "3843671";
constexpr auto admob_rewarded_ad = "ca-app-pub-2101587572072038/4784852460";
constexpr auto facebook_ads_rewarded_ad = "1095721240884103_1095725130883714";
#else  // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
constexpr auto iron_source_app = "d8d2fb49";
constexpr auto unity_ads_app = "3843670";
constexpr auto admob_rewarded_ad = "ca-app-pub-2101587572072038/7027872422";
constexpr auto facebook_ads_rewarded_ad = "1095721240884103_1095724794217081";
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
constexpr auto unity_ads_rewarded_ad = "rewardedVideo";
constexpr auto iron_source_rewarded_ad = "0";
} // namespace config

using Self = RewardedAdSceneTester;

Self::RewardedAdSceneTester()
    : scene_(nullptr) {}

void Self::initialize() {
    adMob_ = ee::PluginManager::createPlugin<ee::IAdMob>();
    facebookAds_ = ee::PluginManager::createPlugin<ee::IFacebookAds>();
    ironSource_ = ee::PluginManager::createPlugin<ee::IIronSource>();
    unityAds_ = ee::PluginManager::createPlugin<ee::IUnityAds>();

    adMob_->initialize();
    ironSource_->initialize(config::iron_source_app);
    unityAds_->initialize(config::unity_ads_app, false);

    handle_ = std::make_unique<ee::ObserverHandle>();

    scene_ = cocos2d::Scene::create();
    scene_->retain();

    auto ad = std::make_shared<ee::MultiRewardedAd>();
    (*ad)
        .addItem(adMob_->createRewardedAd(config::admob_rewarded_ad))
        .addItem(
            facebookAds_->createRewardedAd(config::facebook_ads_rewarded_ad))
        .addItem(ironSource_->createRewardedAd(config::iron_source_rewarded_ad))
        .addItem(unityAds_->createRewardedAd(config::unity_ads_rewarded_ad));
    rewardedAd_ = ad;

    auto winSize = cocos2d::Director::getInstance()->getWinSize();

    auto statusLabel = cocos2d::ui::Text::create();
    statusLabel->setContentSize(cocos2d::Size(200, 60));
    statusLabel->setPosition(
        cocos2d::Point(winSize.width / 2, winSize.height / 2 + 100));
    statusLabel->setString("---");

    auto loadButton = cocos2d::ui::Button::create();
    loadButton->setContentSize(cocos2d::Size(150, 80));
    loadButton->setPosition(
        cocos2d::Point(winSize.width / 2, winSize.height / 2 + 50));
    loadButton->setTitleText("Load");
    loadButton->addClickEventListener(std::bind([ad, statusLabel] { //
        if (ad->isLoaded()) {
            statusLabel->setString("Loaded");
        } else {
            ee::noAwait(ad->load());
        }
    }));

    auto resultLabel = cocos2d::ui::Text::create();
    resultLabel->setContentSize(cocos2d::Size(200, 60));
    resultLabel->setPosition(
        cocos2d::Point(winSize.width / 2, winSize.height / 2 - 0));
    resultLabel->setString("---");

    auto watchButton = cocos2d::ui::Button::create();
    watchButton->setContentSize(cocos2d::Size(150, 80));
    watchButton->setPosition(
        cocos2d::Point(winSize.width / 2, winSize.height / 2 - 50));
    watchButton->setTitleText("Watch");
    watchButton->addClickEventListener(
        std::bind([ad, statusLabel, resultLabel] { //
            ee::noAwait([ad, statusLabel, resultLabel]() -> ee::Task<> {
                statusLabel->setString("---");
                auto result = co_await ad->show();
                switch (result) {
                case ee::IRewardedAdResult::Canceled: {
                    resultLabel->setString("Canceled");
                    break;
                }
                case ee::IRewardedAdResult::Completed: {
                    resultLabel->setString("Completed");
                    break;
                }
                case ee::IRewardedAdResult::Failed: {
                    resultLabel->setString("Failed");
                    break;
                }
                }
                if (ad->isLoaded()) {
                    statusLabel->setString("Loaded");
                }
            });
        }));

    scene_->addChild(statusLabel);
    scene_->addChild(loadButton);
    scene_->addChild(resultLabel);
    scene_->addChild(watchButton);

    handle_->bind(*ad).addObserver({
        .onLoaded =
            [statusLabel] { //
                statusLabel->setString("Loaded");
            },
    });
}

void Self::destroy() {
    scene_->release();
    scene_ = nullptr;
}

void Self::start() {
    cocos2d::Director::getInstance()->pushScene(scene_);
}

void Self::stop() {
    cocos2d::Director::getInstance()->popScene();
}
} // namespace eetest
<commit_msg>Fix ironsource placement id.<commit_after>//
//  RewardedAdSceneTester.cpp
//  ee_x_test_mobile
//
//  Created by eps on 10/7/20.
//

#include "RewardedAdSceneTester.hpp"

#include <cocos2d.h>
#include <ui/CocosGUI.h>

#include <ee/AdMob.hpp>
#include <ee/FacebookAds.hpp>
#include <ee/IronSource.hpp>
#include <ee/UnityAds.hpp>

namespace eetest {
namespace config {
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
constexpr auto iron_source_app = "d8d36e59";
constexpr auto unity_ads_app = "3843671";
constexpr auto admob_rewarded_ad = "ca-app-pub-2101587572072038/4784852460";
constexpr auto facebook_ads_rewarded_ad = "1095721240884103_1095725130883714";
#else  // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
constexpr auto iron_source_app = "d8d2fb49";
constexpr auto unity_ads_app = "3843670";
constexpr auto admob_rewarded_ad = "ca-app-pub-2101587572072038/7027872422";
constexpr auto facebook_ads_rewarded_ad = "1095721240884103_1095724794217081";
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
constexpr auto unity_ads_rewarded_ad = "rewardedVideo";
constexpr auto iron_source_rewarded_ad = "DefaultRewardedVideo";
} // namespace config

using Self = RewardedAdSceneTester;

Self::RewardedAdSceneTester()
    : scene_(nullptr) {}

void Self::initialize() {
    adMob_ = ee::PluginManager::createPlugin<ee::IAdMob>();
    facebookAds_ = ee::PluginManager::createPlugin<ee::IFacebookAds>();
    ironSource_ = ee::PluginManager::createPlugin<ee::IIronSource>();
    unityAds_ = ee::PluginManager::createPlugin<ee::IUnityAds>();

    adMob_->initialize();
    ironSource_->initialize(config::iron_source_app);
    unityAds_->initialize(config::unity_ads_app, false);

    handle_ = std::make_unique<ee::ObserverHandle>();

    scene_ = cocos2d::Scene::create();
    scene_->retain();

    auto ad = std::make_shared<ee::MultiRewardedAd>();
    (*ad)
        .addItem(adMob_->createRewardedAd(config::admob_rewarded_ad))
        .addItem(
            facebookAds_->createRewardedAd(config::facebook_ads_rewarded_ad))
        .addItem(ironSource_->createRewardedAd(config::iron_source_rewarded_ad))
        .addItem(unityAds_->createRewardedAd(config::unity_ads_rewarded_ad));
    rewardedAd_ = ad;

    auto winSize = cocos2d::Director::getInstance()->getWinSize();

    auto statusLabel = cocos2d::ui::Text::create();
    statusLabel->setContentSize(cocos2d::Size(200, 60));
    statusLabel->setPosition(
        cocos2d::Point(winSize.width / 2, winSize.height / 2 + 100));
    statusLabel->setString("---");

    auto loadButton = cocos2d::ui::Button::create();
    loadButton->setContentSize(cocos2d::Size(150, 80));
    loadButton->setPosition(
        cocos2d::Point(winSize.width / 2, winSize.height / 2 + 50));
    loadButton->setTitleText("Load");
    loadButton->addClickEventListener(std::bind([ad, statusLabel] { //
        if (ad->isLoaded()) {
            statusLabel->setString("Loaded");
        } else {
            ee::noAwait(ad->load());
        }
    }));

    auto resultLabel = cocos2d::ui::Text::create();
    resultLabel->setContentSize(cocos2d::Size(200, 60));
    resultLabel->setPosition(
        cocos2d::Point(winSize.width / 2, winSize.height / 2 - 0));
    resultLabel->setString("---");

    auto watchButton = cocos2d::ui::Button::create();
    watchButton->setContentSize(cocos2d::Size(150, 80));
    watchButton->setPosition(
        cocos2d::Point(winSize.width / 2, winSize.height / 2 - 50));
    watchButton->setTitleText("Watch");
    watchButton->addClickEventListener(
        std::bind([ad, statusLabel, resultLabel] { //
            ee::noAwait([ad, statusLabel, resultLabel]() -> ee::Task<> {
                statusLabel->setString("---");
                auto result = co_await ad->show();
                switch (result) {
                case ee::IRewardedAdResult::Canceled: {
                    resultLabel->setString("Canceled");
                    break;
                }
                case ee::IRewardedAdResult::Completed: {
                    resultLabel->setString("Completed");
                    break;
                }
                case ee::IRewardedAdResult::Failed: {
                    resultLabel->setString("Failed");
                    break;
                }
                }
                if (ad->isLoaded()) {
                    statusLabel->setString("Loaded");
                }
            });
        }));

    scene_->addChild(statusLabel);
    scene_->addChild(loadButton);
    scene_->addChild(resultLabel);
    scene_->addChild(watchButton);

    handle_->bind(*ad).addObserver({
        .onLoaded =
            [statusLabel] { //
                statusLabel->setString("Loaded");
            },
    });
}

void Self::destroy() {
    scene_->release();
    scene_ = nullptr;
}

void Self::start() {
    cocos2d::Director::getInstance()->pushScene(scene_);
}

void Self::stop() {
    cocos2d::Director::getInstance()->popScene();
}
} // namespace eetest
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: moduledbu.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 16:15:54 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif

#ifndef _TOOLS_RESMGR_HXX
#include <tools/resmgr.hxx>
#endif
#ifndef _SOLAR_HRC
#include <svtools/solar.hrc>
#endif

#define ENTER_MOD_METHOD()  \
    ::osl::MutexGuard aGuard(s_aMutex); \
    ensureImpl()

//.........................................................................
namespace dbaui
{
//.........................................................................

//=========================================================================
//= OModuleImpl
//=========================================================================
/** implementation for <type>OModule</type>. not threadsafe, has to be guarded by it's owner
*/
class OModuleImpl
{
    ResMgr* m_pRessources;

public:
    /// ctor
    OModuleImpl();
    ~OModuleImpl();

    /// get the manager for the ressources of the module
    ResMgr* getResManager();
};

//-------------------------------------------------------------------------
OModuleImpl::OModuleImpl()
    :m_pRessources(NULL)
{
}

//-------------------------------------------------------------------------
OModuleImpl::~OModuleImpl()
{
    if (m_pRessources)
        delete m_pRessources;
}

//-------------------------------------------------------------------------
ResMgr* OModuleImpl::getResManager()
{
    // note that this method is not threadsafe, which counts for the whole class !

    if (!m_pRessources)
    {
        // create a manager with a fixed prefix
        ByteString aMgrName = ByteString( "dbu" );
        aMgrName += ByteString::CreateFromInt32(SOLARUPD); // current build number
        m_pRessources = ResMgr::CreateResMgr(aMgrName.GetBuffer());
    }
    return m_pRessources;
}

//=========================================================================
//= OModule
//=========================================================================
::osl::Mutex    OModule::s_aMutex;
sal_Int32       OModule::s_nClients = 0;
OModuleImpl*    OModule::s_pImpl = NULL;
//-------------------------------------------------------------------------
ResMgr* OModule::getResManager()
{
    ENTER_MOD_METHOD();
    return s_pImpl->getResManager();
}

//-------------------------------------------------------------------------
void OModule::registerClient()
{
    ::osl::MutexGuard aGuard(s_aMutex);
    ++s_nClients;
}

//-------------------------------------------------------------------------
void OModule::revokeClient()
{
    ::osl::MutexGuard aGuard(s_aMutex);
    if (!--s_nClients && s_pImpl)
    {
        delete s_pImpl;
        s_pImpl = NULL;
    }
}

//-------------------------------------------------------------------------
void OModule::ensureImpl()
{
    if (s_pImpl)
        return;
    s_pImpl = new OModuleImpl();
}

//.........................................................................
}   // namespace dbaui
//.........................................................................

<commit_msg>INTEGRATION: CWS dba201b (1.2.376); FILE MERGED 2005/09/21 09:59:46 oj 1.2.376.2: RESYNC: (1.2-1.3); FILE MERGED 2005/07/11 13:37:25 fs 1.2.376.1: merging CWS dba201 into CWS dba201b<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: moduledbu.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2005-09-23 12:41:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif

#ifndef _TOOLS_RESMGR_HXX
#include <tools/resmgr.hxx>
#endif
#ifndef _SOLAR_HRC
#include <svtools/solar.hrc>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#define ENTER_MOD_METHOD()  \
    ::osl::MutexGuard aGuard(s_aMutex); \
    ensureImpl()

//.........................................................................
namespace dbaui
{
//.........................................................................

//=========================================================================
//= OModuleImpl
//=========================================================================
/** implementation for <type>OModule</type>. not threadsafe, has to be guarded by it's owner
*/
class OModuleImpl
{
    ResMgr* m_pRessources;

public:
    /// ctor
    OModuleImpl();
    ~OModuleImpl();

    /// get the manager for the ressources of the module
    ResMgr* getResManager();
};

DBG_NAME(OModuleImpl)
//-------------------------------------------------------------------------
OModuleImpl::OModuleImpl()
    :m_pRessources(NULL)
{
    DBG_CTOR(OModuleImpl,NULL);

}

//-------------------------------------------------------------------------
OModuleImpl::~OModuleImpl()
{
    if (m_pRessources)
        delete m_pRessources;

    DBG_DTOR(OModuleImpl,NULL);
}

//-------------------------------------------------------------------------
ResMgr* OModuleImpl::getResManager()
{
    // note that this method is not threadsafe, which counts for the whole class !

    if (!m_pRessources)
    {
        // create a manager with a fixed prefix
        ByteString aMgrName = ByteString( "dbu" );
        aMgrName += ByteString::CreateFromInt32(SOLARUPD); // current build number
        m_pRessources = ResMgr::CreateResMgr(aMgrName.GetBuffer());
    }
    return m_pRessources;
}

//=========================================================================
//= OModule
//=========================================================================
::osl::Mutex    OModule::s_aMutex;
sal_Int32       OModule::s_nClients = 0;
OModuleImpl*    OModule::s_pImpl = NULL;
//-------------------------------------------------------------------------
ResMgr* OModule::getResManager()
{
    ENTER_MOD_METHOD();
    return s_pImpl->getResManager();
}

//-------------------------------------------------------------------------
void OModule::registerClient()
{
    ::osl::MutexGuard aGuard(s_aMutex);
    ++s_nClients;
}

//-------------------------------------------------------------------------
void OModule::revokeClient()
{
    ::osl::MutexGuard aGuard(s_aMutex);
    if (!--s_nClients && s_pImpl)
    {
        delete s_pImpl;
        s_pImpl = NULL;
    }
}

//-------------------------------------------------------------------------
void OModule::ensureImpl()
{
    if (s_pImpl)
        return;
    s_pImpl = new OModuleImpl();
}

//.........................................................................
}   // namespace dbaui
//.........................................................................

<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 FirstBuild
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <assert.h>
#include <chillduino.h>

int main(void) {
  assert(Chillduino::todo == 42);
  return 0;
}
<commit_msg>Added placeholder for tests<commit_after>/**
 * Copyright (c) 2015 FirstBuild
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <assert.h>
#include "chillduino.h"

int main(void) {
  Chillduino::setup();
  Chillduino::loop();

  return 0;
}
<|endoftext|>


<commit_before>//----------------------------  job_identifier.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 1998, 1999, 2000, 2001 by the deal authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  job_identifier.cc  ---------------------------

#include <base/job_identifier.h>
#include <ctime>

#if HAVE_GETHOSTNAME
# include <unistd.h>
#endif

JobIdentifier dealjobid;

JobIdentifier::JobIdentifier()
{
  time_t t = time(0);
  id = std::string(program_id());

#if HAVE_GETHOSTNAME
  char name[100];
  gethostname(name,99);
  id += std::string(name) + std::string(" ");
#endif

  id += std::string(ctime(&t));
}

const std::string
JobIdentifier::operator ()() const
{
  return id;
}

<commit_msg>Avoid gethostname in debug mode, since Linux does not know it wth -ansi<commit_after>//----------------------------  job_identifier.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 1998, 1999, 2000, 2001 by the deal authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  job_identifier.cc  ---------------------------

#include <base/job_identifier.h>
#include <ctime>

#if HAVE_GETHOSTNAME
# include <unistd.h>
#endif

JobIdentifier dealjobid;

JobIdentifier::JobIdentifier()
{
  time_t t = time(0);
  id = std::string(program_id());

//TODO:[GK] try to avoid this hack

#if (HAVE_GETHOSTNAME && (!DEBUG))
  char name[100];
  gethostname(name,99);
  id += std::string(name) + std::string(" ");
#endif

  id += std::string(ctime(&t));
}

const std::string
JobIdentifier::operator ()() const
{
  return id;
}

<|endoftext|>


<commit_before>#include "pch.h"
#include "tracker_service.h"
#include "service_manager.h"
#include "main.h"
#include "curl/curl.h"

bool TrackerService::_threadForceQuit = false;
int TrackerService::_dispatchPeriod = 1000;
int TrackerService::_dispatchRate = 1;
std::auto_ptr< std::thread > TrackerService::_dispatchThread;

TrackerService::TrackerService(const ServiceManager * manager)
    : Service(manager)
    , _trackingId()
    , _clientId()
    , _protocolVersion(1)
    , _curl(NULL)
    , _allowDispatch(true)
    , _sessionStartTime(0)
    , _lastPayloadSentTime(0)
{
    memset(_customMetrics, 0, sizeof(_customMetrics));
    time(&_trackerStartTime);
}

TrackerService::~TrackerService()
{
}

static char errorBuffer[CURL_ERROR_SIZE];
void TrackerService::setupTracking(const char * gaAppId, const char * clientId, const char * startScreen)
{
    _trackingId = gaAppId;
    _clientId = clientId;

    _appName = urlEncode(gameplay::Game::getInstance()->getConfig()->getNamespace("window", true)->getString("title"));
    _appVersion = urlEncode(gameplay::Game::getInstance()->getConfig()->getNamespace("window", true)->getString("version"));

    // load previously saved payloads which weren't sent to server
    std::string filename = std::string(static_cast<DfgGame *>(gameplay::Game::getInstance())->getUserDataFolder()) + "/payloads.dat";
    gameplay::Stream * stream(gameplay::FileSystem::open(filename.c_str(), gameplay::FileSystem::READ));

    if (stream)
    {
        int version = 0;
        stream->read(&version, sizeof(version), 1);

        if (version == 1)
        {
            time_t lastTrackerStartTime;
            stream->read(&lastTrackerStartTime, sizeof(lastTrackerStartTime), 1);

            int32_t payloadsCount = 0;
            stream->read(&payloadsCount, sizeof(payloadsCount), 1);

            int payloadDiffInSeconds = static_cast<int>(difftime(_trackerStartTime, lastTrackerStartTime));

            for (int i = 0; i < payloadsCount; i++)
            {
                int size = 0;

                stream->read(&size, sizeof(size), 1);

                char * str = reinterpret_cast<char *>(alloca(size + 1));
                stream->read(str, size, 1);
                str[size] = '\0';

                PayloadInfo payload;
                payload.params = str;

                stream->read(&payload.createTime, sizeof(payload.createTime), 1);

                // adjust payload's createTime by diff between runs
                payload.createTime -= static_cast<float>(payloadDiffInSeconds * 1000.0f);

                // filter out too old payloads (older thah 4h)
                if (payload.createTime > -4.0f * 3600.0f * 1000.0f)
                    _payloadsQueue.push_back(payload);
            }
        }

        SAFE_DELETE(stream);
    }

    _curl = curl_easy_init();
    if (_curl)
    {
        const char * endpoint = "http://www.google-analytics.com/collect";
        curl_easy_setopt(_curl, CURLOPT_URL, endpoint);
        curl_easy_setopt(_curl, CURLOPT_POST, 1);
        curl_easy_setopt(_curl, CURLOPT_USERAGENT, gameplay::Game::getInstance()->getUserAgentString());
        //curl_easy_setopt( _curl, CURLOPT_DNS_CACHE_TIMEOUT, -1 );
        curl_easy_setopt(_curl, CURLOPT_NOSIGNAL, 1);
        curl_easy_setopt(_curl, CURLOPT_TIMEOUT, 4);
        curl_easy_setopt(_curl, CURLOPT_CONNECTTIMEOUT, 2);
        curl_easy_setopt(_curl, CURLOPT_ERRORBUFFER, errorBuffer);
        curl_easy_setopt(_curl, CURLOPT_TCP_NODELAY, 1);  // make sure packets are sent immediately
    }

    if (!_payloadsQueue.empty())
    {
        // make sure previous session is ended
        endSession();
    }

    _currentView = urlEncode(startScreen);
    sendData("t=appview&cd=%s",
        _currentView.c_str()
        );
}

bool TrackerService::onInit()
{
    _dispatchThread.reset(new std::thread(&TrackerService::dispatchThreadProc, this));
    return true;
}

bool TrackerService::onShutdown()
{
    // try to empty payloads queue, thread will exit right after sleep.
    endSession();

    if (_dispatchThread.get())
    {
        _dispatchMutex.lock();
        _threadForceQuit = true;
        _dispatchMutex.unlock();
        _dispatchThread->join();
    }

    if (_curl)
        curl_easy_cleanup(_curl);

    _payloadsQueue.clear();

    return true;
}

void TrackerService::flushPayloads()
{
    std::string filename = std::string(static_cast<DfgGame *>(gameplay::Game::getInstance())->getUserDataFolder()) + "/payloads.dat";
    gameplay::Stream * stream(gameplay::FileSystem::open(filename.c_str(), gameplay::FileSystem::WRITE));

    if (stream)
    {
        int version = 1;
        stream->write(&version, sizeof(version), 1);
        stream->write(&_trackerStartTime, sizeof(_trackerStartTime), 1);

        int maxPayloadsToStore = std::min< int >(1024, static_cast<int>(_payloadsQueue.size()));
        stream->write(&maxPayloadsToStore, sizeof(maxPayloadsToStore), 1);
        _payloadQueueMutex.lock();
        std::deque< PayloadInfo >::iterator it = _payloadsQueue.begin();
        while (maxPayloadsToStore-- > 0)
        {
            GP_ASSERT(it != _payloadsQueue.end());
            const PayloadInfo& payload = *it;

            int32_t size = static_cast<int32_t>(payload.params.size());
            stream->write(&size, sizeof(size), 1);
            stream->write(payload.params.c_str(), size, 1);
            stream->write(&payload.createTime, sizeof(payload.createTime), 1);

            it++;
        }
        _payloadQueueMutex.unlock();

        SAFE_DELETE(stream);
    }
}

bool TrackerService::onTick()
{
    return false; // as long as service is active dispatch thread is working
}

void TrackerService::forceDispatch(int dispatchCount)
{
    _dispatchMutex.lock();

    // if thread is forced to quit, _payloadsQueue may be invalid
    if (_threadForceQuit)
    {
        _dispatchMutex.unlock();
        return;
    }

    bool flushAll = dispatchCount == 0;
    dispatchCount = std::min< int >(dispatchCount, static_cast<int>(_payloadsQueue.size()) - 1);
    while (flushAll && !_payloadsQueue.empty() || dispatchCount > 0)
    {
        // get a copy of payload because queue can be modified in another thread
        PayloadInfo payload = _payloadsQueue.front();

        if (!dispatch(payload))
            break;

        _payloadQueueMutex.lock();
        _payloadsQueue.pop_front();
        _payloadQueueMutex.unlock();

        dispatchCount--;
    }
    _dispatchMutex.unlock();
}

void TrackerService::endSession()
{
    if (!_payloadsQueue.empty() && _payloadsQueue.back().params.find("&sc=end") == _payloadsQueue.back().params.npos)
        _payloadsQueue.back().params += "&sc=end";

    forceDispatch(0);

    _dispatchMutex.lock();
    _sessionStartTime = 0;
    _dispatchMutex.unlock();

    // if payload queue still not empty (e.g., internet connection was lost)
    // store it offline to send payloads on next run
    flushPayloads();
}

bool TrackerService::dispatch(const PayloadInfo& payload)
{
    if (!_allowDispatch)
        return false;

    static char finalRequest[4096];
    float curTime = static_cast<float>(gameplay::Game::getInstance()->getAbsoluteTime());

    int timeDiff = static_cast<int>(curTime - payload.createTime);
    sprintf(finalRequest, "v=%d&tid=%s&cid=%s&an=%s&av=%s&%s",
        _protocolVersion, _trackingId.c_str(), _clientId.c_str(),
        _appName.c_str(),
        _appVersion.c_str(),
        payload.params.c_str());

    // reset session when time between payloads passed midnight
    time_t time1 = _trackerStartTime + static_cast<int>(_lastPayloadSentTime * 0.001f);
    time_t time2 = _trackerStartTime + static_cast<int>(curTime * 0.001f);
    int day1 = localtime(&time1)->tm_mday;
    int day2 = localtime(&time2)->tm_mday;

    if (payload.createTime >= 0 &&
        (_sessionStartTime <= 0
        || (payload.createTime - _sessionStartTime) > 240.0f * 60.0f * 1000.0f     // sessions in GA are automaticaly ended after some period of time
        || day1 != day2)
        )
    {
        // send language and resolution for first payload
        // assuming the first payload starts a session
        int width = gameplay::Game::getInstance()->getWidth();
        int height = gameplay::Game::getInstance()->getHeight();

        sprintf(finalRequest, "%s&sr=%dx%d&ul=%s&sc=start",
            finalRequest,
            width, height,
            static_cast<DfgGame *>(gameplay::Game::getInstance())->getGameLocale()
            );
    }

    if (timeDiff > 0)
        sprintf(finalRequest, "%s&qt=%d",
        finalRequest,
        timeDiff
        );

    curl_easy_setopt(_curl, CURLOPT_POSTFIELDS, finalRequest);
    CURLcode res = curl_easy_perform(_curl);

    if (res == CURLE_OK)
    {
        if (_sessionStartTime <= 0)
            _sessionStartTime = payload.createTime;

        _lastPayloadSentTime = payload.createTime;
    }

#ifdef _DEBUG
    time_t seconds;
    time(&seconds);
    tm * t = localtime(&seconds);

    gameplay::Logger::log(gameplay::Logger::LEVEL_INFO,
        "%02d-%02d-%02d %02d:%02d:%02d %08d %08d GA: %s - %d\n",
        t->tm_mon + 1, t->tm_mday, t->tm_year % 100, t->tm_hour, t->tm_min, t->tm_sec,
        static_cast<int>(curTime), static_cast<int>(payload.createTime), finalRequest, res);

    GP_ASSERT(abs(static_cast<int>(curTime)-timeDiff - static_cast<int>(payload.createTime)) < 2);
#endif

    return res == CURLE_OK;
}

void TrackerService::sendView(const char * screenName)
{
    if (_currentView == screenName)
        return;

    _currentView = urlEncode(screenName);
    sendData("t=appview&cd=%s", _currentView.c_str());
}

void TrackerService::sendEvent(const char * category, const char * action, const char * label, const int& value, bool interactive)
{
    sendData("t=event&ec=%s&ea=%s&el=%s&ev=%u&ni=%d&cd=%s",
        urlEncode(category),
        urlEncode(action),
        urlEncode(label),
        value,
        interactive ? 0 : 1,
        _currentView.c_str()
        );
}

void TrackerService::sendSocialEvent(const char * network, const char * action, const char * target)
{
    sendData("t=social&sn=%s&sa=%s&st=%s&cd=%s",
        urlEncode(network),
        urlEncode(action),
        urlEncode(target),
        _currentView.c_str()
        );
}

void TrackerService::sendTiming(const char * category, const int& timeMs, const char * name, const char * label)
{
    sendData("t=timing&utc=%s&utv=%s&utt=%d&utl=%s&cd=%s",
        urlEncode(category),
        name == NULL ? "" : urlEncode(name),
        timeMs,
        label == NULL ? "" : urlEncode(label),
        _currentView.c_str()
        );
}

void TrackerService::sendException(const char * type, bool isFatal)
{
    sendData("t=exception&exd=%s&exf=%d&cd=%s",
        urlEncode(type),
        isFatal ? 1 : 0,
        _currentView.c_str()
        );
}

void TrackerService::sendTransaction(const char * transactionID, const char * store, float totalRevenue, float shippingCost, float tax, const char * currencyCode)
{
    sendData("t=transaction&ti=%s&ta=%s&tr=%.2f&ts=%.2f&tt=%.2f&cu=%s",
        urlEncode(transactionID),
        urlEncode(store),
        totalRevenue,
        shippingCost,
        tax,
        urlEncode(currencyCode)
        );
}

void TrackerService::sendItem(const char * transactionID, const char * name, float price, int quantity, const char * sku, const char * category, const char * currencyCode)
{
    sendData("t=item&ti=%s&in=%s&ip=%.2f&iq=%d&ic=%s&iv=%s&cu=%s",
        urlEncode(transactionID),
        urlEncode(name),
        price,
        quantity,
        urlEncode(sku),
        urlEncode(category),
        urlEncode(currencyCode)
        );
}

void TrackerService::setCustomDimension(const int& id, const char * dimension)
{
    if (id < 0 || id > MAX_CUSTOM_DIMENSIONS)
        return;

    _customDimensions[id] = dimension;
}

void TrackerService::setCustomMetric(const int& id, const int& metric)
{
    if (id < 0 || id > MAX_CUSTOM_METRICS)
        return;

    _customMetrics[id] = metric;
}

void TrackerService::sendData(const char * format, ...)
{
    va_list args;
    va_start(args, format);

    char request[4096];
    vsnprintf(request, 4095, format, args);
    request[4095] = '\0';

    int i;
    for (i = 0; i < MAX_CUSTOM_DIMENSIONS; i++)
        if (!_customDimensions[i].empty())
        {
            char buf[256];
            sprintf(buf, "&cd%d=%s", i + 1, urlEncode(_customDimensions[i].c_str()));
            strncat(request, buf, 4095);
        }

    for (i = 0; i < MAX_CUSTOM_METRICS; i++)
        if (_customMetrics[i] > 0)
        {
            char buf[256];
            sprintf(buf, "&cm%d=%d", i + 1, _customMetrics[i]);
            strncat(request, buf, 4095);
        }

    PayloadInfo payload;
    payload.params = request;
    payload.createTime = static_cast<float>(gameplay::Game::getInstance()->getAbsoluteTime());

    _payloadQueueMutex.lock();
    _payloadsQueue.push_back(payload);
    _payloadQueueMutex.unlock();

    memset(_customMetrics, 0, sizeof(_customMetrics));
    for (i = 0; i < MAX_CUSTOM_DIMENSIONS; i++)
        _customDimensions[i].clear();
}

const char * TrackerService::urlEncode(const char * str)
{
    static std::string res[16];
    static int resInd = 0;
    char * escapedStr = curl_easy_escape(_curl, str, static_cast<int>(strlen(str)));
    res[resInd] = escapedStr;
    const char * resStr = res[resInd].c_str();
    resInd = (resInd + 1) & 15;

    curl_free(escapedStr);

    return resStr;
}

void TrackerService::dispatchThreadProc(void * arg)
{
    TrackerService * _this = reinterpret_cast<TrackerService *>(arg);

    if (!_this->_curl)
        return;

    while (!_this->_threadForceQuit && (_this->getState() == Service::INITIALIZING || _this->getState() == Service::RUNNING))
    {
        _this->forceDispatch(_this->_dispatchRate);
        std::this_thread::sleep_for(std::chrono::milliseconds(_this->_dispatchPeriod));
    }
}<commit_msg>fixed invalid comparison for current view in TrackerService (one view could be sent several times in a row)<commit_after>#include "pch.h"
#include "tracker_service.h"
#include "service_manager.h"
#include "main.h"
#include "curl/curl.h"

bool TrackerService::_threadForceQuit = false;
int TrackerService::_dispatchPeriod = 1000;
int TrackerService::_dispatchRate = 1;
std::auto_ptr< std::thread > TrackerService::_dispatchThread;

TrackerService::TrackerService(const ServiceManager * manager)
    : Service(manager)
    , _trackingId()
    , _clientId()
    , _protocolVersion(1)
    , _curl(NULL)
    , _allowDispatch(true)
    , _sessionStartTime(0)
    , _lastPayloadSentTime(0)
{
    memset(_customMetrics, 0, sizeof(_customMetrics));
    time(&_trackerStartTime);
}

TrackerService::~TrackerService()
{
}

static char errorBuffer[CURL_ERROR_SIZE];
void TrackerService::setupTracking(const char * gaAppId, const char * clientId, const char * startScreen)
{
    _trackingId = gaAppId;
    _clientId = clientId;

    _appName = urlEncode(gameplay::Game::getInstance()->getConfig()->getNamespace("window", true)->getString("title"));
    _appVersion = urlEncode(gameplay::Game::getInstance()->getConfig()->getNamespace("window", true)->getString("version"));

    // load previously saved payloads which weren't sent to server
    std::string filename = std::string(static_cast<DfgGame *>(gameplay::Game::getInstance())->getUserDataFolder()) + "/payloads.dat";
    gameplay::Stream * stream(gameplay::FileSystem::open(filename.c_str(), gameplay::FileSystem::READ));

    if (stream)
    {
        int version = 0;
        stream->read(&version, sizeof(version), 1);

        if (version == 1)
        {
            time_t lastTrackerStartTime;
            stream->read(&lastTrackerStartTime, sizeof(lastTrackerStartTime), 1);

            int32_t payloadsCount = 0;
            stream->read(&payloadsCount, sizeof(payloadsCount), 1);

            int payloadDiffInSeconds = static_cast<int>(difftime(_trackerStartTime, lastTrackerStartTime));

            for (int i = 0; i < payloadsCount; i++)
            {
                int size = 0;

                stream->read(&size, sizeof(size), 1);

                char * str = reinterpret_cast<char *>(alloca(size + 1));
                stream->read(str, size, 1);
                str[size] = '\0';

                PayloadInfo payload;
                payload.params = str;

                stream->read(&payload.createTime, sizeof(payload.createTime), 1);

                // adjust payload's createTime by diff between runs
                payload.createTime -= static_cast<float>(payloadDiffInSeconds * 1000.0f);

                // filter out too old payloads (older thah 4h)
                if (payload.createTime > -4.0f * 3600.0f * 1000.0f)
                    _payloadsQueue.push_back(payload);
            }
        }

        SAFE_DELETE(stream);
    }

    _curl = curl_easy_init();
    if (_curl)
    {
        const char * endpoint = "http://www.google-analytics.com/collect";
        curl_easy_setopt(_curl, CURLOPT_URL, endpoint);
        curl_easy_setopt(_curl, CURLOPT_POST, 1);
        curl_easy_setopt(_curl, CURLOPT_USERAGENT, gameplay::Game::getInstance()->getUserAgentString());
        //curl_easy_setopt( _curl, CURLOPT_DNS_CACHE_TIMEOUT, -1 );
        curl_easy_setopt(_curl, CURLOPT_NOSIGNAL, 1);
        curl_easy_setopt(_curl, CURLOPT_TIMEOUT, 4);
        curl_easy_setopt(_curl, CURLOPT_CONNECTTIMEOUT, 2);
        curl_easy_setopt(_curl, CURLOPT_ERRORBUFFER, errorBuffer);
        curl_easy_setopt(_curl, CURLOPT_TCP_NODELAY, 1);  // make sure packets are sent immediately
    }

    if (!_payloadsQueue.empty())
    {
        // make sure previous session is ended
        endSession();
    }

    _currentView = urlEncode(startScreen);
    sendData("t=appview&cd=%s",
        _currentView.c_str()
        );
}

bool TrackerService::onInit()
{
    _dispatchThread.reset(new std::thread(&TrackerService::dispatchThreadProc, this));
    return true;
}

bool TrackerService::onShutdown()
{
    // try to empty payloads queue, thread will exit right after sleep.
    endSession();

    if (_dispatchThread.get())
    {
        _dispatchMutex.lock();
        _threadForceQuit = true;
        _dispatchMutex.unlock();
        _dispatchThread->join();
    }

    if (_curl)
        curl_easy_cleanup(_curl);

    _payloadsQueue.clear();

    return true;
}

void TrackerService::flushPayloads()
{
    std::string filename = std::string(static_cast<DfgGame *>(gameplay::Game::getInstance())->getUserDataFolder()) + "/payloads.dat";
    gameplay::Stream * stream(gameplay::FileSystem::open(filename.c_str(), gameplay::FileSystem::WRITE));

    if (stream)
    {
        int version = 1;
        stream->write(&version, sizeof(version), 1);
        stream->write(&_trackerStartTime, sizeof(_trackerStartTime), 1);

        int maxPayloadsToStore = std::min< int >(1024, static_cast<int>(_payloadsQueue.size()));
        stream->write(&maxPayloadsToStore, sizeof(maxPayloadsToStore), 1);
        _payloadQueueMutex.lock();
        std::deque< PayloadInfo >::iterator it = _payloadsQueue.begin();
        while (maxPayloadsToStore-- > 0)
        {
            GP_ASSERT(it != _payloadsQueue.end());
            const PayloadInfo& payload = *it;

            int32_t size = static_cast<int32_t>(payload.params.size());
            stream->write(&size, sizeof(size), 1);
            stream->write(payload.params.c_str(), size, 1);
            stream->write(&payload.createTime, sizeof(payload.createTime), 1);

            it++;
        }
        _payloadQueueMutex.unlock();

        SAFE_DELETE(stream);
    }
}

bool TrackerService::onTick()
{
    return false; // as long as service is active dispatch thread is working
}

void TrackerService::forceDispatch(int dispatchCount)
{
    _dispatchMutex.lock();

    // if thread is forced to quit, _payloadsQueue may be invalid
    if (_threadForceQuit)
    {
        _dispatchMutex.unlock();
        return;
    }

    bool flushAll = dispatchCount == 0;
    dispatchCount = std::min< int >(dispatchCount, static_cast<int>(_payloadsQueue.size()) - 1);
    while (flushAll && !_payloadsQueue.empty() || dispatchCount > 0)
    {
        // get a copy of payload because queue can be modified in another thread
        PayloadInfo payload = _payloadsQueue.front();

        if (!dispatch(payload))
            break;

        _payloadQueueMutex.lock();
        _payloadsQueue.pop_front();
        _payloadQueueMutex.unlock();

        dispatchCount--;
    }
    _dispatchMutex.unlock();
}

void TrackerService::endSession()
{
    if (!_payloadsQueue.empty() && _payloadsQueue.back().params.find("&sc=end") == _payloadsQueue.back().params.npos)
        _payloadsQueue.back().params += "&sc=end";

    forceDispatch(0);

    _dispatchMutex.lock();
    _sessionStartTime = 0;
    _dispatchMutex.unlock();

    // if payload queue still not empty (e.g., internet connection was lost)
    // store it offline to send payloads on next run
    flushPayloads();
}

bool TrackerService::dispatch(const PayloadInfo& payload)
{
    if (!_allowDispatch)
        return false;

    static char finalRequest[4096];
    float curTime = static_cast<float>(gameplay::Game::getInstance()->getAbsoluteTime());

    int timeDiff = static_cast<int>(curTime - payload.createTime);
    sprintf(finalRequest, "v=%d&tid=%s&cid=%s&an=%s&av=%s&%s",
        _protocolVersion, _trackingId.c_str(), _clientId.c_str(),
        _appName.c_str(),
        _appVersion.c_str(),
        payload.params.c_str());

    // reset session when time between payloads passed midnight
    time_t time1 = _trackerStartTime + static_cast<int>(_lastPayloadSentTime * 0.001f);
    time_t time2 = _trackerStartTime + static_cast<int>(curTime * 0.001f);
    int day1 = localtime(&time1)->tm_mday;
    int day2 = localtime(&time2)->tm_mday;

    if (payload.createTime >= 0 &&
        (_sessionStartTime <= 0
        || (payload.createTime - _sessionStartTime) > 240.0f * 60.0f * 1000.0f     // sessions in GA are automaticaly ended after some period of time
        || day1 != day2)
        )
    {
        // send language and resolution for first payload
        // assuming the first payload starts a session
        int width = gameplay::Game::getInstance()->getWidth();
        int height = gameplay::Game::getInstance()->getHeight();

        sprintf(finalRequest, "%s&sr=%dx%d&ul=%s&sc=start",
            finalRequest,
            width, height,
            static_cast<DfgGame *>(gameplay::Game::getInstance())->getGameLocale()
            );
    }

    if (timeDiff > 0)
        sprintf(finalRequest, "%s&qt=%d",
        finalRequest,
        timeDiff
        );

    curl_easy_setopt(_curl, CURLOPT_POSTFIELDS, finalRequest);
    CURLcode res = curl_easy_perform(_curl);

    if (res == CURLE_OK)
    {
        if (_sessionStartTime <= 0)
            _sessionStartTime = payload.createTime;

        _lastPayloadSentTime = payload.createTime;
    }

#ifdef _DEBUG
    time_t seconds;
    time(&seconds);
    tm * t = localtime(&seconds);

    gameplay::Logger::log(gameplay::Logger::LEVEL_INFO,
        "%02d-%02d-%02d %02d:%02d:%02d %08d %08d GA: %s - %d\n",
        t->tm_mon + 1, t->tm_mday, t->tm_year % 100, t->tm_hour, t->tm_min, t->tm_sec,
        static_cast<int>(curTime), static_cast<int>(payload.createTime), finalRequest, res);

    GP_ASSERT(abs(static_cast<int>(curTime)-timeDiff - static_cast<int>(payload.createTime)) < 2);
#endif

    return res == CURLE_OK;
}

void TrackerService::sendView(const char * screenName)
{
    std::string newView(urlEncode(screenName));
    if (_currentView == newView)
        return;

    _currentView = newView;
    sendData("t=appview&cd=%s", _currentView.c_str());
}

void TrackerService::sendEvent(const char * category, const char * action, const char * label, const int& value, bool interactive)
{
    sendData("t=event&ec=%s&ea=%s&el=%s&ev=%u&ni=%d&cd=%s",
        urlEncode(category),
        urlEncode(action),
        urlEncode(label),
        value,
        interactive ? 0 : 1,
        _currentView.c_str()
        );
}

void TrackerService::sendSocialEvent(const char * network, const char * action, const char * target)
{
    sendData("t=social&sn=%s&sa=%s&st=%s&cd=%s",
        urlEncode(network),
        urlEncode(action),
        urlEncode(target),
        _currentView.c_str()
        );
}

void TrackerService::sendTiming(const char * category, const int& timeMs, const char * name, const char * label)
{
    sendData("t=timing&utc=%s&utv=%s&utt=%d&utl=%s&cd=%s",
        urlEncode(category),
        name == NULL ? "" : urlEncode(name),
        timeMs,
        label == NULL ? "" : urlEncode(label),
        _currentView.c_str()
        );
}

void TrackerService::sendException(const char * type, bool isFatal)
{
    sendData("t=exception&exd=%s&exf=%d&cd=%s",
        urlEncode(type),
        isFatal ? 1 : 0,
        _currentView.c_str()
        );
}

void TrackerService::sendTransaction(const char * transactionID, const char * store, float totalRevenue, float shippingCost, float tax, const char * currencyCode)
{
    sendData("t=transaction&ti=%s&ta=%s&tr=%.2f&ts=%.2f&tt=%.2f&cu=%s",
        urlEncode(transactionID),
        urlEncode(store),
        totalRevenue,
        shippingCost,
        tax,
        urlEncode(currencyCode)
        );
}

void TrackerService::sendItem(const char * transactionID, const char * name, float price, int quantity, const char * sku, const char * category, const char * currencyCode)
{
    sendData("t=item&ti=%s&in=%s&ip=%.2f&iq=%d&ic=%s&iv=%s&cu=%s",
        urlEncode(transactionID),
        urlEncode(name),
        price,
        quantity,
        urlEncode(sku),
        urlEncode(category),
        urlEncode(currencyCode)
        );
}

void TrackerService::setCustomDimension(const int& id, const char * dimension)
{
    if (id < 0 || id > MAX_CUSTOM_DIMENSIONS)
        return;

    _customDimensions[id] = dimension;
}

void TrackerService::setCustomMetric(const int& id, const int& metric)
{
    if (id < 0 || id > MAX_CUSTOM_METRICS)
        return;

    _customMetrics[id] = metric;
}

void TrackerService::sendData(const char * format, ...)
{
    va_list args;
    va_start(args, format);

    char request[4096];
    vsnprintf(request, 4095, format, args);
    request[4095] = '\0';

    int i;
    for (i = 0; i < MAX_CUSTOM_DIMENSIONS; i++)
        if (!_customDimensions[i].empty())
        {
            char buf[256];
            sprintf(buf, "&cd%d=%s", i + 1, urlEncode(_customDimensions[i].c_str()));
            strncat(request, buf, 4095);
        }

    for (i = 0; i < MAX_CUSTOM_METRICS; i++)
        if (_customMetrics[i] > 0)
        {
            char buf[256];
            sprintf(buf, "&cm%d=%d", i + 1, _customMetrics[i]);
            strncat(request, buf, 4095);
        }

    PayloadInfo payload;
    payload.params = request;
    payload.createTime = static_cast<float>(gameplay::Game::getInstance()->getAbsoluteTime());

    _payloadQueueMutex.lock();
    _payloadsQueue.push_back(payload);
    _payloadQueueMutex.unlock();

    memset(_customMetrics, 0, sizeof(_customMetrics));
    for (i = 0; i < MAX_CUSTOM_DIMENSIONS; i++)
        _customDimensions[i].clear();
}

const char * TrackerService::urlEncode(const char * str)
{
    static std::string res[16];
    static int resInd = 0;
    char * escapedStr = curl_easy_escape(_curl, str, static_cast<int>(strlen(str)));
    res[resInd] = escapedStr;
    const char * resStr = res[resInd].c_str();
    resInd = (resInd + 1) & 15;

    curl_free(escapedStr);

    return resStr;
}

void TrackerService::dispatchThreadProc(void * arg)
{
    TrackerService * _this = reinterpret_cast<TrackerService *>(arg);

    if (!_this->_curl)
        return;

    while (!_this->_threadForceQuit && (_this->getState() == Service::INITIALIZING || _this->getState() == Service::RUNNING))
    {
        _this->forceDispatch(_this->_dispatchRate);
        std::this_thread::sleep_for(std::chrono::milliseconds(_this->_dispatchPeriod));
    }
}<|endoftext|>


<commit_before><commit_msg>Add new test cases to ionComparison<commit_after><|endoftext|>


<commit_before>/**************************************************************************
 * The MIT License                                                        *
 * Copyright (c) 2013 Antony Arciuolo.                                    *
 * arciuolo@gmail.com                                                     *
 *                                                                        *
 * Permission is hereby granted, free of charge, to any person obtaining  *
 * a copy of this software and associated documentation files (the        *
 * "Software"), to deal in the Software without restriction, including    *
 * without limitation the rights to use, copy, modify, merge, publish,    *
 * distribute, sublicense, and/or sell copies of the Software, and to     *
 * permit persons to whom the Software is furnished to do so, subject to  *
 * the following conditions:                                              *
 *                                                                        *
 * The above copyright notice and this permission notice shall be         *
 * included in all copies or substantial portions of the Software.        *
 *                                                                        *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        *
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     *
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                  *
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE *
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION *
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  *
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        *
 **************************************************************************/
#include <oGPU/oGPUUtil.h>
#include <oBase/finally.h>

namespace ouro {
	namespace gpu {

void commit_buffer(command_list* _pCommandList, buffer* _pBuffer, const void* _pStruct, uint _SizeofStruct, uint _NumStructs)
{
	oCHECK(byte_aligned(_SizeofStruct, 16), "structs must be aligned to 16 bytes (%u bytes specified %.02f of alignment)", _SizeofStruct, _SizeofStruct / 16.0f);
	surface::mapped_subresource msr;
	msr.data = const_cast<void*>(_pStruct);
	msr.row_pitch = _SizeofStruct;
	msr.depth_pitch = _NumStructs * _SizeofStruct;
	_pCommandList->commit(_pBuffer, 0, msr);
}

void commit_buffer(device* _pDevice, buffer* _pBuffer, const void* _pStruct, uint _SizeofStruct, uint _NumStructs)
{
	oCHECK(byte_aligned(_SizeofStruct, 16), "structs must be aligned to 16 bytes (%u bytes specified %.02f of alignment)", _SizeofStruct, _SizeofStruct / 16.0f);
	surface::mapped_subresource msr;
	msr.data = const_cast<void*>(_pStruct);
	msr.row_pitch = _SizeofStruct;
	msr.depth_pitch = _NumStructs * _SizeofStruct;
	_pDevice->immediate()->commit(_pBuffer, 0, msr);
}

#if 0
std::shared_ptr<buffer> make_readback_copy(buffer* _pSource)
{
	std::shared_ptr<device> Device = _pSource->get_device();
	buffer_info i = _pSource->get_info();
	i.type = buffer_type::readback;
	sstring Name;
	snprintf(Name, "%s.Readback", _pSource->name());
	return Device->make_buffer(Name, i);
}

std::shared_ptr<texture> make_readback_copy(texture* _pSource)
{
	std::shared_ptr<device> Device = _pSource->get_device();
	texture_info i = _pSource->get_info();
	i.type = make_readback(i.type);
	sstring Name;
	snprintf(Name, "%s.Readback", _pSource->name());
	return Device->make_texture(Name, i);
}
#endif

uint read_back_counter(buffer* _pUnorderedBuffer, buffer* _pPreallocatedReadbackBuffer)
{
	buffer_info i = _pUnorderedBuffer->get_info();
	if (i.type != buffer_type::unordered_structured_append && i.type != buffer_type::unordered_structured_counter)
		oTHROW_INVARG("the specified buffer must be of type buffer_type::unordered_structured_append or buffer_type::unordered_structured_counter");

	std::shared_ptr<device> Device = _pUnorderedBuffer->get_device();

	std::shared_ptr<buffer> CounterBuffer;
	buffer* Counter = _pPreallocatedReadbackBuffer;
	if (!Counter)
	{
		sstring Name;
		snprintf(Name, "%s.Readback", _pUnorderedBuffer->name());

		buffer_info rb;
		rb.type = buffer_type::readback;
		rb.struct_byte_size = sizeof(uint);

		CounterBuffer = Device->make_buffer(Name, rb);
		Counter = CounterBuffer.get();
	}

	Device->immediate()->copy_counter(Counter, 0, _pUnorderedBuffer);

	surface::mapped_subresource msr;
	if (!Device->map_read(Counter, 0, &msr, true))
		return invalid; // pass through error
	uint c = *(uint*)msr.data;
	Device->unmap_read(Counter, 0);
	return c;
}

bool read(resource* _pSourceResource, int _Subresource, surface::mapped_subresource& _Destination, bool _FlipVertically)
{
	std::shared_ptr<device> Device = _pSourceResource->get_device();

	switch (_pSourceResource->type())
	{
		case resource_type::buffer:
		{
			buffer_info i = static_cast<buffer*>(_pSourceResource)->get_info();
			if (i.type != buffer_type::readback)
				oTHROW_INVARG("The specified resource %p %s must be a readback type.", _pSourceResource, _pSourceResource->name());
			break;
		}

		case resource_type::texture:
		{
			texture_info i = static_cast<texture*>(_pSourceResource)->get_info();
			if (!is_readback(i.type))
				oTHROW_INVARG("The specified resource %p %s must be a readback type.", _pSourceResource, _pSourceResource->name());
			break;
		}

		default:
			break;
	}

	surface::mapped_subresource source;
	if (Device->map_read(_pSourceResource, _Subresource, &source))
	{
		uint2 ByteDimensions = _pSourceResource->byte_dimensions(_Subresource);
		memcpy2d(_Destination.data, _Destination.row_pitch, source.data, source.row_pitch, ByteDimensions.x, ByteDimensions.y, _FlipVertically);
		Device->unmap_read(_pSourceResource, _Subresource);
		return true;
	}
	return false;
}

std::shared_ptr<texture> make_texture(device* _pDevice, const char* _Name, const surface::buffer* const* _ppSourceImages, uint _NumImages, texture_type::value _Type)
{
	if (!_NumImages)
		oTHROW_INVARG("Need at least one source image");

	surface::info si = _ppSourceImages[0]->get_info();
	si.array_size = _NumImages;

	std::shared_ptr<texture> Texture;
	texture_info i;
	i.format = si.format;
	i.type = _Type;
	i.dimensions = int3(si.dimensions.xy(), is_3d(_Type) ? _NumImages : 1);
	i.array_size = is_array(_Type) || is_cube(_Type) ? static_cast<ushort>(_NumImages) : 0;

	switch (get_type(_Type))
	{
		case texture_type::default_1d:
			if (si.dimensions.y != 1)
				oTHROW_INVARG("1D textures cannot have height");
			break;

		case texture_type::default_cube:
			if (((_NumImages) % 6) != 0)
				oTHROW_INVARG("Cube maps must be specified in sets of 6");
			break;

		default:
			break;
	}

	Texture = _pDevice->make_texture(_Name, i);

	const int NumMips = surface::num_mips(is_mipped(_Type), i.dimensions);
	surface::buffer::make_type MakeType = is_3d(_Type)
		? (NumMips ? surface::buffer::mips3d : surface::buffer::image3d)
		: (NumMips ? surface::buffer::mips_array : surface::buffer::image_array);

	auto src = surface::buffer::make(_ppSourceImages, _NumImages, MakeType);
	auto src_si = src->get_info();
	const int nSubresources = surface::num_subresources(src_si);

	if (is_3d(_Type))
	{
		for (int subresource = 0; subresource < nSubresources; subresource++)
		{
			auto sri = surface::subresource(src_si, subresource);
			surface::box region;
			region.right = sri.dimensions.x;
			region.bottom = sri.dimensions.y;
			surface::shared_lock lock(src, subresource);
			for (int slice = 0; slice < sri.dimensions.z; slice++)
			{
				region.front = slice;
				region.back = slice + 1;
				_pDevice->immediate()->commit(Texture, subresource, lock.mapped, region);
			}
		}
	}

	else
	{
		for (int subresource = 0; subresource < nSubresources; subresource++)
		{
			surface::shared_lock lock(src, subresource);
			_pDevice->immediate()->commit(Texture, subresource, lock.mapped);
		}
	}

	return Texture;
}

#if 0
std::shared_ptr<surface::buffer> copy_to_surface_buffer(texture* _pSource, int _Subresource)
{
	std::shared_ptr<device> Device = _pSource->get_device();

	std::shared_ptr<texture> readbackTexture;
	texture* readback = nullptr;
	texture_info i = _pSource->get_info();
	if (is_readback(i.type))
		readback = _pSource;
	else
	{
		readbackTexture = make_readback_copy(_pSource);
		readback = readbackTexture.get();
		i = readback->get_info();
		Device->immediate()->copy(readback, _pSource);
	}

	surface::info si;
	si.dimensions = i.dimensions;
	si.format = i.format;
	si.layout = surface::tight;
	si.array_size = i.array_size;

	std::shared_ptr<surface::buffer> b;

	if (_Subresource == invalid)
	{
		b = surface::buffer::make(si);

		int nSubresources = surface::num_subresources(si);
		if (is_3d(i.type))
		{
			for (int subresource = 0; subresource < nSubresources; subresource++)
			{
				auto sri = surface::subresource(si, subresource);
				surface::box region;
				region.right = sri.dimensions.x;
				region.bottom = sri.dimensions.y;

				surface::mapped_subresource mapped;
				oCHECK(Device->map_read(readback, subresource, &mapped, true), "map_read failed");

				for (int slice = 0; slice < sri.dimensions.z; slice++)
				{
					region.front = slice;
					region.back = slice + 1;
					b->update_subresource(subresource, region, mapped);
				}

				Device->unmap_read(readback, subresource);
			}
		}

		else
		{
			for (int subresource = 0; subresource < nSubresources; subresource++)
			{
				auto sri = surface::subresource(si, subresource);

				surface::mapped_subresource mapped;
				oCHECK(Device->map_read(readback, subresource, &mapped, true), "map_read failed");
				b->update_subresource(subresource, mapped);
				Device->unmap_read(readback, subresource);
			}
		}
	}

	else
	{
		surface::subresource_info sri = surface::subresource(si, _Subresource);
		si.dimensions = sri.dimensions;
		si.format = sri.format;
		si.array_size = 0;
		si.layout = surface::image;
		b = surface::buffer::make(si);

		surface::mapped_subresource mapped;
		oCHECK(Device->map_read(readback, _Subresource, &mapped, true), "map_read failed");
		b->update_subresource(_Subresource, mapped);
		Device->unmap_read(readback, _Subresource);
	}

	return b;
}
#endif

	} // namespace gpu
} // namespace ouro
<commit_msg>Remove oGPUUtil for readbacks.<commit_after>/**************************************************************************
 * The MIT License                                                        *
 * Copyright (c) 2013 Antony Arciuolo.                                    *
 * arciuolo@gmail.com                                                     *
 *                                                                        *
 * Permission is hereby granted, free of charge, to any person obtaining  *
 * a copy of this software and associated documentation files (the        *
 * "Software"), to deal in the Software without restriction, including    *
 * without limitation the rights to use, copy, modify, merge, publish,    *
 * distribute, sublicense, and/or sell copies of the Software, and to     *
 * permit persons to whom the Software is furnished to do so, subject to  *
 * the following conditions:                                              *
 *                                                                        *
 * The above copyright notice and this permission notice shall be         *
 * included in all copies or substantial portions of the Software.        *
 *                                                                        *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        *
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     *
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                  *
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE *
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION *
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  *
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.        *
 **************************************************************************/
#include <oGPU/oGPUUtil.h>
#include <oBase/finally.h>

namespace ouro {
	namespace gpu {

void commit_buffer(command_list* _pCommandList, buffer* _pBuffer, const void* _pStruct, uint _SizeofStruct, uint _NumStructs)
{
	oCHECK(byte_aligned(_SizeofStruct, 16), "structs must be aligned to 16 bytes (%u bytes specified %.02f of alignment)", _SizeofStruct, _SizeofStruct / 16.0f);
	surface::mapped_subresource msr;
	msr.data = const_cast<void*>(_pStruct);
	msr.row_pitch = _SizeofStruct;
	msr.depth_pitch = _NumStructs * _SizeofStruct;
	_pCommandList->commit(_pBuffer, 0, msr);
}

void commit_buffer(device* _pDevice, buffer* _pBuffer, const void* _pStruct, uint _SizeofStruct, uint _NumStructs)
{
	oCHECK(byte_aligned(_SizeofStruct, 16), "structs must be aligned to 16 bytes (%u bytes specified %.02f of alignment)", _SizeofStruct, _SizeofStruct / 16.0f);
	surface::mapped_subresource msr;
	msr.data = const_cast<void*>(_pStruct);
	msr.row_pitch = _SizeofStruct;
	msr.depth_pitch = _NumStructs * _SizeofStruct;
	_pDevice->immediate()->commit(_pBuffer, 0, msr);
}

uint read_back_counter(buffer* _pUnorderedBuffer, buffer* _pPreallocatedReadbackBuffer)
{
	buffer_info i = _pUnorderedBuffer->get_info();
	if (i.type != buffer_type::unordered_structured_append && i.type != buffer_type::unordered_structured_counter)
		oTHROW_INVARG("the specified buffer must be of type buffer_type::unordered_structured_append or buffer_type::unordered_structured_counter");

	std::shared_ptr<device> Device = _pUnorderedBuffer->get_device();

	std::shared_ptr<buffer> CounterBuffer;
	buffer* Counter = _pPreallocatedReadbackBuffer;
	if (!Counter)
	{
		sstring Name;
		snprintf(Name, "%s.Readback", _pUnorderedBuffer->name());

		buffer_info rb;
		rb.type = buffer_type::readback;
		rb.struct_byte_size = sizeof(uint);

		CounterBuffer = Device->make_buffer(Name, rb);
		Counter = CounterBuffer.get();
	}

	Device->immediate()->copy_counter(Counter, 0, _pUnorderedBuffer);

	surface::mapped_subresource msr;
	if (!Device->map_read(Counter, 0, &msr, true))
		return invalid; // pass through error
	uint c = *(uint*)msr.data;
	Device->unmap_read(Counter, 0);
	return c;
}

bool read(resource* _pSourceResource, int _Subresource, surface::mapped_subresource& _Destination, bool _FlipVertically)
{
	std::shared_ptr<device> Device = _pSourceResource->get_device();

	switch (_pSourceResource->type())
	{
		case resource_type::buffer:
		{
			buffer_info i = static_cast<buffer*>(_pSourceResource)->get_info();
			if (i.type != buffer_type::readback)
				oTHROW_INVARG("The specified resource %p %s must be a readback type.", _pSourceResource, _pSourceResource->name());
			break;
		}

		case resource_type::texture:
		{
			texture_info i = static_cast<texture*>(_pSourceResource)->get_info();
			if (!is_readback(i.type))
				oTHROW_INVARG("The specified resource %p %s must be a readback type.", _pSourceResource, _pSourceResource->name());
			break;
		}

		default:
			break;
	}

	surface::mapped_subresource source;
	if (Device->map_read(_pSourceResource, _Subresource, &source))
	{
		uint2 ByteDimensions = _pSourceResource->byte_dimensions(_Subresource);
		memcpy2d(_Destination.data, _Destination.row_pitch, source.data, source.row_pitch, ByteDimensions.x, ByteDimensions.y, _FlipVertically);
		Device->unmap_read(_pSourceResource, _Subresource);
		return true;
	}
	return false;
}

std::shared_ptr<texture> make_texture(device* _pDevice, const char* _Name, const surface::buffer* const* _ppSourceImages, uint _NumImages, texture_type::value _Type)
{
	if (!_NumImages)
		oTHROW_INVARG("Need at least one source image");

	surface::info si = _ppSourceImages[0]->get_info();
	si.array_size = _NumImages;

	std::shared_ptr<texture> Texture;
	texture_info i;
	i.format = si.format;
	i.type = _Type;
	i.dimensions = int3(si.dimensions.xy(), is_3d(_Type) ? _NumImages : 1);
	i.array_size = is_array(_Type) || is_cube(_Type) ? static_cast<ushort>(_NumImages) : 0;

	switch (get_type(_Type))
	{
		case texture_type::default_1d:
			if (si.dimensions.y != 1)
				oTHROW_INVARG("1D textures cannot have height");
			break;

		case texture_type::default_cube:
			if (((_NumImages) % 6) != 0)
				oTHROW_INVARG("Cube maps must be specified in sets of 6");
			break;

		default:
			break;
	}

	Texture = _pDevice->make_texture(_Name, i);

	const int NumMips = surface::num_mips(is_mipped(_Type), i.dimensions);
	surface::buffer::make_type MakeType = is_3d(_Type)
		? (NumMips ? surface::buffer::mips3d : surface::buffer::image3d)
		: (NumMips ? surface::buffer::mips_array : surface::buffer::image_array);

	auto src = surface::buffer::make(_ppSourceImages, _NumImages, MakeType);
	auto src_si = src->get_info();
	const int nSubresources = surface::num_subresources(src_si);

	if (is_3d(_Type))
	{
		for (int subresource = 0; subresource < nSubresources; subresource++)
		{
			auto sri = surface::subresource(src_si, subresource);
			surface::box region;
			region.right = sri.dimensions.x;
			region.bottom = sri.dimensions.y;
			surface::shared_lock lock(src, subresource);
			for (int slice = 0; slice < sri.dimensions.z; slice++)
			{
				region.front = slice;
				region.back = slice + 1;
				_pDevice->immediate()->commit(Texture, subresource, lock.mapped, region);
			}
		}
	}

	else
	{
		for (int subresource = 0; subresource < nSubresources; subresource++)
		{
			surface::shared_lock lock(src, subresource);
			_pDevice->immediate()->commit(Texture, subresource, lock.mapped);
		}
	}

	return Texture;
}

#if 0
std::shared_ptr<surface::buffer> copy_to_surface_buffer(texture* _pSource, int _Subresource)
{
	std::shared_ptr<device> Device = _pSource->get_device();

	std::shared_ptr<texture> readbackTexture;
	texture* readback = nullptr;
	texture_info i = _pSource->get_info();
	if (is_readback(i.type))
		readback = _pSource;
	else
	{
		readbackTexture = make_readback_copy(_pSource);
		readback = readbackTexture.get();
		i = readback->get_info();
		Device->immediate()->copy(readback, _pSource);
	}

	surface::info si;
	si.dimensions = i.dimensions;
	si.format = i.format;
	si.layout = surface::tight;
	si.array_size = i.array_size;

	std::shared_ptr<surface::buffer> b;

	if (_Subresource == invalid)
	{
		b = surface::buffer::make(si);

		int nSubresources = surface::num_subresources(si);
		if (is_3d(i.type))
		{
			for (int subresource = 0; subresource < nSubresources; subresource++)
			{
				auto sri = surface::subresource(si, subresource);
				surface::box region;
				region.right = sri.dimensions.x;
				region.bottom = sri.dimensions.y;

				surface::mapped_subresource mapped;
				oCHECK(Device->map_read(readback, subresource, &mapped, true), "map_read failed");

				for (int slice = 0; slice < sri.dimensions.z; slice++)
				{
					region.front = slice;
					region.back = slice + 1;
					b->update_subresource(subresource, region, mapped);
				}

				Device->unmap_read(readback, subresource);
			}
		}

		else
		{
			for (int subresource = 0; subresource < nSubresources; subresource++)
			{
				auto sri = surface::subresource(si, subresource);

				surface::mapped_subresource mapped;
				oCHECK(Device->map_read(readback, subresource, &mapped, true), "map_read failed");
				b->update_subresource(subresource, mapped);
				Device->unmap_read(readback, subresource);
			}
		}
	}

	else
	{
		surface::subresource_info sri = surface::subresource(si, _Subresource);
		si.dimensions = sri.dimensions;
		si.format = sri.format;
		si.array_size = 0;
		si.layout = surface::image;
		b = surface::buffer::make(si);

		surface::mapped_subresource mapped;
		oCHECK(Device->map_read(readback, _Subresource, &mapped, true), "map_read failed");
		b->update_subresource(_Subresource, mapped);
		Device->unmap_read(readback, _Subresource);
	}

	return b;
}
#endif

	} // namespace gpu
} // namespace ouro
<|endoftext|>


<commit_before>#include "ReflectTest.h"
#include "Crate/Traits.h"
#include <memory>
#include <QtTest>
#include "../example/Default/Builder.h"

static int ctorCount = 0;
static int copyCount = 0;
static int dtorCount = 0;

class Vector3
  {
public:
  Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z)
    {
    ++ctorCount;
    }

  Vector3(const Vector3 &copy) : x(copy.x), y(copy.y), z(copy.z)
    {
    ++copyCount;
    }

  ~Vector3()
    {
    ++dtorCount;
    }

  bool operator==(const Vector3 &v) const
    {
    return x == v.x && y == v.y && z == v.z;
    }

  float x;
  float y;
  float z;
  };

class NonCopyable
  {
public:
  NonCopyable(const Vector3 &v)
    {
    ++ctorCount;
    m_ptr = std::unique_ptr<Vector3>(new Vector3(v));
    }

  ~NonCopyable()
    {
    ++dtorCount;
    }

  std::unique_ptr<Vector3> m_ptr;
  };

class NonCopyableReferencable
  {
public:
  NonCopyableReferencable(const Vector3 &v)
    {
    ++ctorCount;
    m_ptr = std::unique_ptr<Vector3>(new Vector3(v));
    }

  ~NonCopyableReferencable()
    {
    ++dtorCount;
    }

  std::unique_ptr<Vector3> m_ptr;
  };

namespace Crate
{
namespace detail
{

template <> struct TypeResolver<Vector3>
  {
  static const Type *find()
    {
    static Type t("Vector3");
    return &t;
    }
  };

template <> struct TypeResolver<NonCopyable>
  {
  static const Type *find()
    {
    static Type t("NonCopyable");
    return &t;
    }
  };

template <> struct TypeResolver<NonCopyableReferencable>
  {
  static const Type *find()
    {
    static Type t("NonCopyableReferencable");
    return &t;
    }
  };

}
}

namespace Crate
{
template <> class Traits<NonCopyable> : public ReferenceTraits<NonCopyable>
  {
  };
template <> class Traits<NonCopyableReferencable> : public ReferenceNonCleanedTraits<NonCopyableReferencable>
  {
  };
}

typedef Crate::Traits<Vector3> Vector3Traits;
typedef Crate::Traits<NonCopyable> NonCopyableTraits;
typedef Crate::Traits<NonCopyableReferencable> NonCopyableReferencableTraits;

void ReflectTest::typeCheckTest()
  {
  ctorCount = 0;
  dtorCount = 0;

  Reflect::example::Boxer boxer;
    {
    auto vec3 = boxer.create<Vector3Traits>();

    Vector3 vec3Data(1, 2, 3);

    QCOMPARE(ctorCount, 1);
    QCOMPARE(dtorCount, 0);
    Vector3Traits::box(&boxer, vec3.get(), &vec3Data);

    Vector3 *v = Vector3Traits::unbox(&boxer, vec3.get());
    QVERIFY(v != &vec3Data);
    QCOMPARE(*v, vec3Data);

    bool caught = false;
    try
      {
      auto empty = NonCopyableTraits::unbox(&boxer, vec3.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    caught = false;
    try
      {
      auto empty = NonCopyableReferencableTraits::unbox(&boxer, vec3.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    vec3 = nullptr;

    QCOMPARE(ctorCount, 1);
    QCOMPARE(dtorCount, 1);
    }
  }

void ReflectTest::copyableTyperTest()
  {
  ctorCount = 0;
  dtorCount = 0;

  Reflect::example::Boxer boxer;
    {
    auto vec3 = boxer.create<Vector3Traits>();

    Vector3 vec3Data(1, 2, 3);

    QCOMPARE(ctorCount, 1);
    QCOMPARE(dtorCount, 0);
    Vector3Traits::box(&boxer, vec3.get(), &vec3Data);

    Vector3 *v = Vector3Traits::unbox(&boxer, vec3.get());
    QVERIFY(v != &vec3Data);
    QCOMPARE(*v, vec3Data);

    bool caught = false;
    try
      {
      auto empty = NonCopyableTraits::unbox(&boxer, vec3.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    caught = false;
    try
      {
      auto empty = NonCopyableReferencableTraits::unbox(&boxer, vec3.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    vec3 = nullptr;

    QCOMPARE(ctorCount, 1);
    QCOMPARE(dtorCount, 1);
    }
  }

void ReflectTest::nonCopyableTyperTest()
  {
  ctorCount = 0;
  copyCount = 0;
  dtorCount = 0;

  Reflect::example::Boxer boxer;
    {
    auto nonCopyable = boxer.create<NonCopyableTraits>();

    Vector3 vec(1, 2, 3);

    QCOMPARE(ctorCount, 1);
    QCOMPARE(copyCount, 0);
    QCOMPARE(dtorCount, 0);
    auto nonCopyData = new NonCopyable(vec);

    QCOMPARE(ctorCount, 2);
    QCOMPARE(copyCount, 1);
    QCOMPARE(dtorCount, 0);
    NonCopyableTraits::box(&boxer, nonCopyable.get(), nonCopyData);

    QCOMPARE(ctorCount, 2);
    QCOMPARE(copyCount, 1);
    QCOMPARE(dtorCount, 0);

    auto v = NonCopyableTraits::unbox(&boxer, nonCopyable.get());
    QCOMPARE(v, nonCopyData);

    bool caught = false;
    try
      {
      auto empty = Vector3Traits::unbox(&boxer, nonCopyable.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    caught = false;
    try
      {
      auto empty = NonCopyableReferencableTraits::unbox(&boxer, nonCopyable.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    QCOMPARE(ctorCount, 2);
    QCOMPARE(copyCount, 1);
    QCOMPARE(dtorCount, 0);

    nonCopyable = nullptr;
    QCOMPARE(dtorCount, 2);
    }

  QCOMPARE(ctorCount, 2);
  QCOMPARE(copyCount, 1);
  QCOMPARE(dtorCount, 3);
  }

void ReflectTest::nonCopyableNonCleanedTyperTest()
  {
  ctorCount = 0;
  copyCount = 0;
  dtorCount = 0;

  Reflect::example::Boxer boxer;
    {
    auto nonCopyable = boxer.create<NonCopyableReferencableTraits>();

    Vector3 vec(1, 2, 3);

    QCOMPARE(ctorCount, 1);
    QCOMPARE(copyCount, 0);
    QCOMPARE(dtorCount, 0);
    NonCopyableReferencable nonCopyData(vec);

    QCOMPARE(ctorCount, 2);
    QCOMPARE(copyCount, 1);
    QCOMPARE(dtorCount, 0);
    NonCopyableReferencableTraits::box(&boxer, nonCopyable.get(), &nonCopyData);

    auto v = NonCopyableReferencableTraits::unbox(&boxer, nonCopyable.get());
    QCOMPARE(v, &nonCopyData);

    bool caught = false;
    try
      {
      auto empty = Vector3Traits::unbox(&boxer, nonCopyable.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    caught = false;
    try
      {
      auto empty = NonCopyableTraits::unbox(&boxer, nonCopyable.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    QCOMPARE(ctorCount, 2);
    QCOMPARE(copyCount, 1);
    QCOMPARE(dtorCount, 0);

    nonCopyable = nullptr;
    }

  QCOMPARE(ctorCount, 2);
  QCOMPARE(copyCount, 1);
  QCOMPARE(dtorCount, 3);
  }
<commit_msg>are - remove more includes<commit_after>#include "ReflectTest.h"
#include "Crate/Traits.h"
#include <memory>
#include "../example/Default/Builder.h"

static int ctorCount = 0;
static int copyCount = 0;
static int dtorCount = 0;

class Vector3
  {
public:
  Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z)
    {
    ++ctorCount;
    }

  Vector3(const Vector3 &copy) : x(copy.x), y(copy.y), z(copy.z)
    {
    ++copyCount;
    }

  ~Vector3()
    {
    ++dtorCount;
    }

  bool operator==(const Vector3 &v) const
    {
    return x == v.x && y == v.y && z == v.z;
    }

  float x;
  float y;
  float z;
  };

class NonCopyable
  {
public:
  NonCopyable(const Vector3 &v)
    {
    ++ctorCount;
    m_ptr = std::unique_ptr<Vector3>(new Vector3(v));
    }

  ~NonCopyable()
    {
    ++dtorCount;
    }

  std::unique_ptr<Vector3> m_ptr;
  };

class NonCopyableReferencable
  {
public:
  NonCopyableReferencable(const Vector3 &v)
    {
    ++ctorCount;
    m_ptr = std::unique_ptr<Vector3>(new Vector3(v));
    }

  ~NonCopyableReferencable()
    {
    ++dtorCount;
    }

  std::unique_ptr<Vector3> m_ptr;
  };

namespace Crate
{
namespace detail
{

template <> struct TypeResolver<Vector3>
  {
  static const Type *find()
    {
    static Type t("Vector3");
    return &t;
    }
  };

template <> struct TypeResolver<NonCopyable>
  {
  static const Type *find()
    {
    static Type t("NonCopyable");
    return &t;
    }
  };

template <> struct TypeResolver<NonCopyableReferencable>
  {
  static const Type *find()
    {
    static Type t("NonCopyableReferencable");
    return &t;
    }
  };

}
}

namespace Crate
{
template <> class Traits<NonCopyable> : public ReferenceTraits<NonCopyable>
  {
  };
template <> class Traits<NonCopyableReferencable> : public ReferenceNonCleanedTraits<NonCopyableReferencable>
  {
  };
}

typedef Crate::Traits<Vector3> Vector3Traits;
typedef Crate::Traits<NonCopyable> NonCopyableTraits;
typedef Crate::Traits<NonCopyableReferencable> NonCopyableReferencableTraits;

void ReflectTest::typeCheckTest()
  {
  ctorCount = 0;
  dtorCount = 0;

  Reflect::example::Boxer boxer;
    {
    auto vec3 = boxer.create<Vector3Traits>();

    Vector3 vec3Data(1, 2, 3);

    QCOMPARE(ctorCount, 1);
    QCOMPARE(dtorCount, 0);
    Vector3Traits::box(&boxer, vec3.get(), &vec3Data);

    Vector3 *v = Vector3Traits::unbox(&boxer, vec3.get());
    QVERIFY(v != &vec3Data);
    QCOMPARE(*v, vec3Data);

    bool caught = false;
    try
      {
      auto empty = NonCopyableTraits::unbox(&boxer, vec3.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    caught = false;
    try
      {
      auto empty = NonCopyableReferencableTraits::unbox(&boxer, vec3.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    vec3 = nullptr;

    QCOMPARE(ctorCount, 1);
    QCOMPARE(dtorCount, 1);
    }
  }

void ReflectTest::copyableTyperTest()
  {
  ctorCount = 0;
  dtorCount = 0;

  Reflect::example::Boxer boxer;
    {
    auto vec3 = boxer.create<Vector3Traits>();

    Vector3 vec3Data(1, 2, 3);

    QCOMPARE(ctorCount, 1);
    QCOMPARE(dtorCount, 0);
    Vector3Traits::box(&boxer, vec3.get(), &vec3Data);

    Vector3 *v = Vector3Traits::unbox(&boxer, vec3.get());
    QVERIFY(v != &vec3Data);
    QCOMPARE(*v, vec3Data);

    bool caught = false;
    try
      {
      auto empty = NonCopyableTraits::unbox(&boxer, vec3.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    caught = false;
    try
      {
      auto empty = NonCopyableReferencableTraits::unbox(&boxer, vec3.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    vec3 = nullptr;

    QCOMPARE(ctorCount, 1);
    QCOMPARE(dtorCount, 1);
    }
  }

void ReflectTest::nonCopyableTyperTest()
  {
  ctorCount = 0;
  copyCount = 0;
  dtorCount = 0;

  Reflect::example::Boxer boxer;
    {
    auto nonCopyable = boxer.create<NonCopyableTraits>();

    Vector3 vec(1, 2, 3);

    QCOMPARE(ctorCount, 1);
    QCOMPARE(copyCount, 0);
    QCOMPARE(dtorCount, 0);
    auto nonCopyData = new NonCopyable(vec);

    QCOMPARE(ctorCount, 2);
    QCOMPARE(copyCount, 1);
    QCOMPARE(dtorCount, 0);
    NonCopyableTraits::box(&boxer, nonCopyable.get(), nonCopyData);

    QCOMPARE(ctorCount, 2);
    QCOMPARE(copyCount, 1);
    QCOMPARE(dtorCount, 0);

    auto v = NonCopyableTraits::unbox(&boxer, nonCopyable.get());
    QCOMPARE(v, nonCopyData);

    bool caught = false;
    try
      {
      auto empty = Vector3Traits::unbox(&boxer, nonCopyable.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    caught = false;
    try
      {
      auto empty = NonCopyableReferencableTraits::unbox(&boxer, nonCopyable.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    QCOMPARE(ctorCount, 2);
    QCOMPARE(copyCount, 1);
    QCOMPARE(dtorCount, 0);

    nonCopyable = nullptr;
    QCOMPARE(dtorCount, 2);
    }

  QCOMPARE(ctorCount, 2);
  QCOMPARE(copyCount, 1);
  QCOMPARE(dtorCount, 3);
  }

void ReflectTest::nonCopyableNonCleanedTyperTest()
  {
  ctorCount = 0;
  copyCount = 0;
  dtorCount = 0;

  Reflect::example::Boxer boxer;
    {
    auto nonCopyable = boxer.create<NonCopyableReferencableTraits>();

    Vector3 vec(1, 2, 3);

    QCOMPARE(ctorCount, 1);
    QCOMPARE(copyCount, 0);
    QCOMPARE(dtorCount, 0);
    NonCopyableReferencable nonCopyData(vec);

    QCOMPARE(ctorCount, 2);
    QCOMPARE(copyCount, 1);
    QCOMPARE(dtorCount, 0);
    NonCopyableReferencableTraits::box(&boxer, nonCopyable.get(), &nonCopyData);

    auto v = NonCopyableReferencableTraits::unbox(&boxer, nonCopyable.get());
    QCOMPARE(v, &nonCopyData);

    bool caught = false;
    try
      {
      auto empty = Vector3Traits::unbox(&boxer, nonCopyable.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    caught = false;
    try
      {
      auto empty = NonCopyableTraits::unbox(&boxer, nonCopyable.get());
      QVERIFY(!empty);
      }
    catch(...)
      {
      caught = true;
      }
    QVERIFY(caught);

    QCOMPARE(ctorCount, 2);
    QCOMPARE(copyCount, 1);
    QCOMPARE(dtorCount, 0);

    nonCopyable = nullptr;
    }

  QCOMPARE(ctorCount, 2);
  QCOMPARE(copyCount, 1);
  QCOMPARE(dtorCount, 3);
  }
<|endoftext|>