<commit_before>/*
AlloCore Example: Vectors

Description:
This shows basic usage of the Vec class which represents an n-dimensional vector or n-vector.

Author:
Lance Putnam, 10/2012, putnam.lance@gmail.com
*/

#include "allocore/math/al_Vec.hpp"
using namespace al;

int main(){

	// Lesson 1: Declarations
	// =============================================================================================
	{
	/*
	Vec is a template class with two template parameters:
	1) N, the number of dimensions and 2) T, the element type.
	Here are some example declarations:
	*/
		Vec<3,float> vec3f;		// 3-vector of floats
		Vec<2,int> vec2i;		// 2-vector of ints
		Vec<11,double> vec11d;	// 11-vector of doubles (!)
		Vec<1,float> vec1f;		// 1-vector (scalar) with a float
		Vec<0,float> vec0f;		// even 0-vectors are allowed, for completeness

	/*
	For convience, some common types are predefined:
	*/
	//	2-vector     3-vector     4-vector
		{ Vec2f v; } { Vec3f v; } { Vec4f v; } // float
		{ Vec2d v; } { Vec3d v; } { Vec4d v; } // double
		{ Vec2i v; } { Vec3i v; } { Vec4i v; } // int
	}

	// Lesson 2: Constructors
	// =============================================================================================
	/*
	Vec has many different kinds of constructors. Here are some examples:
	*/
	{	Vec3f x;				// Initialize to {0, 0, 0}
		Vec3f a(1);				// Initialize to {1, 1, 1}
		Vec3f b(1,2,3);			// Initialize to {1, 2, 3}
		Vec2f c(4,5);			// Initialize to {4, 5}
		Vec4f d(6,7,8,9);		// Initializing with scalars works up to 4-vectors

		Vec2d e(c);				// Initialize from vector to {4, 5}
		Vec3f f(c, 6);			// Initialize from vector and scalar to {4, 5, 6}

	/*
	Vec can be initialized from C-arrays:
	*/
		float arr2[] = {1,2};
		Vec2f g(arr2);			// Initialize from C-array, sizes match
		Vec2i h(arr2);			// It's okay for the C-array and vector to be different types
	/*
	Sizes can be different, but the C-array must be longer. Only the first n elements are copied.
	*/
		float arr3[] = {3,4,5};
		Vec2f i(arr3);
	/*
	It is also possible to specify a stride amount through the C-array
	*/
		float arr8[] = {0,1,2,3,4,5,6,7};
		Vec3f l(arr8, 2);		// Initialize to {0, 2, 4}
		Vec3f m(arr8, 3);		// Initialize to {0, 3, 6}
	}

	// Lesson 3: Acccessing Elements
	// =============================================================================================
	/*
	All vectors know their size (number of elements):
	*/
	{	Vec3f a;
		a.size();				// Returns '3'
	}
	/*
	Access is accomplished using the normal array access operator:
	*/
	{	Vec3f a(7,2,5);
		a[0];					// Access element 0
		a[2];					// Access element 2
	}
	/*
	For 1-, 2-, 3-, and 4-vectors, it is possible to use symbolic names. The symbols
	'x', 'y', 'z', and 'w' are used to access elements 0, 1, 2, and 3, respectively. E.g.:
	*/
	{	Vec2f b(1,2);
		b.x = b.y;				// Results in {2, 2}

		Vec3f c(1,2,3);
		c.x = c.y = c.z;		// Results in {3, 3, 3}

		Vec4f d(1,2,3,4);
		d.x = d.y = d.z = d.w;	// Results in {4, 4, 4, 4}
	}
	/*
	The 'set' family of methods make it easy to set multiple elements at once:
	*/
	{	Vec3f a, b;
		a.set(1,2,3);			// Sets 'a' to {1, 2, 3}
		b.set(1);				// Sets 'b' to {1, 1, 1}
		a.set(b);				// Sets 'a' to {1, 1, 1}

		Vec2f c(9,1);
		a.set(c, 3);			// Sets 'a' to {9, 1, 3}

		float arr[] = {1,7,2,8,3,9};
		a.set(arr);				// Sets 'a' to {1, 7, 2}
		a.set(arr,2);			// Sets 'a' to {1, 2, 3} by using a stride of 2
	}
	/*
	It is easy to obtain subvectors, contiguous parts of a larger vector:
	*/
	{
		Vec4f a(7,5,0,2);
		a.sub<2>(0);			// Returns 2-vector {7, 5}
		a.sub<2>(2);			// Returns 2-vector {0, 2}
		a.sub<3>(1);			// Returns 3-vector {5, 0, 2}
	}
	/*
	It is also possible to "swizzle", that is, obtain a new vector comprised of arbitrary elements
	from a particular vector:
	*/
	{	Vec3f a(9,3,7);
		a.get(0,0,0);			// Returns {9, 9, 9}
		a.get(2,1,0);			// Returns {7, 3, 9}
		a.get(1,0);				// Returns {3, 9}
	}

	// Lesson 4: Arithmetic
	// =============================================================================================
	/*
	Like expected of any good vector, Vec has many arithemtic operators defined:
	*/
	{	Vec3f a(2,6,4);
		-a;						// Returns {-2, -6, -4}
		a + 1;					// Returns {3, 7, 5}
		a - 1;					// Returns {1, 5, 3}
		a * 3;					// Returns {6, 18, 12}
		a / 4;					// Returns {0.5, 1.5, 1}
		a += 1;					// Sets 'a' to {3, 7, 5}
		a -= 1;					// Sets 'a' to {2, 6, 4}
		a *= 2;					// Sets 'a' to {4,12, 8}
		a /= 2;					// Sets 'a' to {2, 6, 4}
	}
	/*
	Operations between vectors are element-wise:
	*/
	{	Vec3f a(2,6,4);
		Vec3f b(4,1,2);
		a + b;					// Returns {6, 7, 6}
		a - b;					// Returns {-2, 5, 2}
		a * b;					// Returns {8, 6, 8}
		a / b;					// Returns {0.5, 6, 2}
		a += b;					// Sets 'a' to {6, 7, 6}
		a -= b;					// Sets 'a' to {2, 6, 4}
		a *= b;					// Sets 'a' to {8, 6, 8}
		a /= b;					// Sets 'a' to {2, 6, 4}
	}
	/*
	Some comparison operators are provided:
	*/
	{	Vec3f a(2,6,4);
		Vec3f b(2,2,2);
		Vec3f c(2,6,4);

		a == b;					// Returns 'false'
		a == c;					// Returns 'true'
		a != b;					// Returns 'true'
		a != c;					// Returns 'false'
	}

	// Lesson 5: Vector Functions
	// =============================================================================================
	/**/
	{	Vec2f v(3,4);

		v.mag();				// Returns 5, the magnitude of the vector
		v.magSqr();				// Returns 25, the magnitude squared

		v.normalize();			// Sets magnitude to 1 without changing the direction.
								// Equivalent to a = a / a.mag()

		v.normalize(0.5);		// Sets magnitude to 0.5 without changing the direction

		v.normalized();			// Returns closest vector on unit sphere

		Vec3f A( 1, 2, 3);
		Vec3f B( 3,-2, 0);

		A.dot(B);				// Returns -1 (=1*3 + 2*-2 + 3*0), the dot product of A and B

		A.product();			// Returns 6 (= 1*2*3), the product of all elements
		B.sum();				// Returns 1 (= 3+-2+0), the sum of all elements

		cross(A, B);			// Returns cross product A x B (3-vectors only)
		angle(A, B);			// Returns angle, in radians, between A and B
		dist(A, B);				// Returns Euclidean distance between A and B; same as (A-B).mag()

		min(A, B);				// Returns {1,-2, 0}, minimum elements between A and B
		max(A, B);				// Returns {3, 2, 3}, maximum elements between A and B
	}
}
<commit_msg>narrow column width<commit_after>/*
AlloCore Example: Vectors

Description:
This shows basic usage of the Vec class which represents an n-dimensional vector
or n-vector.

Author:
Lance Putnam, 10/2012, putnam.lance@gmail.com
*/

#include "allocore/math/al_Vec.hpp"
using namespace al;

int main(){

	// Lesson 1: Declarations
	// =========================================================================
	{
	/*
	Vec is a template class with two template parameters:
	1) N, the number of dimensions and 2) T, the element type.
	Here are some example declarations:
	*/
		Vec<3,float> vec3f;		// 3-vector of floats
		Vec<2,int> vec2i;		// 2-vector of ints
		Vec<11,double> vec11d;	// 11-vector of doubles (!)
		Vec<1,float> vec1f;		// 1-vector (scalar) with a float
		Vec<0,float> vec0f;		// even 0-vectors are allowed, for completeness

	/*
	For convience, some common types are predefined:
	*/
	//	2-vector     3-vector     4-vector
		{ Vec2f v; } { Vec3f v; } { Vec4f v; } // float
		{ Vec2d v; } { Vec3d v; } { Vec4d v; } // double
		{ Vec2i v; } { Vec3i v; } { Vec4i v; } // int
	}

	// Lesson 2: Constructors
	// =========================================================================
	/*
	Vec has many different kinds of constructors. Here are some examples:
	*/
	{	Vec3f x;				// Initialize to {0, 0, 0}
		Vec3f a(1);				// Initialize to {1, 1, 1}
		Vec3f b(1,2,3);			// Initialize to {1, 2, 3}
		Vec2f c(4,5);			// Initialize to {4, 5}
		Vec4f d(6,7,8,9);		// Init'ing with scalars works up to 4-vectors

		Vec2d e(c);				// Initialize from vector to {4, 5}
		Vec3f f(c, 6);			// Initialize from vector and scalar to {4,5,6}

	/*
	Vec can be initialized from C-arrays:
	*/
		float arr2[] = {1,2};
		Vec2f g(arr2);			// Initialize from C-array, sizes match
		Vec2i h(arr2);			// The C-array and vector can be different types
	/*
	Sizes can be different, but the C-array must be longer. Only the first
	n elements are copied.
	*/
		float arr3[] = {3,4,5};
		Vec2f i(arr3);
	/*
	It is also possible to specify a stride amount through the C-array
	*/
		float arr8[] = {0,1,2,3,4,5,6,7};
		Vec3f l(arr8, 2);		// Initialize to {0, 2, 4}
		Vec3f m(arr8, 3);		// Initialize to {0, 3, 6}
	}

	// Lesson 3: Acccessing Elements
	// =========================================================================
	/*
	All vectors know their size (number of elements):
	*/
	{	Vec3f a;
		a.size();				// Returns '3'
	}
	/*
	Access is accomplished using the normal array access operator:
	*/
	{	Vec3f a(7,2,5);
		a[0];					// Access element 0
		a[2];					// Access element 2
	}
	/*
	For 1-, 2-, 3-, and 4-vectors, it is possible to use symbolic names. The
	symbols 'x', 'y', 'z', and 'w' are used to access elements 0, 1, 2, and 3,
	respectively. E.g.:
	*/
	{	Vec2f b(1,2);
		b.x = b.y;				// Results in {2, 2}

		Vec3f c(1,2,3);
		c.x = c.y = c.z;		// Results in {3, 3, 3}

		Vec4f d(1,2,3,4);
		d.x = d.y = d.z = d.w;	// Results in {4, 4, 4, 4}
	}
	/*
	The 'set' family of methods make it easy to set multiple elements at once:
	*/
	{	Vec3f a, b;
		a.set(1,2,3);			// Sets 'a' to {1, 2, 3}
		b.set(1);				// Sets 'b' to {1, 1, 1}
		a.set(b);				// Sets 'a' to {1, 1, 1}

		Vec2f c(9,1);
		a.set(c, 3);			// Sets 'a' to {9, 1, 3}

		float arr[] = {1,7,2,8,3,9};
		a.set(arr);				// Sets 'a' to {1, 7, 2}
		a.set(arr,2);			// Sets 'a' to {1, 2, 3} by using a stride of 2
	}
	/*
	It is easy to obtain subvectors, contiguous parts of a larger vector:
	*/
	{
		Vec4f a(7,5,0,2);
		a.sub<2>(0);			// Returns 2-vector {7, 5}
		a.sub<2>(2);			// Returns 2-vector {0, 2}
		a.sub<3>(1);			// Returns 3-vector {5, 0, 2}
	}
	/*
	It is also possible to "swizzle", that is, obtain a new vector comprised of
	arbitrary elements from a particular vector:
	*/
	{	Vec3f a(9,3,7);
		a.get(0,0,0);			// Returns {9, 9, 9}
		a.get(2,1,0);			// Returns {7, 3, 9}
		a.get(1,0);				// Returns {3, 9}
	}

	// Lesson 4: Arithmetic
	// =========================================================================
	/*
	Like expected of any good vector, Vec has many arithemtic operators defined:
	*/
	{	Vec3f a(2,6,4);
		-a;						// Returns {-2, -6, -4}
		a + 1;					// Returns {3, 7, 5}
		a - 1;					// Returns {1, 5, 3}
		a * 3;					// Returns {6, 18, 12}
		a / 4;					// Returns {0.5, 1.5, 1}
		a += 1;					// Sets 'a' to {3, 7, 5}
		a -= 1;					// Sets 'a' to {2, 6, 4}
		a *= 2;					// Sets 'a' to {4,12, 8}
		a /= 2;					// Sets 'a' to {2, 6, 4}
	}
	/*
	Operations between vectors are element-wise:
	*/
	{	Vec3f a(2,6,4);
		Vec3f b(4,1,2);
		a + b;					// Returns {6, 7, 6}
		a - b;					// Returns {-2, 5, 2}
		a * b;					// Returns {8, 6, 8}
		a / b;					// Returns {0.5, 6, 2}
		a += b;					// Sets 'a' to {6, 7, 6}
		a -= b;					// Sets 'a' to {2, 6, 4}
		a *= b;					// Sets 'a' to {8, 6, 8}
		a /= b;					// Sets 'a' to {2, 6, 4}
	}
	/*
	Some comparison operators are provided:
	*/
	{	Vec3f a(2,6,4);
		Vec3f b(2,2,2);
		Vec3f c(2,6,4);

		a == b;					// Returns 'false'
		a == c;					// Returns 'true'
		a != b;					// Returns 'true'
		a != c;					// Returns 'false'
	}

	// Lesson 5: Vector Functions
	// =========================================================================
	/**/
	{	Vec2f v(3,4);

		v.mag();				// Returns 5, the magnitude of the vector
		v.magSqr();				// Returns 25, the magnitude squared

		v.normalize();			// Sets magnitude to 1 without changing the
								// vector's direction; the map a <- a / a.mag().

		v.normalize(0.5);		// Sets magnitude to 0.5 without changing the
								// direction

		v.normalized();			// Returns closest vector on unit sphere

		Vec3f A( 1, 2, 3);
		Vec3f B( 3,-2, 0);

		A.dot(B);				// Returns -1 (=1*3 + 2*-2 + 3*0);
								// the dot product of A and B

		A.product();			// Returns 6 (= 1*2*3), the product of all elems
		B.sum();				// Returns 1 (= 3+-2+0), the sum of all elems

		cross(A, B);			// Returns cross product A x B (3-vectors only)
		angle(A, B);			// Returns angle, in radians, between A and B
		dist(A, B);				// Returns Euclidean distance between A and B;
								// same as (A-B).mag()

		min(A, B);				// Returns {1,-2, 0}; minimum values between A and B
		max(A, B);				// Returns {3, 2, 3}; maximum values between A and B
	}
}
<|endoftext|>


<commit_before>#include "LatestCompetitionScene.h"
#include <array>
#include "network/HttpClient.h"
#include "json/document.h"
#include "json/stringbuffer.h"
#include "../widget/LoadingView.h"
#include "../widget/AlertView.h"

USING_NS_CC;

bool LatestCompetitionScene::init() {
    if (UNLIKELY(!BaseScene::initWithTitle("近期赛事"))) {
        return false;
    }

    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    Label *label = Label::createWithSystemFont("宣传赛事信息，请联系逍遥宫", "Arial", 12);
    this->addChild(label);
    label->setPosition(Vec2(origin.x + visibleSize.width * 0.5f, origin.y + visibleSize.height - 45.0f));
    label->setColor(Color3B::ORANGE);

    cw::TableView *tableView = cw::TableView::create();
    tableView->setDirection(ui::ScrollView::Direction::VERTICAL);
    tableView->setScrollBarPositionFromCorner(Vec2(2.0f, 2.0f));
    tableView->setScrollBarWidth(4.0f);
    tableView->setScrollBarOpacity(0x99);
    tableView->setContentSize(Size(visibleSize.width - 5.0f, visibleSize.height - 65.0f));
    tableView->setDelegate(this);
    tableView->setVerticalFillOrder(cw::TableView::VerticalFillOrder::TOP_DOWN);

    tableView->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
    tableView->setPosition(Vec2(origin.x + visibleSize.width * 0.5f, origin.y + visibleSize.height * 0.5f - 30.0f));
    this->addChild(tableView);
    _tableView = tableView;

    label = Label::createWithSystemFont("无近期赛事信息", "Arial", 12);
    this->addChild(label);
    label->setPosition(Vec2(origin.x + visibleSize.width * 0.5f, origin.y + visibleSize.height - 75.0f));
    label->setColor(Color3B::BLACK);
    label->setVisible(false);
    _emptyLabel = label;

    this->scheduleOnce([this](float) { requestCompetitions(); }, 0.0f, "request_competitions");

    return true;
}

void LatestCompetitionScene::requestCompetitions() {
    LoadingView *loadingView = LoadingView::create();
    this->addChild(loadingView);
    loadingView->setPosition(Director::getInstance()->getVisibleOrigin());

    network::HttpRequest *request = new (std::nothrow) network::HttpRequest();
    request->setRequestType(network::HttpRequest::Type::GET);
    request->setUrl("https://raw.githubusercontent.com/summerinsects/ChineseOfficialMahjongLatestCompetition/master/LatestCompetition.json");

    auto thiz = makeRef(this);  // 保证线程回来之前不析构
    request->setResponseCallback([thiz, loadingView](network::HttpClient *client, network::HttpResponse *response) {
        if (UNLIKELY(!thiz->isRunning())) {
            return;
        }

        loadingView->removeFromParent();

        LatestCompetitionScene *pthis = thiz.get();
        if (response == nullptr) {
            AlertView::showWithMessage("提示", "获取近期赛事失败", 12, [pthis]() {
                pthis->requestCompetitions();
            }, nullptr);
            return;
        }

        log("HTTP Status Code: %ld", response->getResponseCode());

        if (!response->isSucceed()) {
            log("response failed");
            log("error buffer: %s", response->getErrorBuffer());
            AlertView::showWithMessage("提示", "获取近期赛事失败", 12, [pthis]() {
                pthis->requestCompetitions();
            }, nullptr);
            return;
        }

        std::vector<char> *buffer = response->getResponseData();
        thiz->parseResponse(buffer);
    });

    network::HttpClient::getInstance()->send(request);
    request->release();
}

bool LatestCompetitionScene::parseResponse(const std::vector<char> *buffer) {
    if (buffer == nullptr) {
        return false;
    }

    try {
        do {
            std::string str(buffer->begin(), buffer->end());
            rapidjson::Document doc;
            doc.Parse<0>(str.c_str());
            if (doc.HasParseError() || !doc.IsArray()) {
                break;
            }

            _competitions.clear();
            _competitions.reserve(doc.Size());
            std::transform(doc.Begin(), doc.End(), std::back_inserter(_competitions), [](const rapidjson::Value &json) {
                CompetitionInfo info = { 0 };

                rapidjson::Value::ConstMemberIterator it = json.FindMember("name");
                if (it != json.MemberEnd() && it->value.IsString()) {
                    strncpy(info.name, it->value.GetString(), 255);
                }

                it = json.FindMember("start_time");
                if (it != json.MemberEnd() && it->value.IsInt64()) {
                    info.startTime = it->value.GetInt64();
                }

                it = json.FindMember("end_time");
                if (it != json.MemberEnd() && it->value.IsInt64()) {
                    info.endTime = it->value.GetInt64();
                }

                it = json.FindMember("url");
                if (it != json.MemberEnd() && it->value.IsString()) {
                    strncpy(info.url, it->value.GetString(), 1023);
                }

                it = json.FindMember("time_accuracy");
                if (it != json.MemberEnd() && it->value.IsInt()) {
                    info.timeAccuracy = static_cast<TIME_ACCURACY>(it->value.GetInt());
                }
                return info;
            });

            time_t now = time(nullptr);
            std::vector<CompetitionInfo>::iterator it = std::remove_if(_competitions.begin(), _competitions.end(),
                [now](const CompetitionInfo &info) {
                return (info.timeAccuracy != TIME_ACCURACY::UNDETERMINED && info.startTime < now);
            });
            _competitions.erase(it, _competitions.end());

            _tableView->reloadDataInplacement();
            _emptyLabel->setVisible(_competitions.empty());

            return true;
        } while (0);
    }
    catch (std::exception &e) {
        CCLOG("%s %s", __FUNCTION__, e.what());
    }

    return false;
}

ssize_t LatestCompetitionScene::numberOfCellsInTableView(cw::TableView *table) {
    return _competitions.size();
}

float LatestCompetitionScene::tableCellSizeForIndex(cw::TableView *table, ssize_t idx) {
    return 50.0f;
}

cw::TableViewCell *LatestCompetitionScene::tableCellAtIndex(cw::TableView *table, ssize_t idx) {
    typedef cw::TableViewCellEx<std::array<LayerColor *, 2>, std::array<Label *, 2>, ui::Button *> CustomCell;
    CustomCell *cell = (CustomCell *)table->dequeueCell();

    if (cell == nullptr) {
        cell = CustomCell::create();

        Size visibleSize = Director::getInstance()->getVisibleSize();
        const float width = visibleSize.width - 5.0f;

        CustomCell::ExtDataType &ext = cell->getExtData();
        std::array<LayerColor *, 2> &layerColors = std::get<0>(ext);
        std::array<Label *, 2> &label = std::get<1>(ext);
        ui::Button *&detailBtn = std::get<2>(ext);

        layerColors[0] = LayerColor::create(Color4B(0x10, 0x10, 0x10, 0x10), width, 50.0f);
        cell->addChild(layerColors[0]);

        layerColors[1] = LayerColor::create(Color4B(0xC0, 0xC0, 0xC0, 0x10), width, 50.0f);
        cell->addChild(layerColors[1]);

        label[0] = Label::createWithSystemFont("", "Arail", 10);
        label[0]->setColor(Color3B::BLACK);
        cell->addChild(label[0]);
        label[0]->setPosition(Vec2(5.0f, 35.0f));
        label[0]->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);

        label[1] = Label::createWithSystemFont("", "Arail", 10);
        label[1]->setColor(Color3B(0x60, 0x60, 0x60));
        cell->addChild(label[1]);
        label[1]->setPosition(Vec2(5.0f, 15.0f));
        label[1]->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);

        detailBtn = ui::Button::create("source_material/btn_square_highlighted.png", "source_material/btn_square_selected.png");
        detailBtn->setScale9Enabled(true);
        detailBtn->setContentSize(Size(40.0f, 20.0f));
        detailBtn->setTitleFontSize(12);
        detailBtn->setTitleText("详情");
        detailBtn->addClickEventListener(std::bind(&LatestCompetitionScene::onDetailButton, this, std::placeholders::_1));
        cell->addChild(detailBtn);
        detailBtn->setPosition(Vec2(width - 25.0f, 25.0f));
    }

    const CustomCell::ExtDataType &ext = cell->getExtData();
    const std::array<LayerColor *, 2> &layerColors = std::get<0>(ext);
    const std::array<Label *, 2> &label = std::get<1>(ext);
    ui::Button *detailBtn = std::get<2>(ext);

    layerColors[0]->setVisible(!(idx & 1));
    layerColors[1]->setVisible(!!(idx & 1));

    detailBtn->setUserData(reinterpret_cast<void *>(idx));

    const CompetitionInfo &info = _competitions[idx];
    label[0]->setString(info.name);

    struct tm ret = *localtime(&info.startTime);
    std::string date;

    switch (info.timeAccuracy) {
    default:
        date = "具体时间待定";
        break;
    case TIME_ACCURACY::MONTHS:
        date = Common::format("%d年%d月", ret.tm_year + 1900, ret.tm_mon + 1);
        if (info.endTime != 0) {
            date.append("——");
            ret = *localtime(&info.endTime);
            date.append(Common::format("%d年%d月", ret.tm_year + 1900, ret.tm_mon + 1));
        }
        break;
    case TIME_ACCURACY::DAYS:
        date = Common::format("%d年%d月%d日", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday);
        if (info.endTime != 0) {
            date.append("——");
            ret = *localtime(&info.endTime);
            date.append(Common::format("%d年%d月%d日", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday));
        }
        break;
    case TIME_ACCURACY::HONRS:
        date = Common::format("%d年%d月%d日%.2d点", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday, ret.tm_hour);
        if (info.endTime != 0) {
            date.append("——");
            ret = *localtime(&info.endTime);
            date.append(Common::format("%d年%d月%d日%.2d点", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday, ret.tm_hour));
        }
        break;
    case TIME_ACCURACY::MINUTES:
        date = Common::format("%d年%d月%d日%.2d:%.2d", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday, ret.tm_hour, ret.tm_min);
        if (info.endTime != 0) {
            date.append("——");
            ret = *localtime(&info.endTime);
            date.append(Common::format("%d年%d月%d日%.2d:%.2d", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday, ret.tm_hour, ret.tm_min));
        }
        break;
    }
    label[1]->setString(date);

    detailBtn->setVisible(info.url[0] != '\0');

    return cell;
}

void LatestCompetitionScene::onDetailButton(cocos2d::Ref *sender) {
    ui::Button *button = (ui::Button *)sender;
    size_t idx = reinterpret_cast<size_t>(button->getUserData());
    Application::getInstance()->openURL(_competitions[idx].url);
}
<commit_msg>检查了strncpy的参数<commit_after>#include "LatestCompetitionScene.h"
#include <array>
#include "network/HttpClient.h"
#include "json/document.h"
#include "json/stringbuffer.h"
#include "../widget/LoadingView.h"
#include "../widget/AlertView.h"

USING_NS_CC;

bool LatestCompetitionScene::init() {
    if (UNLIKELY(!BaseScene::initWithTitle("近期赛事"))) {
        return false;
    }

    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    Label *label = Label::createWithSystemFont("宣传赛事信息，请联系逍遥宫", "Arial", 12);
    this->addChild(label);
    label->setPosition(Vec2(origin.x + visibleSize.width * 0.5f, origin.y + visibleSize.height - 45.0f));
    label->setColor(Color3B::ORANGE);

    cw::TableView *tableView = cw::TableView::create();
    tableView->setDirection(ui::ScrollView::Direction::VERTICAL);
    tableView->setScrollBarPositionFromCorner(Vec2(2.0f, 2.0f));
    tableView->setScrollBarWidth(4.0f);
    tableView->setScrollBarOpacity(0x99);
    tableView->setContentSize(Size(visibleSize.width - 5.0f, visibleSize.height - 65.0f));
    tableView->setDelegate(this);
    tableView->setVerticalFillOrder(cw::TableView::VerticalFillOrder::TOP_DOWN);

    tableView->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
    tableView->setPosition(Vec2(origin.x + visibleSize.width * 0.5f, origin.y + visibleSize.height * 0.5f - 30.0f));
    this->addChild(tableView);
    _tableView = tableView;

    label = Label::createWithSystemFont("无近期赛事信息", "Arial", 12);
    this->addChild(label);
    label->setPosition(Vec2(origin.x + visibleSize.width * 0.5f, origin.y + visibleSize.height - 75.0f));
    label->setColor(Color3B::BLACK);
    label->setVisible(false);
    _emptyLabel = label;

    this->scheduleOnce([this](float) { requestCompetitions(); }, 0.0f, "request_competitions");

    return true;
}

void LatestCompetitionScene::requestCompetitions() {
    LoadingView *loadingView = LoadingView::create();
    this->addChild(loadingView);
    loadingView->setPosition(Director::getInstance()->getVisibleOrigin());

    network::HttpRequest *request = new (std::nothrow) network::HttpRequest();
    request->setRequestType(network::HttpRequest::Type::GET);
    request->setUrl("https://raw.githubusercontent.com/summerinsects/ChineseOfficialMahjongLatestCompetition/master/LatestCompetition.json");

    auto thiz = makeRef(this);  // 保证线程回来之前不析构
    request->setResponseCallback([thiz, loadingView](network::HttpClient *client, network::HttpResponse *response) {
        if (UNLIKELY(!thiz->isRunning())) {
            return;
        }

        loadingView->removeFromParent();

        LatestCompetitionScene *pthis = thiz.get();
        if (response == nullptr) {
            AlertView::showWithMessage("提示", "获取近期赛事失败", 12, [pthis]() {
                pthis->requestCompetitions();
            }, nullptr);
            return;
        }

        log("HTTP Status Code: %ld", response->getResponseCode());

        if (!response->isSucceed()) {
            log("response failed");
            log("error buffer: %s", response->getErrorBuffer());
            AlertView::showWithMessage("提示", "获取近期赛事失败", 12, [pthis]() {
                pthis->requestCompetitions();
            }, nullptr);
            return;
        }

        std::vector<char> *buffer = response->getResponseData();
        thiz->parseResponse(buffer);
    });

    network::HttpClient::getInstance()->send(request);
    request->release();
}

bool LatestCompetitionScene::parseResponse(const std::vector<char> *buffer) {
    if (buffer == nullptr) {
        return false;
    }

    try {
        do {
            std::string str(buffer->begin(), buffer->end());
            rapidjson::Document doc;
            doc.Parse<0>(str.c_str());
            if (doc.HasParseError() || !doc.IsArray()) {
                break;
            }

            _competitions.clear();
            _competitions.reserve(doc.Size());
            std::transform(doc.Begin(), doc.End(), std::back_inserter(_competitions), [](const rapidjson::Value &json) {
                CompetitionInfo info = { 0 };

                rapidjson::Value::ConstMemberIterator it = json.FindMember("name");
                if (it != json.MemberEnd() && it->value.IsString()) {
                    strncpy(info.name, it->value.GetString(), sizeof(info.name) - 1);
                }

                it = json.FindMember("start_time");
                if (it != json.MemberEnd() && it->value.IsInt64()) {
                    info.startTime = it->value.GetInt64();
                }

                it = json.FindMember("end_time");
                if (it != json.MemberEnd() && it->value.IsInt64()) {
                    info.endTime = it->value.GetInt64();
                }

                it = json.FindMember("url");
                if (it != json.MemberEnd() && it->value.IsString()) {
                    strncpy(info.url, it->value.GetString(), sizeof(info.url) - 1);
                }

                it = json.FindMember("time_accuracy");
                if (it != json.MemberEnd() && it->value.IsInt()) {
                    info.timeAccuracy = static_cast<TIME_ACCURACY>(it->value.GetInt());
                }
                return info;
            });

            time_t now = time(nullptr);
            std::vector<CompetitionInfo>::iterator it = std::remove_if(_competitions.begin(), _competitions.end(),
                [now](const CompetitionInfo &info) {
                return (info.timeAccuracy != TIME_ACCURACY::UNDETERMINED && info.startTime < now);
            });
            _competitions.erase(it, _competitions.end());

            _tableView->reloadDataInplacement();
            _emptyLabel->setVisible(_competitions.empty());

            return true;
        } while (0);
    }
    catch (std::exception &e) {
        CCLOG("%s %s", __FUNCTION__, e.what());
    }

    return false;
}

ssize_t LatestCompetitionScene::numberOfCellsInTableView(cw::TableView *table) {
    return _competitions.size();
}

float LatestCompetitionScene::tableCellSizeForIndex(cw::TableView *table, ssize_t idx) {
    return 50.0f;
}

cw::TableViewCell *LatestCompetitionScene::tableCellAtIndex(cw::TableView *table, ssize_t idx) {
    typedef cw::TableViewCellEx<std::array<LayerColor *, 2>, std::array<Label *, 2>, ui::Button *> CustomCell;
    CustomCell *cell = (CustomCell *)table->dequeueCell();

    if (cell == nullptr) {
        cell = CustomCell::create();

        Size visibleSize = Director::getInstance()->getVisibleSize();
        const float width = visibleSize.width - 5.0f;

        CustomCell::ExtDataType &ext = cell->getExtData();
        std::array<LayerColor *, 2> &layerColors = std::get<0>(ext);
        std::array<Label *, 2> &label = std::get<1>(ext);
        ui::Button *&detailBtn = std::get<2>(ext);

        layerColors[0] = LayerColor::create(Color4B(0x10, 0x10, 0x10, 0x10), width, 50.0f);
        cell->addChild(layerColors[0]);

        layerColors[1] = LayerColor::create(Color4B(0xC0, 0xC0, 0xC0, 0x10), width, 50.0f);
        cell->addChild(layerColors[1]);

        label[0] = Label::createWithSystemFont("", "Arail", 10);
        label[0]->setColor(Color3B::BLACK);
        cell->addChild(label[0]);
        label[0]->setPosition(Vec2(5.0f, 35.0f));
        label[0]->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);

        label[1] = Label::createWithSystemFont("", "Arail", 10);
        label[1]->setColor(Color3B(0x60, 0x60, 0x60));
        cell->addChild(label[1]);
        label[1]->setPosition(Vec2(5.0f, 15.0f));
        label[1]->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);

        detailBtn = ui::Button::create("source_material/btn_square_highlighted.png", "source_material/btn_square_selected.png");
        detailBtn->setScale9Enabled(true);
        detailBtn->setContentSize(Size(40.0f, 20.0f));
        detailBtn->setTitleFontSize(12);
        detailBtn->setTitleText("详情");
        detailBtn->addClickEventListener(std::bind(&LatestCompetitionScene::onDetailButton, this, std::placeholders::_1));
        cell->addChild(detailBtn);
        detailBtn->setPosition(Vec2(width - 25.0f, 25.0f));
    }

    const CustomCell::ExtDataType &ext = cell->getExtData();
    const std::array<LayerColor *, 2> &layerColors = std::get<0>(ext);
    const std::array<Label *, 2> &label = std::get<1>(ext);
    ui::Button *detailBtn = std::get<2>(ext);

    layerColors[0]->setVisible(!(idx & 1));
    layerColors[1]->setVisible(!!(idx & 1));

    detailBtn->setUserData(reinterpret_cast<void *>(idx));

    const CompetitionInfo &info = _competitions[idx];
    label[0]->setString(info.name);

    struct tm ret = *localtime(&info.startTime);
    std::string date;

    switch (info.timeAccuracy) {
    default:
        date = "具体时间待定";
        break;
    case TIME_ACCURACY::MONTHS:
        date = Common::format("%d年%d月", ret.tm_year + 1900, ret.tm_mon + 1);
        if (info.endTime != 0) {
            date.append("——");
            ret = *localtime(&info.endTime);
            date.append(Common::format("%d年%d月", ret.tm_year + 1900, ret.tm_mon + 1));
        }
        break;
    case TIME_ACCURACY::DAYS:
        date = Common::format("%d年%d月%d日", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday);
        if (info.endTime != 0) {
            date.append("——");
            ret = *localtime(&info.endTime);
            date.append(Common::format("%d年%d月%d日", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday));
        }
        break;
    case TIME_ACCURACY::HONRS:
        date = Common::format("%d年%d月%d日%.2d点", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday, ret.tm_hour);
        if (info.endTime != 0) {
            date.append("——");
            ret = *localtime(&info.endTime);
            date.append(Common::format("%d年%d月%d日%.2d点", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday, ret.tm_hour));
        }
        break;
    case TIME_ACCURACY::MINUTES:
        date = Common::format("%d年%d月%d日%.2d:%.2d", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday, ret.tm_hour, ret.tm_min);
        if (info.endTime != 0) {
            date.append("——");
            ret = *localtime(&info.endTime);
            date.append(Common::format("%d年%d月%d日%.2d:%.2d", ret.tm_year + 1900, ret.tm_mon + 1, ret.tm_mday, ret.tm_hour, ret.tm_min));
        }
        break;
    }
    label[1]->setString(date);

    detailBtn->setVisible(info.url[0] != '\0');

    return cell;
}

void LatestCompetitionScene::onDetailButton(cocos2d::Ref *sender) {
    ui::Button *button = (ui::Button *)sender;
    size_t idx = reinterpret_cast<size_t>(button->getUserData());
    Application::getInstance()->openURL(_competitions[idx].url);
}
<|endoftext|>


<commit_before>/** \brief Utility for updating SQL schemata etc.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2019-2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include "Compiler.h"
#include "FileUtil.h"
#include "DbConnection.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--test] update_directory_path");
}

void SplitIntoDatabaseAndVersion(const std::string &update_filename, std::string * const database, unsigned * const version) {
    const auto first_dot_pos(update_filename.find('.'));
    if (first_dot_pos == std::string::npos or first_dot_pos == 0 or first_dot_pos == update_filename.length() - 1)
        LOG_ERROR("invalid update filename \"" + update_filename + "\"!");

    if (not StringUtil::ToUnsigned(update_filename.substr(first_dot_pos + 1), version))
        LOG_ERROR("bad or missing version in update filename \"" + update_filename + "\"!");

    *database = update_filename.substr(0, first_dot_pos);
}

// The filenames being compared are assumed to have the "structure database.version]*"
bool FileNameCompare(const std::string &filename1, const std::string &filename2) {
    std::string database1;
    unsigned version1;
    SplitIntoDatabaseAndVersion(filename1, &database1, &version1);

    std::string database2;
    unsigned version2;
    SplitIntoDatabaseAndVersion(filename2, &database2, &version2);

    // Compare database names:
    if (database1 < database2)
        return true;
    if (database1 > database2)
        return false;

    return version1 < version2;
}

void LoadAndSortUpdateFilenames(const bool test, const std::string &directory_path, std::vector<std::string> * const update_filenames) {
    FileUtil::Directory directory(directory_path, "[^.]+\\.\\d+");
    for (const auto &entry : directory)
        update_filenames->emplace_back(entry.getName());

    std::sort(update_filenames->begin(), update_filenames->end(), FileNameCompare);

    if (test) {
        std::cerr << "Sorted filenames:\n";
        for (const auto &filename : *update_filenames)
            std::cerr << filename << '\n';
        std::exit(0);
    }
}

void ApplyUpdate(DbConnection * const db_connection, const std::string &update_directory_path, const std::string &update_filename) {
    std::string database;
    unsigned update_version;
    SplitIntoDatabaseAndVersion(update_filename, &database, &update_version);

    if (not db_connection->mySQLDatabaseExists(database)) {
        LOG_WARNING("database \"" + database + "\" does not exist, skipping file " + update_filename);
        return;
    }

    DbTransaction transaction(db_connection); // No new scope required as the transaction is supposed to last until the end
                                              // of this function anyway!

    unsigned current_version(0);
    db_connection->queryOrDie("SELECT version FROM ub_tools.database_versions WHERE database_name='"
                              + db_connection->escapeString(database) + "'");
    DbResultSet result_set(db_connection->getLastResultSet());
    if (result_set.empty()) {
        db_connection->queryOrDie("INSERT INTO ub_tools.database_versions (database_name,version) VALUES ('"
                                  + db_connection->escapeString(database) + "',0)");
            LOG_INFO("Created a new entry for database \"" + database + " in ub_tools.database_versions.");
    } else
        current_version = StringUtil::ToUnsigned(result_set.getNextRow()["version"]);
    if (update_version <= current_version)
        return;

    // Sanity check:
    if (unlikely(update_version != current_version + 1))
        LOG_ERROR("update version is " + std::to_string(update_version) + ", current version is "
                  + std::to_string(current_version) + " for database \"" + database + "\"!");

    LOG_INFO("applying update " + std::to_string(update_version) + " to database \"" + database + "\".");
    db_connection->queryFileOrDie(update_directory_path + "/" + update_filename);
    db_connection->queryOrDie("UPDATE ub_tools.database_versions SET version=" + std::to_string(update_version)
                              + " WHERE database_name='" + db_connection->escapeString(database) + "'");
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 2 and argc != 3)
        Usage();

    bool test(false);
    if (argc == 3) {
        if (std::strcmp(argv[1], "--test") != 0)
            Usage();
        test = true;
        --argc, ++argv;
    }

    std::vector<std::string> update_filenames;
    const std::string update_directory_path(argv[1]);
    LoadAndSortUpdateFilenames(test, update_directory_path, &update_filenames);

    DbConnection db_connection;
    const std::string system_table_name("database_versions");
    if (not db_connection.tableExists("ub_tools", system_table_name)) {
        db_connection.queryOrDie("CREATE TABLE ub_tools." + system_table_name + " (version INT UNSIGNED NOT NULL,"
                                 "database_name VARCHAR(64) NOT NULL,UNIQUE (database_name)) "
                                 "CHARACTER SET utf8mb4 COLLATE utf8mb4_bin");
        LOG_INFO("Created the ub_tools." + system_table_name + " table.");
    }

    for (const auto &update_filename : update_filenames)
        ApplyUpdate(&db_connection, update_directory_path, update_filename);

    return EXIT_SUCCESS;
}
<commit_msg>Agreed.<commit_after>/** \brief Utility for updating SQL schemata etc.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2019-2020 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include "Compiler.h"
#include "FileUtil.h"
#include "DbConnection.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    ::Usage("[--test] update_directory_path");
}

void SplitIntoDatabaseAndVersion(const std::string &update_filename, std::string * const database, unsigned * const version) {
    const auto first_dot_pos(update_filename.find('.'));
    if (first_dot_pos == std::string::npos or first_dot_pos == 0 or first_dot_pos == update_filename.length() - 1)
        LOG_ERROR("invalid update filename \"" + update_filename + "\"!");

    if (not StringUtil::ToUnsigned(update_filename.substr(first_dot_pos + 1), version))
        LOG_ERROR("bad or missing version in update filename \"" + update_filename + "\"!");

    *database = update_filename.substr(0, first_dot_pos);
}

// The filenames being compared are assumed to have the "structure database.version]*"
bool FileNameCompare(const std::string &filename1, const std::string &filename2) {
    std::string database1;
    unsigned version1;
    SplitIntoDatabaseAndVersion(filename1, &database1, &version1);

    std::string database2;
    unsigned version2;
    SplitIntoDatabaseAndVersion(filename2, &database2, &version2);

    // Compare database names:
    if (database1 < database2)
        return true;
    if (database1 > database2)
        return false;

    return version1 < version2;
}

void LoadAndSortUpdateFilenames(const bool test, const std::string &directory_path, std::vector<std::string> * const update_filenames) {
    FileUtil::Directory directory(directory_path, "[^.]+\\.\\d+");
    for (const auto &entry : directory)
        update_filenames->emplace_back(entry.getName());

    std::sort(update_filenames->begin(), update_filenames->end(), FileNameCompare);

    if (test) {
        std::cerr << "Sorted filenames:\n";
        for (const auto &filename : *update_filenames)
            std::cerr << filename << '\n';
        std::exit(0);
    }
}

void ApplyUpdate(DbConnection * const db_connection, const std::string &update_directory_path, const std::string &update_filename) {
    std::string database;
    unsigned update_version;
    SplitIntoDatabaseAndVersion(update_filename, &database, &update_version);

    if (not db_connection->mySQLDatabaseExists(database)) {
        LOG_INFO("database \"" + database + "\" does not exist, skipping file " + update_filename);
        return;
    }

    DbTransaction transaction(db_connection); // No new scope required as the transaction is supposed to last until the end
                                              // of this function anyway!

    unsigned current_version(0);
    db_connection->queryOrDie("SELECT version FROM ub_tools.database_versions WHERE database_name='"
                              + db_connection->escapeString(database) + "'");
    DbResultSet result_set(db_connection->getLastResultSet());
    if (result_set.empty()) {
        db_connection->queryOrDie("INSERT INTO ub_tools.database_versions (database_name,version) VALUES ('"
                                  + db_connection->escapeString(database) + "',0)");
            LOG_INFO("Created a new entry for database \"" + database + " in ub_tools.database_versions.");
    } else
        current_version = StringUtil::ToUnsigned(result_set.getNextRow()["version"]);
    if (update_version <= current_version)
        return;

    // Sanity check:
    if (unlikely(update_version != current_version + 1))
        LOG_ERROR("update version is " + std::to_string(update_version) + ", current version is "
                  + std::to_string(current_version) + " for database \"" + database + "\"!");

    LOG_INFO("applying update " + std::to_string(update_version) + " to database \"" + database + "\".");
    db_connection->queryFileOrDie(update_directory_path + "/" + update_filename);
    db_connection->queryOrDie("UPDATE ub_tools.database_versions SET version=" + std::to_string(update_version)
                              + " WHERE database_name='" + db_connection->escapeString(database) + "'");
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc != 2 and argc != 3)
        Usage();

    bool test(false);
    if (argc == 3) {
        if (std::strcmp(argv[1], "--test") != 0)
            Usage();
        test = true;
        --argc, ++argv;
    }

    std::vector<std::string> update_filenames;
    const std::string update_directory_path(argv[1]);
    LoadAndSortUpdateFilenames(test, update_directory_path, &update_filenames);

    DbConnection db_connection;
    const std::string system_table_name("database_versions");
    if (not db_connection.tableExists("ub_tools", system_table_name)) {
        db_connection.queryOrDie("CREATE TABLE ub_tools." + system_table_name + " (version INT UNSIGNED NOT NULL,"
                                 "database_name VARCHAR(64) NOT NULL,UNIQUE (database_name)) "
                                 "CHARACTER SET utf8mb4 COLLATE utf8mb4_bin");
        LOG_INFO("Created the ub_tools." + system_table_name + " table.");
    }

    for (const auto &update_filename : update_filenames)
        ApplyUpdate(&db_connection, update_directory_path, update_filename);

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <functional>
#include <map>
#include <string>

#include <ace/Recursive_Thread_Mutex.h>
#include <ace/Guard_T.h>

#include <geode/CacheFactory.hpp>
#include <geode/Cache.hpp>
#include <geode/SystemProperties.hpp>
#include <geode/PoolManager.hpp>

#include "config.h"
#include "version.h"

#include "CacheImpl.hpp"
#include "CppCacheLibrary.hpp"
#include "PoolAttributes.hpp"

#include "CacheConfig.hpp"
#include "DistributedSystemImpl.hpp"
#include "SerializationRegistry.hpp"
#include "PdxType.hpp"
#include "PdxTypeRegistry.hpp"
#include "DiskVersionTag.hpp"
#include "TXCommitMessage.hpp"
#include "PdxHelper.hpp"

#define DEFAULT_CACHE_NAME "default_GeodeCache"

extern ACE_Recursive_Thread_Mutex* g_disconnectLock;

namespace apache {
namespace geode {
namespace client {

CacheFactoryPtr CacheFactory::createCacheFactory(
    const PropertiesPtr& configPtr) {
  return std::make_shared<CacheFactory>(configPtr);
}

void CacheFactory::create_(const char* name, const char* id_data,
                           CachePtr& cptr, bool readPdxSerialized) {
  cptr = nullptr;
  if (name == nullptr) {
    throw IllegalArgumentException("CacheFactory::create: name is nullptr");
  }
  if (name[0] == '\0') {
    name = "NativeCache";
  }

  cptr = std::make_shared<Cache>(name, dsProp, ignorePdxUnreadFields,
                                 readPdxSerialized);
}  // namespace client

const char* CacheFactory::getVersion() { return PRODUCT_VERSION; }

const char* CacheFactory::getProductDescription() {
  return PRODUCT_VENDOR " " PRODUCT_NAME " " PRODUCT_VERSION " (" PRODUCT_BITS
                        ") " PRODUCT_BUILDDATE;
}

CacheFactory::CacheFactory() {
  ignorePdxUnreadFields = false;
  pdxReadSerialized = false;
  dsProp = nullptr;
}

CacheFactory::CacheFactory(const PropertiesPtr dsProps) {
  ignorePdxUnreadFields = false;
  pdxReadSerialized = false;
  this->dsProp = dsProps;
}

CachePtr CacheFactory::create() {
  ACE_Guard<ACE_Recursive_Thread_Mutex> connectGuard(*g_disconnectLock);

  LOGFINE("CacheFactory called DistributedSystem::connect");
  auto cache = create(DEFAULT_CACHE_NAME, nullptr);

  auto& cacheImpl = cache->m_cacheImpl;
  auto& serializationRegistry = cacheImpl->getSerializationRegistry();
  auto& pdxTypeRegistry = cacheImpl->getPdxTypeRegistry();
  auto& memberListForVersionStamp =
      std::ref(*(cacheImpl->getMemberListForVersionStamp()));

  serializationRegistry->addType2(
      std::bind(TXCommitMessage::create, memberListForVersionStamp));

  serializationRegistry->addType(
      GeodeTypeIds::PdxType,
      std::bind(PdxType::CreateDeserializable, pdxTypeRegistry));

  serializationRegistry->addType(
      std::bind(VersionTag::createDeserializable, memberListForVersionStamp));

  serializationRegistry->addType2(
      GeodeTypeIdsImpl::DiskVersionTag,
      std::bind(DiskVersionTag::createDeserializable,
                memberListForVersionStamp));

  serializationRegistry->setPdxTypeHandler([](DataInput& dataInput) {
    return PdxHelper::deserializePdx(dataInput, false);
  });

  pdxTypeRegistry->setPdxIgnoreUnreadFields(cache->getPdxIgnoreUnreadFields());
  pdxTypeRegistry->setPdxReadSerialized(cache->getPdxReadSerialized());

  return cache;
}

CachePtr CacheFactory::create(const char* name,
                              const CacheAttributesPtr& attrs /*= nullptr*/) {
  ACE_Guard<ACE_Recursive_Thread_Mutex> connectGuard(*g_disconnectLock);

  CachePtr cptr;
  create_(name, "", cptr, pdxReadSerialized);
  cptr->m_cacheImpl->setAttributes(attrs);
  try {
    const char* cacheXml =
        cptr->getDistributedSystem().getSystemProperties().cacheXMLFile();
    if (cacheXml != 0 && strlen(cacheXml) > 0) {
      cptr->initializeDeclarativeCache(cacheXml);
    } else {
      cptr->m_cacheImpl->initServices();
    }
  } catch (const apache::geode::client::RegionExistsException&) {
    LOGWARN("Attempt to create existing regions declaratively");
  } catch (const apache::geode::client::Exception&) {
    if (!cptr->isClosed()) {
      cptr->close();
      cptr = nullptr;
    }
    throw;
  } catch (...) {
    if (!cptr->isClosed()) {
      cptr->close();
      cptr = nullptr;
    }
    throw apache::geode::client::UnknownException(
        "Exception thrown in CacheFactory::create");
  }

  return cptr;
}

CacheFactory::~CacheFactory() {}

CacheFactoryPtr CacheFactory::set(const char* name, const char* value) {
  if (this->dsProp == nullptr) {
    this->dsProp = Properties::create();
  }
  this->dsProp->insert(name, value);
  return shared_from_this();
}

CacheFactoryPtr CacheFactory::setPdxIgnoreUnreadFields(bool ignore) {
  ignorePdxUnreadFields = ignore;
  return shared_from_this();
}

CacheFactoryPtr CacheFactory::setPdxReadSerialized(bool prs) {
  pdxReadSerialized = prs;
  return shared_from_this();
}
}  // namespace client
}  // namespace geode
}  // namespace apache
<commit_msg>GEODE-3630: Fixes compiler errors on gcc.<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <functional>
#include <map>
#include <string>

#include <ace/Recursive_Thread_Mutex.h>
#include <ace/Guard_T.h>

#include <geode/CacheFactory.hpp>
#include <geode/Cache.hpp>
#include <geode/SystemProperties.hpp>
#include <geode/PoolManager.hpp>

#include "config.h"
#include "version.h"

#include "CacheImpl.hpp"
#include "CppCacheLibrary.hpp"
#include "PoolAttributes.hpp"

#include "CacheConfig.hpp"
#include "DistributedSystemImpl.hpp"
#include "SerializationRegistry.hpp"
#include "PdxType.hpp"
#include "PdxTypeRegistry.hpp"
#include "DiskVersionTag.hpp"
#include "TXCommitMessage.hpp"
#include "PdxHelper.hpp"

#define DEFAULT_CACHE_NAME "default_GeodeCache"

extern ACE_Recursive_Thread_Mutex* g_disconnectLock;

namespace apache {
namespace geode {
namespace client {

CacheFactoryPtr CacheFactory::createCacheFactory(
    const PropertiesPtr& configPtr) {
  return std::make_shared<CacheFactory>(configPtr);
}

void CacheFactory::create_(const char* name, const char* id_data,
                           CachePtr& cptr, bool readPdxSerialized) {
  cptr = nullptr;
  if (name == nullptr) {
    throw IllegalArgumentException("CacheFactory::create: name is nullptr");
  }
  if (name[0] == '\0') {
    name = "NativeCache";
  }

  cptr = std::make_shared<Cache>(name, dsProp, ignorePdxUnreadFields,
                                 readPdxSerialized);
}  // namespace client

const char* CacheFactory::getVersion() { return PRODUCT_VERSION; }

const char* CacheFactory::getProductDescription() {
  return PRODUCT_VENDOR " " PRODUCT_NAME " " PRODUCT_VERSION " (" PRODUCT_BITS
                        ") " PRODUCT_BUILDDATE;
}

CacheFactory::CacheFactory() {
  ignorePdxUnreadFields = false;
  pdxReadSerialized = false;
  dsProp = nullptr;
}

CacheFactory::CacheFactory(const PropertiesPtr dsProps) {
  ignorePdxUnreadFields = false;
  pdxReadSerialized = false;
  this->dsProp = dsProps;
}

CachePtr CacheFactory::create() {
  ACE_Guard<ACE_Recursive_Thread_Mutex> connectGuard(*g_disconnectLock);

  LOGFINE("CacheFactory called DistributedSystem::connect");
  auto cache = create(DEFAULT_CACHE_NAME, nullptr);

  auto& cacheImpl = cache->m_cacheImpl;
  const auto& serializationRegistry = cacheImpl->getSerializationRegistry();
  const auto& pdxTypeRegistry = cacheImpl->getPdxTypeRegistry();
  const auto& memberListForVersionStamp =
      std::ref(*(cacheImpl->getMemberListForVersionStamp()));

  serializationRegistry->addType2(
      std::bind(TXCommitMessage::create, memberListForVersionStamp));

  serializationRegistry->addType(
      GeodeTypeIds::PdxType,
      std::bind(PdxType::CreateDeserializable, pdxTypeRegistry));

  serializationRegistry->addType(
      std::bind(VersionTag::createDeserializable, memberListForVersionStamp));

  serializationRegistry->addType2(
      GeodeTypeIdsImpl::DiskVersionTag,
      std::bind(DiskVersionTag::createDeserializable,
                memberListForVersionStamp));

  serializationRegistry->setPdxTypeHandler([](DataInput& dataInput) {
    return PdxHelper::deserializePdx(dataInput, false);
  });

  pdxTypeRegistry->setPdxIgnoreUnreadFields(cache->getPdxIgnoreUnreadFields());
  pdxTypeRegistry->setPdxReadSerialized(cache->getPdxReadSerialized());

  return cache;
}

CachePtr CacheFactory::create(const char* name,
                              const CacheAttributesPtr& attrs /*= nullptr*/) {
  ACE_Guard<ACE_Recursive_Thread_Mutex> connectGuard(*g_disconnectLock);

  CachePtr cptr;
  create_(name, "", cptr, pdxReadSerialized);
  cptr->m_cacheImpl->setAttributes(attrs);
  try {
    const char* cacheXml =
        cptr->getDistributedSystem().getSystemProperties().cacheXMLFile();
    if (cacheXml != 0 && strlen(cacheXml) > 0) {
      cptr->initializeDeclarativeCache(cacheXml);
    } else {
      cptr->m_cacheImpl->initServices();
    }
  } catch (const apache::geode::client::RegionExistsException&) {
    LOGWARN("Attempt to create existing regions declaratively");
  } catch (const apache::geode::client::Exception&) {
    if (!cptr->isClosed()) {
      cptr->close();
      cptr = nullptr;
    }
    throw;
  } catch (...) {
    if (!cptr->isClosed()) {
      cptr->close();
      cptr = nullptr;
    }
    throw apache::geode::client::UnknownException(
        "Exception thrown in CacheFactory::create");
  }

  return cptr;
}

CacheFactory::~CacheFactory() {}

CacheFactoryPtr CacheFactory::set(const char* name, const char* value) {
  if (this->dsProp == nullptr) {
    this->dsProp = Properties::create();
  }
  this->dsProp->insert(name, value);
  return shared_from_this();
}

CacheFactoryPtr CacheFactory::setPdxIgnoreUnreadFields(bool ignore) {
  ignorePdxUnreadFields = ignore;
  return shared_from_this();
}

CacheFactoryPtr CacheFactory::setPdxReadSerialized(bool prs) {
  pdxReadSerialized = prs;
  return shared_from_this();
}
}  // namespace client
}  // namespace geode
}  // namespace apache
<|endoftext|>


<commit_before>#include "audio_engine.h"

using namespace Halley;

AudioEngine::AudioEngine()
	: running(true)
	, needsBuffer(true)
{
}

AudioCallback AudioEngine::getCallback()
{
	return [this] (gsl::span<AudioSamplePack> dst) { serviceAudio(dst); };
}

void AudioEngine::playUI(std::shared_ptr<AudioClip> clip, float volume, float pan)
{
	// TODO
}

void AudioEngine::run()
{
	{
		std::unique_lock<std::mutex> lock(mutex);
		while (!needsBuffer && running) {
			backBufferCondition.wait(lock);
		}
	}

	if (!running) {
		return;
	}

	generateBuffer();
}

void AudioEngine::start(AudioSpec s)
{
	spec = s;
	backBuffer.samples.resize(spec.bufferSize * spec.numChannels / 16);
}

void AudioEngine::stop()
{
	running = false;
	needsBuffer = false;
	backBufferCondition.notify_one();
}

void AudioEngine::serviceAudio(gsl::span<AudioSamplePack> buffer)
{
	Expects(buffer.size() == backBuffer.samples.size());

	for (ptrdiff_t i = 0; i < buffer.size(); ++i) {
		gsl::span<const float> src = backBuffer.samples[i].samples;
		gsl::span<float> dst = buffer[i].samples;
		for (size_t j = 0; j < 16; ++j) {
			dst[j] = src[j];
		}
	}

	needsBuffer = true;
	backBufferCondition.notify_one();
}

void AudioEngine::generateBuffer()
{
	// TODO: make this actually work instead of generating a sine wave

	constexpr float scale = 6.283185307179586476925286766559f / 256.0f;

	for (size_t i = 0; i < backBuffer.samples.size(); ++i) {
		gsl::span<float> dst = backBuffer.samples[i].samples;
		for (size_t j = 0; j < 16; j += 2) {
			size_t pos = j + i * 16;
			float amplitude = 0.25f * ::sin(pos * scale);
			dst[j] = amplitude;
			dst[j + 1] = amplitude;
		}
	}
}
<commit_msg><commit_after>#include "audio_engine.h"
#include <cmath>

using namespace Halley;

AudioEngine::AudioEngine()
	: running(true)
	, needsBuffer(true)
{
}

AudioCallback AudioEngine::getCallback()
{
	return [this] (gsl::span<AudioSamplePack> dst) { serviceAudio(dst); };
}

void AudioEngine::playUI(std::shared_ptr<AudioClip> clip, float volume, float pan)
{
	// TODO
}

void AudioEngine::run()
{
	{
		std::unique_lock<std::mutex> lock(mutex);
		while (!needsBuffer && running) {
			backBufferCondition.wait(lock);
		}
	}

	if (!running) {
		return;
	}

	generateBuffer();
}

void AudioEngine::start(AudioSpec s)
{
	spec = s;
	backBuffer.samples.resize(spec.bufferSize * spec.numChannels / 16);
}

void AudioEngine::stop()
{
	running = false;
	needsBuffer = false;
	backBufferCondition.notify_one();
}

void AudioEngine::serviceAudio(gsl::span<AudioSamplePack> buffer)
{
	Expects(buffer.size() == backBuffer.samples.size());

	for (ptrdiff_t i = 0; i < buffer.size(); ++i) {
		gsl::span<const float> src = backBuffer.samples[i].samples;
		gsl::span<float> dst = buffer[i].samples;
		for (size_t j = 0; j < 16; ++j) {
			dst[j] = src[j];
		}
	}

	needsBuffer = true;
	backBufferCondition.notify_one();
}

void AudioEngine::generateBuffer()
{
	// TODO: make this actually work instead of generating a sine wave

	constexpr float scale = 6.283185307179586476925286766559f / 256.0f;

	for (size_t i = 0; i < backBuffer.samples.size(); ++i) {
		gsl::span<float> dst = backBuffer.samples[i].samples;
		for (size_t j = 0; j < 16; j += 2) {
			size_t pos = j + i * 16;
			float amplitude = 0.25f * ::sin(pos * scale);
			dst[j] = amplitude;
			dst[j + 1] = amplitude;
		}
	}
}
<|endoftext|>


<commit_before>/*
*
* Copyright 2013 Telefonica Investigacion y Desarrollo, S.A.U
*
* This file is part of Orion Context Broker.
*
* Orion Context Broker is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Orion Context Broker 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 Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Orion Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* iot_support at tid dot es
*
* Author: Ken Zangelin
*/
#include "gtest/gtest.h"

#include "logMsg/logMsg.h"
#include "logMsg/traceLevels.h"

#include "ngsi/Request.h"

typedef struct Req
{
   RequestType  rt;
   const char*  string;
} Req;

/* ****************************************************************************
*
* requestType -
*/
TEST(Request, requestType)
{
  Req   req[] =
  {
    { RegisterContext,                                 "RegisterContextRequest"                                 },
    { DiscoverContextAvailability,                     "DiscoverContextAvailabilityRequest"                     },
    { SubscribeContextAvailability,                    "SubscribeContextAvailabilityRequest"                    },
    { RtSubscribeContextAvailabilityResponse,          "SubscribeContextAvailabilityResponse"                   },
    { UpdateContextAvailabilitySubscription,           "UpdateContextAvailabilitySubscriptionRequest"           },
    { RtUpdateContextAvailabilitySubscriptionResponse, "UpdateContextAvailabilitySubscriptionResponse"          },
    { UnsubscribeContextAvailability,                  "UnsubscribeContextAvailabilityRequest"                  },
    { RtUnsubscribeContextAvailabilityResponse,        "UnsubscribeContextAvailabilityResponse"                 },
    { NotifyContextAvailability,                       "NotifyContextAvailabilityRequest"                       },

    { QueryContext,                                "QueryContextRequest"                                    },
    { SubscribeContext,                            "SubscribeContextRequest"                                },
    { UpdateContextSubscription,                   "UpdateContextSubscriptionRequest"                       },
    { UnsubscribeContext,                          "UnsubscribeContextRequest"                              },
    { NotifyContext,                               "NotifyContextRequest"                                   },
    { UpdateContext,                               "UpdateContextRequest"                                   },

    { ContextEntitiesByEntityId,                   "ContextEntitiesByEntityId"                              },
    { ContextEntityAttributes,                     "ContextEntityAttributes"                                },
    { ContextEntityTypes,                          "ContextEntityTypes"                                     },
    { ContextEntityTypeAttributeContainer,         "ContextEntityTypeAttributeContainer"                    },
    { ContextEntityTypeAttribute,                  "ContextEntityTypeAttribute"                             },
    { EntityByIdAttributeByName,                   "EntityByIdAttributeByName"                              },
    { Ngsi9SubscriptionsConvOp,                    "Ngsi9SubscriptionsConvOp"                               },

    { IndividualContextEntity,                     "IndividualContextEntity"                                },
    { IndividualContextEntityAttributes,           "IndividualContextEntityAttributes"                      },
    { IndividualContextEntityAttribute,            "IndividualContextEntityAttribute"                       },
    { AttributeValueInstance,                      "AttributeValueInstance"                                 },
    { UpdateContextElement,                        "UpdateContextElement"                                   },
    { AppendContextElement,                        "AppendContextElement"                                   },
    { UpdateContextAttribute,                      "UpdateContextAttribute"                                 },
    { Ngsi10ContextEntityTypes,                    "Ngsi10ContextEntityTypes"                               },
    { Ngsi10ContextEntityTypesAttributeContainer,  "Ngsi10ContextEntityTypesAttributeContainer"             },
    { Ngsi10ContextEntityTypesAttribute,           "Ngsi10ContextEntityTypesAttribute"                      },
    { Ngsi10SubscriptionsConvOp,                   "Ngsi10SubscriptionsConvOp"                              },

    { LogTraceRequest,                             "Log"                                                    },
    { VersionRequest,                              "Version"                                                },
    { StatisticsRequest,                           "Statistics"                                             },
    { ExitRequest,                                 "Exit"                                                   },
    { LeakRequest,                                 "Leak"                                                   },
    { RegisterResponse,                            "RegisterContextResponse"                                },

    { RtSubscribeResponse,                         "SubscribeResponse"                                      },
    { RtSubscribeError,                            "SubscribeError"                                         },

    { EntityTypes,                                 "EntityTypes"                                            },
    { AttributesForEntityType,                     "AttributesForEntityType"                                },
    { RtEntityTypesResponse,                       "EntityTypesResponse"                                    },
    { RtAttributesForEntityTypeResponse,           "AttributesForEntityTypeResponse"                        },

    { InvalidRequest,                              "InvalidRequest"                                         },

  };

  for (unsigned int ix = 0; ix < sizeof(req) / sizeof(req[0]); ++ix)
  {
    EXPECT_STREQ(req[ix].string, requestType(req[ix].rt));
  }

  RequestType rt = (RequestType) (InvalidRequest + 1);
  EXPECT_STREQ("", requestType(rt));
}
<commit_msg>Fixed an error in unit tests due to recent changes (Log->LogTrace+LogLevel)<commit_after>/*
*
* Copyright 2013 Telefonica Investigacion y Desarrollo, S.A.U
*
* This file is part of Orion Context Broker.
*
* Orion Context Broker is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Orion Context Broker 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 Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Orion Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* iot_support at tid dot es
*
* Author: Ken Zangelin
*/
#include "gtest/gtest.h"

#include "logMsg/logMsg.h"
#include "logMsg/traceLevels.h"

#include "ngsi/Request.h"

typedef struct Req
{
   RequestType  rt;
   const char*  string;
} Req;

/* ****************************************************************************
*
* requestType -
*/
TEST(Request, requestType)
{
  Req   req[] =
  {
    { RegisterContext,                                 "RegisterContextRequest"                                 },
    { DiscoverContextAvailability,                     "DiscoverContextAvailabilityRequest"                     },
    { SubscribeContextAvailability,                    "SubscribeContextAvailabilityRequest"                    },
    { RtSubscribeContextAvailabilityResponse,          "SubscribeContextAvailabilityResponse"                   },
    { UpdateContextAvailabilitySubscription,           "UpdateContextAvailabilitySubscriptionRequest"           },
    { RtUpdateContextAvailabilitySubscriptionResponse, "UpdateContextAvailabilitySubscriptionResponse"          },
    { UnsubscribeContextAvailability,                  "UnsubscribeContextAvailabilityRequest"                  },
    { RtUnsubscribeContextAvailabilityResponse,        "UnsubscribeContextAvailabilityResponse"                 },
    { NotifyContextAvailability,                       "NotifyContextAvailabilityRequest"                       },

    { QueryContext,                                "QueryContextRequest"                                    },
    { SubscribeContext,                            "SubscribeContextRequest"                                },
    { UpdateContextSubscription,                   "UpdateContextSubscriptionRequest"                       },
    { UnsubscribeContext,                          "UnsubscribeContextRequest"                              },
    { NotifyContext,                               "NotifyContextRequest"                                   },
    { UpdateContext,                               "UpdateContextRequest"                                   },

    { ContextEntitiesByEntityId,                   "ContextEntitiesByEntityId"                              },
    { ContextEntityAttributes,                     "ContextEntityAttributes"                                },
    { ContextEntityTypes,                          "ContextEntityTypes"                                     },
    { ContextEntityTypeAttributeContainer,         "ContextEntityTypeAttributeContainer"                    },
    { ContextEntityTypeAttribute,                  "ContextEntityTypeAttribute"                             },
    { EntityByIdAttributeByName,                   "EntityByIdAttributeByName"                              },
    { Ngsi9SubscriptionsConvOp,                    "Ngsi9SubscriptionsConvOp"                               },

    { IndividualContextEntity,                     "IndividualContextEntity"                                },
    { IndividualContextEntityAttributes,           "IndividualContextEntityAttributes"                      },
    { IndividualContextEntityAttribute,            "IndividualContextEntityAttribute"                       },
    { AttributeValueInstance,                      "AttributeValueInstance"                                 },
    { UpdateContextElement,                        "UpdateContextElement"                                   },
    { AppendContextElement,                        "AppendContextElement"                                   },
    { UpdateContextAttribute,                      "UpdateContextAttribute"                                 },
    { Ngsi10ContextEntityTypes,                    "Ngsi10ContextEntityTypes"                               },
    { Ngsi10ContextEntityTypesAttributeContainer,  "Ngsi10ContextEntityTypesAttributeContainer"             },
    { Ngsi10ContextEntityTypesAttribute,           "Ngsi10ContextEntityTypesAttribute"                      },
    { Ngsi10SubscriptionsConvOp,                   "Ngsi10SubscriptionsConvOp"                              },

    { LogTraceRequest,                             "LogTrace"                                               },
    { LogLevelRequest,                             "LogLevel"                                               },
    { VersionRequest,                              "Version"                                                },
    { StatisticsRequest,                           "Statistics"                                             },
    { ExitRequest,                                 "Exit"                                                   },
    { LeakRequest,                                 "Leak"                                                   },
    { RegisterResponse,                            "RegisterContextResponse"                                },

    { RtSubscribeResponse,                         "SubscribeResponse"                                      },
    { RtSubscribeError,                            "SubscribeError"                                         },

    { EntityTypes,                                 "EntityTypes"                                            },
    { AttributesForEntityType,                     "AttributesForEntityType"                                },
    { RtEntityTypesResponse,                       "EntityTypesResponse"                                    },
    { RtAttributesForEntityTypeResponse,           "AttributesForEntityTypeResponse"                        },

    { InvalidRequest,                              "InvalidRequest"                                         },

  };

  for (unsigned int ix = 0; ix < sizeof(req) / sizeof(req[0]); ++ix)
  {
    EXPECT_STREQ(req[ix].string, requestType(req[ix].rt));
  }

  RequestType rt = (RequestType) (InvalidRequest + 1);
  EXPECT_STREQ("", requestType(rt));
}
<|endoftext|>


<commit_before>#include "Exception.h"

using namespace CppUnit;

const std::string
CppUnit::Exception::UNKNOWNFILENAME =
  "<unknown>";
const int CppUnit::Exception::UNKNOWNLINENUMBER = -1;

/// Construct the exception
CppUnit::Exception::Exception (const Exception& other)
  : exception (other)
{
  m_message       = other.m_message;
  m_lineNumber    = other.m_lineNumber;
  m_fileName      = other.m_fileName;
}

CppUnit::Exception::Exception (std::string message, long lineNumber, std::string fileName)
  : m_message (message), m_lineNumber (lineNumber), m_fileName (fileName)
{}

/// Destruct the exception
CppUnit::Exception::~Exception ()
{}

/// Perform an assignment
Exception&
CppUnit::Exception::operator= (const Exception& other)
{
  exception::operator= (other);

  if (&other != this) {
    m_message       = other.m_message;
    m_lineNumber    = other.m_lineNumber;
    m_fileName      = other.m_fileName;
  }

  return *this;
}

/// Return descriptive message
const char*
CppUnit::Exception::what() const throw ()
{ return m_message.c_str (); }

/// The line on which the error occurred
long
CppUnit::Exception::lineNumber ()
{ return m_lineNumber; }

/// The file in which the error occurred
std::string
CppUnit::Exception::fileName ()
{ return m_fileName; }

<commit_msg>code beautification.<commit_after>#include "Exception.h"

using namespace CppUnit;

const std::string
CppUnit::Exception::UNKNOWNFILENAME =
  "<unknown>";
const int CppUnit::Exception::UNKNOWNLINENUMBER = -1;

/// Construct the exception
CppUnit::Exception::Exception (const Exception& other)
  : exception (other)
{
  m_message       = other.m_message;
  m_lineNumber    = other.m_lineNumber;
  m_fileName      = other.m_fileName;
}

CppUnit::Exception::Exception (std::string message, long lineNumber, std::string fileName)
  : m_message (message), m_lineNumber (lineNumber), m_fileName (fileName)
{
}

/// Destruct the exception
CppUnit::Exception::~Exception ()
{}

/// Perform an assignment
Exception&
CppUnit::Exception::operator= (const Exception& other)
{
  exception::operator= (other);

  if (&other != this) {
    m_message       = other.m_message;
    m_lineNumber    = other.m_lineNumber;
    m_fileName      = other.m_fileName;
  }

  return *this;
}

/// Return descriptive message
const char*
CppUnit::Exception::what() const throw ()
{ return m_message.c_str (); }

/// The line on which the error occurred
long
CppUnit::Exception::lineNumber ()
{ return m_lineNumber; }

/// The file in which the error occurred
std::string
CppUnit::Exception::fileName ()
{ return m_fileName; }

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* @file
 * EventQueue interfaces
 */

#ifndef __EVENTQ_HH__
#define __EVENTQ_HH__

#include <assert.h>

#include <algorithm>
#include <map>
#include <string>
#include <vector>

#include "sim/host.hh"	// for Tick

#include "base/fast_alloc.hh"
#include "sim/serialize.hh"
#include "base/trace.hh"

class EventQueue;	// forward declaration

/*
 * An item on an event queue.  The action caused by a given
 * event is specified by deriving a subclass and overriding the
 * process() member function.
 */
class Event : public Serializable, public FastAlloc
{
    friend class EventQueue;

  private:
    /// queue to which this event belongs (though it may or may not be
    /// scheduled on this queue yet)
    EventQueue *queue;

    Event *next;

    Tick _when;	//!< timestamp when event should be processed
    int _priority;	//!< event priority
    char _flags;

  protected:
    enum Flags {
        None = 0x0,
        Squashed = 0x1,
        Scheduled = 0x2,
        AutoDelete = 0x4,
        AutoSerialize = 0x8
    };

    bool getFlags(Flags f) const { return (_flags & f) == f; }
    void setFlags(Flags f) { _flags |= f; }
    void clearFlags(Flags f) { _flags &= ~f; }

  protected:
    EventQueue *theQueue() const { return queue; }

#if TRACING_ON
    Tick when_created;	//!< Keep track of creation time For debugging
    Tick when_scheduled;	//!< Keep track of creation time For debugging

    virtual void trace(const char *action);	//!< trace event activity
#else
    void trace(const char *) {}
#endif

    unsigned annotated_value;

  public:

    /// Event priorities, to provide tie-breakers for events scheduled
    /// at the same cycle.  Most events are scheduled at the default
    /// priority; these values are used to control events that need to
    /// be ordered within a cycle.
    enum Priority {
        /// Breakpoints should happen before anything else, so we
        /// don't miss any action when debugging.
        Debug_Break_Pri		= -100,

        /// For some reason "delayed" inter-cluster writebacks are
        /// scheduled before regular writebacks (which have default
        /// priority).  Steve?
        Delayed_Writeback_Pri	=   -1,

        /// Default is zero for historical reasons.
        Default_Pri		=    0,

        /// CPU switches schedule the new CPU's tick event for the
        /// same cycle (after unscheduling the old CPU's tick event).
        /// The switch needs to come before any tick events to make
        /// sure we don't tick both CPUs in the same cycle.
        CPU_Switch_Pri		=   31,

        /// Serailization needs to occur before tick events also, so
        /// that a serialize/unserialize is identical to an on-line
        /// CPU switch.
        Serialize_Pri		=   32,

        /// CPU ticks must come after other associated CPU events
        /// (such as writebacks).
        CPU_Tick_Pri		=   50,

        /// Statistics events (dump, reset, etc.) come after
        /// everything else, but before exit.
        Stat_Event_Pri		=   90,

        /// If we want to exit on this cycle, it's the very last thing
        /// we do.
        Sim_Exit_Pri		=  100
    };

    /*
     * Event constructor
     * @param queue that the event gets scheduled on
     */
    Event(EventQueue *q, Priority p = Default_Pri)
        : queue(q), next(NULL), _priority(p), _flags(None),
#if TRACING_ON
          when_created(curTick), when_scheduled(0),
#endif
          annotated_value(0)
    {
    }

    ~Event() {}

    virtual const std::string name() const {
        return csprintf("Event_%x", (uintptr_t)this);
    }

    /// Determine if the current event is scheduled
    bool scheduled() const { return getFlags(Scheduled); }

    /// Schedule the event with the current priority or default priority
    void schedule(Tick t);

    /// Reschedule the event with the current priority
    void reschedule(Tick t);

    /// Remove the event from the current schedule
    void deschedule();

    /// Return a C string describing the event.  This string should
    /// *not* be dynamically allocated; just a const char array
    /// describing the event class.
    virtual const char *description();

    /// Dump the current event data
    void dump();

    /*
     * This member function is invoked when the event is processed
     * (occurs).  There is no default implementation; each subclass
     * must provide its own implementation.  The event is not
     * automatically deleted after it is processed (to allow for
     * statically allocated event objects).
     *
     * If the AutoDestroy flag is set, the object is deleted once it
     * is processed.
     */
    virtual void process() = 0;

    void annotate(unsigned value) { annotated_value = value; };
    unsigned annotation() { return annotated_value; }

    /// Squash the current event
    void squash() { setFlags(Squashed); }

    /// Check whether the event is squashed
    bool squashed() { return getFlags(Squashed); }

    /// Get the time that the event is scheduled
    Tick when() const { return _when; }

    /// Get the event priority
    int priority() const { return _priority; }

    struct priority_compare :
    public std::binary_function<Event *, Event *, bool>
    {
        bool operator()(const Event *l, const Event *r) const {
            return l->when() >= r->when() || l->priority() >= r->priority();
        }
    };

    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);
};

template <class T, void (T::* F)()>
void
DelayFunction(Tick when, T *object)
{
    class DelayEvent : public Event
    {
      private:
        T *object;

      public:
        DelayEvent(Tick when, T *o)
            : Event(&mainEventQueue), object(o)
            { setFlags(AutoDestroy); schedule(when); }
        void process() { (object->*F)(); }
        const char *description() { return "delay"; }
    };

    new DelayEvent(when, object);
}

/*
 * Queue of events sorted in time order
 */
class EventQueue : public Serializable
{
  protected:
    std::string objName;

  private:
    Event *head;

    void insert(Event *event);
    void remove(Event *event);

  public:

    // constructor
    EventQueue(const std::string &n)
        : objName(n), head(NULL)
    {}

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

    // schedule the given event on this queue
    void schedule(Event *ev);
    void deschedule(Event *ev);
    void reschedule(Event *ev);

    Tick nextTick() { return head->when(); }
    void serviceOne();

    // process all events up to the given timestamp.  we inline a
    // quick test to see if there are any events to process; if so,
    // call the internal out-of-line version to process them all.
    void serviceEvents(Tick when) {
        while (!empty()) {
            if (nextTick() > when)
                break;

            assert(head->when() >= when && "event scheduled in the past");
            serviceOne();
        }
    }

    // default: process all events up to 'now' (curTick)
    void serviceEvents() { serviceEvents(curTick); }

    // return true if no events are queued
    bool empty() { return head == NULL; }

    void dump();

    Tick nextEventTime() { return empty() ? curTick : head->when(); }

    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);
};

//////////////////////
//
// inline functions
//
// can't put these inside declaration due to circular dependence
// between Event and EventQueue classes.
//
//////////////////////

// schedule at specified time (place on event queue specified via
// constructor)
inline void
Event::schedule(Tick t)
{
    assert(!scheduled());
    setFlags(Scheduled);
#if TRACING_ON
    when_scheduled = curTick;
#endif
    _when = t;
    queue->schedule(this);
}

inline void
Event::deschedule()
{
    assert(scheduled());

    clearFlags(Squashed);
    clearFlags(Scheduled);
    queue->deschedule(this);
}

inline void
Event::reschedule(Tick t)
{
    assert(scheduled());
    clearFlags(Squashed);

#if TRACING_ON
    when_scheduled = curTick;
#endif
    _when = t;
    queue->reschedule(this);
}

inline void
EventQueue::schedule(Event *event)
{
    insert(event);
    if (DTRACE(Event))
        event->trace("scheduled");
}

inline void
EventQueue::deschedule(Event *event)
{
    remove(event);
    if (DTRACE(Event))
        event->trace("descheduled");
}

inline void
EventQueue::reschedule(Event *event)
{
    remove(event);
    insert(event);
    if (DTRACE(Event))
        event->trace("rescheduled");
}

//////////////////////
//
// Main Event Queue
//
// Events on this queue are processed at the *beginning* of each
// cycle, before the pipeline simulation is performed.
//
// defined in eventq.cc
//
//////////////////////
extern EventQueue mainEventQueue;

#endif // __EVENTQ_HH__
<commit_msg>Add a simple event wrapper class that takes a class pointer and member function and will schedule it for the future.<commit_after>/*
 * Copyright (c) 2003 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* @file
 * EventQueue interfaces
 */

#ifndef __EVENTQ_HH__
#define __EVENTQ_HH__

#include <assert.h>

#include <algorithm>
#include <map>
#include <string>
#include <vector>

#include "sim/host.hh"	// for Tick

#include "base/fast_alloc.hh"
#include "sim/serialize.hh"
#include "base/trace.hh"

class EventQueue;	// forward declaration

/*
 * An item on an event queue.  The action caused by a given
 * event is specified by deriving a subclass and overriding the
 * process() member function.
 */
class Event : public Serializable, public FastAlloc
{
    friend class EventQueue;

  private:
    /// queue to which this event belongs (though it may or may not be
    /// scheduled on this queue yet)
    EventQueue *queue;

    Event *next;

    Tick _when;	//!< timestamp when event should be processed
    int _priority;	//!< event priority
    char _flags;

  protected:
    enum Flags {
        None = 0x0,
        Squashed = 0x1,
        Scheduled = 0x2,
        AutoDelete = 0x4,
        AutoSerialize = 0x8
    };

    bool getFlags(Flags f) const { return (_flags & f) == f; }
    void setFlags(Flags f) { _flags |= f; }
    void clearFlags(Flags f) { _flags &= ~f; }

  protected:
    EventQueue *theQueue() const { return queue; }

#if TRACING_ON
    Tick when_created;	//!< Keep track of creation time For debugging
    Tick when_scheduled;	//!< Keep track of creation time For debugging

    virtual void trace(const char *action);	//!< trace event activity
#else
    void trace(const char *) {}
#endif

    unsigned annotated_value;

  public:

    /// Event priorities, to provide tie-breakers for events scheduled
    /// at the same cycle.  Most events are scheduled at the default
    /// priority; these values are used to control events that need to
    /// be ordered within a cycle.
    enum Priority {
        /// Breakpoints should happen before anything else, so we
        /// don't miss any action when debugging.
        Debug_Break_Pri		= -100,

        /// For some reason "delayed" inter-cluster writebacks are
        /// scheduled before regular writebacks (which have default
        /// priority).  Steve?
        Delayed_Writeback_Pri	=   -1,

        /// Default is zero for historical reasons.
        Default_Pri		=    0,

        /// CPU switches schedule the new CPU's tick event for the
        /// same cycle (after unscheduling the old CPU's tick event).
        /// The switch needs to come before any tick events to make
        /// sure we don't tick both CPUs in the same cycle.
        CPU_Switch_Pri		=   31,

        /// Serailization needs to occur before tick events also, so
        /// that a serialize/unserialize is identical to an on-line
        /// CPU switch.
        Serialize_Pri		=   32,

        /// CPU ticks must come after other associated CPU events
        /// (such as writebacks).
        CPU_Tick_Pri		=   50,

        /// Statistics events (dump, reset, etc.) come after
        /// everything else, but before exit.
        Stat_Event_Pri		=   90,

        /// If we want to exit on this cycle, it's the very last thing
        /// we do.
        Sim_Exit_Pri		=  100
    };

    /*
     * Event constructor
     * @param queue that the event gets scheduled on
     */
    Event(EventQueue *q, Priority p = Default_Pri)
        : queue(q), next(NULL), _priority(p), _flags(None),
#if TRACING_ON
          when_created(curTick), when_scheduled(0),
#endif
          annotated_value(0)
    {
    }

    ~Event() {}

    virtual const std::string name() const {
        return csprintf("Event_%x", (uintptr_t)this);
    }

    /// Determine if the current event is scheduled
    bool scheduled() const { return getFlags(Scheduled); }

    /// Schedule the event with the current priority or default priority
    void schedule(Tick t);

    /// Reschedule the event with the current priority
    void reschedule(Tick t);

    /// Remove the event from the current schedule
    void deschedule();

    /// Return a C string describing the event.  This string should
    /// *not* be dynamically allocated; just a const char array
    /// describing the event class.
    virtual const char *description();

    /// Dump the current event data
    void dump();

    /*
     * This member function is invoked when the event is processed
     * (occurs).  There is no default implementation; each subclass
     * must provide its own implementation.  The event is not
     * automatically deleted after it is processed (to allow for
     * statically allocated event objects).
     *
     * If the AutoDestroy flag is set, the object is deleted once it
     * is processed.
     */
    virtual void process() = 0;

    void annotate(unsigned value) { annotated_value = value; };
    unsigned annotation() { return annotated_value; }

    /// Squash the current event
    void squash() { setFlags(Squashed); }

    /// Check whether the event is squashed
    bool squashed() { return getFlags(Squashed); }

    /// Get the time that the event is scheduled
    Tick when() const { return _when; }

    /// Get the event priority
    int priority() const { return _priority; }

    struct priority_compare :
    public std::binary_function<Event *, Event *, bool>
    {
        bool operator()(const Event *l, const Event *r) const {
            return l->when() >= r->when() || l->priority() >= r->priority();
        }
    };

    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);
};

template <class T, void (T::* F)()>
void
DelayFunction(Tick when, T *object)
{
    class DelayEvent : public Event
    {
      private:
        T *object;

      public:
        DelayEvent(Tick when, T *o)
            : Event(&mainEventQueue), object(o)
            { setFlags(AutoDestroy); schedule(when); }
        void process() { (object->*F)(); }
        const char *description() { return "delay"; }
    };

    new DelayEvent(when, object);
}

template <class T, void (T::* F)()>
class EventWrapper : public Event
{
  private:
    T *object;

  public:
    EventWrapper(T *obj, EventQueue *q = &mainEventQueue,
                 Priority p = Default_Pri)
        : Event(q, p), object(obj)
    {}
    void process() { (object->*F)(); }
};

/*
 * Queue of events sorted in time order
 */
class EventQueue : public Serializable
{
  protected:
    std::string objName;

  private:
    Event *head;

    void insert(Event *event);
    void remove(Event *event);

  public:

    // constructor
    EventQueue(const std::string &n)
        : objName(n), head(NULL)
    {}

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

    // schedule the given event on this queue
    void schedule(Event *ev);
    void deschedule(Event *ev);
    void reschedule(Event *ev);

    Tick nextTick() { return head->when(); }
    void serviceOne();

    // process all events up to the given timestamp.  we inline a
    // quick test to see if there are any events to process; if so,
    // call the internal out-of-line version to process them all.
    void serviceEvents(Tick when) {
        while (!empty()) {
            if (nextTick() > when)
                break;

            assert(head->when() >= when && "event scheduled in the past");
            serviceOne();
        }
    }

    // default: process all events up to 'now' (curTick)
    void serviceEvents() { serviceEvents(curTick); }

    // return true if no events are queued
    bool empty() { return head == NULL; }

    void dump();

    Tick nextEventTime() { return empty() ? curTick : head->when(); }

    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);
};

//////////////////////
//
// inline functions
//
// can't put these inside declaration due to circular dependence
// between Event and EventQueue classes.
//
//////////////////////

// schedule at specified time (place on event queue specified via
// constructor)
inline void
Event::schedule(Tick t)
{
    assert(!scheduled());
    setFlags(Scheduled);
#if TRACING_ON
    when_scheduled = curTick;
#endif
    _when = t;
    queue->schedule(this);
}

inline void
Event::deschedule()
{
    assert(scheduled());

    clearFlags(Squashed);
    clearFlags(Scheduled);
    queue->deschedule(this);
}

inline void
Event::reschedule(Tick t)
{
    assert(scheduled());
    clearFlags(Squashed);

#if TRACING_ON
    when_scheduled = curTick;
#endif
    _when = t;
    queue->reschedule(this);
}

inline void
EventQueue::schedule(Event *event)
{
    insert(event);
    if (DTRACE(Event))
        event->trace("scheduled");
}

inline void
EventQueue::deschedule(Event *event)
{
    remove(event);
    if (DTRACE(Event))
        event->trace("descheduled");
}

inline void
EventQueue::reschedule(Event *event)
{
    remove(event);
    insert(event);
    if (DTRACE(Event))
        event->trace("rescheduled");
}

//////////////////////
//
// Main Event Queue
//
// Events on this queue are processed at the *beginning* of each
// cycle, before the pipeline simulation is performed.
//
// defined in eventq.cc
//
//////////////////////
extern EventQueue mainEventQueue;

#endif // __EVENTQ_HH__
<|endoftext|>