<commit_before>/* This file was autogenerated by makekdewidgets. Any changes will be lost! */
#include <qwidgetplugin.h>

#include <kinstance.h>
#include "kopetelistview.h"
#ifndef EMBED_IMAGES
#include <kstandarddirs.h>
#endif

class KopeteWidgets : public QWidgetPlugin
{
public:
	KopeteWidgets();

	virtual ~KopeteWidgets();

	virtual QStringList keys() const
	{
		QStringList result;
		for (WidgetInfos::ConstIterator it = m_widgets.begin(); it != m_widgets.end(); ++it)
			result << it.key();
		return result;
	}

	virtual QWidget *create(const QString &key, QWidget *parent = 0, const char *name = 0);

	virtual QIconSet iconSet(const QString &key) const
	{
#ifdef EMBED_IMAGES
		QPixmap pix(m_widgets[key].iconSet);
#else
		QPixmap pix(locate("data", QString::fromLatin1("kopetewidgets/pics/") + m_widgets[key].iconSet));
#endif
		return QIconSet(pix);
	}

	virtual bool isContainer(const QString &key) const { return m_widgets[key].isContainer; }

	virtual QString group(const QString &key) const { return m_widgets[key].group; }

	virtual QString includeFile(const QString &key) const { return m_widgets[key].includeFile; }

	virtual QString toolTip(const QString &key) const { return m_widgets[key].toolTip; }

	virtual QString whatsThis(const QString &key) const { return m_widgets[key].whatsThis; }
private:
	struct WidgetInfo
	{
		QString group;
#ifdef EMBED_IMAGES
		QPixmap iconSet;
#else
		QString iconSet;
#endif
		QString includeFile;
		QString toolTip;
		QString whatsThis;
		bool isContainer;
	};
	typedef QMap<QString, WidgetInfo> WidgetInfos;
	WidgetInfos m_widgets;
};
KopeteWidgets::KopeteWidgets()
{
        WidgetInfo widget;

	widget.group = "Views (Kopete)";
#ifdef EMBED_IMAGES
	widget.iconSet = QPixmap(kopete__ui__listview__listview_xpm);
#else
	widget.iconSet = "kopete__ui__listview__listview.png";
#endif
	widget.includeFile = "kopete/ui/kopetelistview.h";
	widget.toolTip = "List View (Kopete)";
	widget.whatsThis = "A component capable list view widget.";
	widget.isContainer = false;
	m_widgets.insert(QString::fromLatin1("Kopete::UI::ListView::ListView"), widget);

	new KInstance("kopetewidgets");
}
KopeteWidgets::~KopeteWidgets()
{

}
QWidget *KopeteWidgets::create(const QString &key, QWidget *parent, const char *name)
{

         if (key == QString::fromLatin1("Kopete::UI::ListView::ListView"))
                return new Kopete::UI::ListView::ListView(parent, name);

	return 0;
}
KDE_Q_EXPORT_PLUGIN(KopeteWidgets)

<commit_msg><commit_after>/**
* This file was autogenerated by makekdewidgets. Any changes will be lost!
* The generated code in this file is licensed under the same license that the
* input file.
*/
#include <qwidgetplugin.h>

#include <kinstance.h>
#include "kopetelistview.h"
#include "kopetelistviewsearchline.h"
#ifndef EMBED_IMAGES
#include <kstandarddirs.h>
#endif

class KopeteWidgets : public QWidgetPlugin
{
public:
	KopeteWidgets();

	virtual ~KopeteWidgets();

	virtual QStringList keys() const
	{
		QStringList result;
		for (WidgetInfos::ConstIterator it = m_widgets.begin(); it != m_widgets.end(); ++it)
			result << it.key();
		return result;
	}

	virtual QWidget *create(const QString &key, QWidget *parent = 0, const char *name = 0);

	virtual QIconSet iconSet(const QString &key) const
	{
#ifdef EMBED_IMAGES
		QPixmap pix(m_widgets[key].iconSet);
#else
		QPixmap pix(locate( "data",
			QString::fromLatin1("kopetewidgets/pics/") + m_widgets[key].iconSet));
#endif
		return QIconSet(pix);
	}

	virtual bool isContainer(const QString &key) const { return m_widgets[key].isContainer; }

	virtual QString group(const QString &key) const { return m_widgets[key].group; }

	virtual QString includeFile(const QString &key) const { return m_widgets[key].includeFile; }

	virtual QString toolTip(const QString &key) const { return m_widgets[key].toolTip; }

	virtual QString whatsThis(const QString &key) const { return m_widgets[key].whatsThis; }
private:
	struct WidgetInfo
	{
		QString group;
#ifdef EMBED_IMAGES
		QPixmap iconSet;
#else
		QString iconSet;
#endif
		QString includeFile;
		QString toolTip;
		QString whatsThis;
		bool isContainer;
	};
	typedef QMap<QString, WidgetInfo> WidgetInfos;
	WidgetInfos m_widgets;
};
KopeteWidgets::KopeteWidgets()
{
        WidgetInfo widget;

	widget.group = QString::fromLatin1("Views (Kopete)");
#ifdef EMBED_IMAGES
	widget.iconSet = QPixmap(kopete__ui__listview__listview_xpm);
#else
	widget.iconSet = QString::fromLatin1("kopete__ui__listview__listview.png");
#endif
	widget.includeFile = QString::fromLatin1("kopete/ui/kopetelistview.h");
	widget.toolTip = QString::fromLatin1("List View (Kopete)");
	widget.whatsThis = QString::fromLatin1("A component capable list view widget.");
	widget.isContainer = false;
	m_widgets.insert(QString::fromLatin1("Kopete::UI::ListView::ListView"), widget);

	widget.group = QString::fromLatin1("Input (Kopete)");
#ifdef EMBED_IMAGES
	widget.iconSet = QPixmap(kopete__ui__listview__searchline_xpm);
#else
	widget.iconSet = QString::fromLatin1("kopete__ui__listview__searchline.png");
#endif
	widget.includeFile = QString::fromLatin1("kopete/ui/kopetelistviewsearchline.h");
	widget.toolTip = QString::fromLatin1("List View Search Line (Kopete)");
	widget.whatsThis = QString::fromLatin1("Search line able to use Kopete custom list View.");
	widget.isContainer = false;
	m_widgets.insert(QString::fromLatin1("Kopete::UI::ListView::SearchLine"), widget);

	new KInstance("kopetewidgets");
}
KopeteWidgets::~KopeteWidgets()
{

}
QWidget *KopeteWidgets::create(const QString &key, QWidget *parent, const char *name)
{

         if (key == QString::fromLatin1("Kopete::UI::ListView::ListView"))
                return new Kopete::UI::ListView::ListView(parent, name);

         if (key == QString::fromLatin1("Kopete::UI::ListView::SearchLine"))
                return new Kopete::UI::ListView::SearchLine(parent, 0, name);

	return 0;
}
KDE_Q_EXPORT_PLUGIN(KopeteWidgets)

<|endoftext|>


<commit_before>#ifndef stack_cpp
#define stack_cpp
#pragma once
#include <iostream>

template <typename T1, typename T2>
void construct(T1 * ptr, T2 const & value) {
    new(ptr) T1 (value);
}

template <typename T>
void destroy(T * ptr) noexcept
{
    ptr->~T();
}

template <typename FwdIter>
void destroy(FwdIter first, FwdIter last) noexcept
{
    for (; first != last; ++first) {
        destroy(&*first);
    }
}

template <typename T>
class allocator
{
protected:
    allocator(size_t size = 0);
    ~allocator();
    auto swap(allocator & other) -> void;

    allocator(allocator const &) = delete;
    auto operator =(allocator const &) -> allocator & = delete;

    T * ptr_;
    size_t size_;
    size_t count_;
};

template <typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)(operator new(size*sizeof(T)))), size_(size), count_(0){};

template<typename T>
allocator<T>::~allocator(){ operator delete(ptr_); }

template<typename T>
auto allocator<T>::swap(allocator & other) -> void {
	std::swap(ptr_, other.ptr_);
	std::swap(count_, other.count_);
	std::swap(size_, other.size_);
}

template <typename T>
class stack : private allocator<T>
{
public:
	stack(size_t size = 0 ); //noexcept
	stack(stack const &);  //strong
	~stack(); //noexcept
	size_t count() const;  //noexcept
	auto push(T const &) -> void; //strong
	void pop(); //strong
	const T& top(); //strong
	auto operator=(stack const & right)->stack &; //strong
	auto empty() const -> bool; //noexcept

};
template <typename T>
size_t stack<T>::count() const
{
	return allocator<T>::count_;
}
template <typename T>
stack<T>::stack(size_t size):allocator<T>(size){}

template <typename T>
stack<T>::stack(const stack& item) : allocator<T>(item.size_){
	for (size_t i = 0; i < item.count_; i++) construct(allocator<T>::ptr_ + i, item.ptr_[i]);
	allocator<T>::count_ = item.count_;
};

template <typename T>
stack<T>::~stack()
{
}

template <typename T>
void stack<T>::push(T const &item){
	if (allocator<T>::count_ == allocator<T>::size_) {
		size_t array_size = allocator<T>::size_ * 2 + (allocator<T>::size_ == 0);
		stack<T> temp(array_size);
		while (temp.count() < allocator<T>::count_) temp.push(allocator<T>::ptr_[temp.count()]);
		this->swap(temp);
	}
	construct(allocator<T>::ptr_ + allocator<T>::count_, item);
	++allocator<T>::count_;
}

template<typename T>
void stack<T>::pop() {
	if (allocator<T>::count_ == 0) {
		throw ("Stack is empty!");
	} else {
		allocator<T>::count_--;
	}
}

template<typename T>
const T& stack<T>::top()
{
	if (allocator<T>::count_ == 0) {
		throw ("Stack is empty!");
	}
	return allocator<T>::ptr_[allocator<T>::count_ - 1];
}

template<typename T>
auto stack<T>::operator=(stack const & right) -> stack & {
	if (this != &right) {
	stack<T> temp (right.size_);
	while (temp.count_ < right.count_){
		construct(temp.ptr_ + temp.count_, right.ptr_[temp.count_]);
		++temp.count_;
	}
	this -> swap(temp);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const -> bool{
	if (allocator<T>::count_ == 0){
		return true;
	} else{
		return false;
	}
}

#endif
<commit_msg>Update stack.hpp<commit_after>#ifndef stack_cpp
#define stack_cpp
#pragma once
#include <iostream>

template <typename T1, typename T2>
void construct(T1 * ptr, T2 const & value) {
    new(ptr) T1 (value);
}

template <typename T>
void destroy(T * ptr) noexcept
{
    ptr->~T();
}

template <typename FwdIter>
void destroy(FwdIter first, FwdIter last) noexcept
{
    for (; first != last; ++first) {
        destroy(&*first);
    }
}

template <typename T>
class allocator
{
protected:
    allocator(size_t size = 0);
    ~allocator();
    auto swap(allocator & other) -> void;

    allocator(allocator const &) = delete;
    auto operator =(allocator const &) -> allocator & = delete;

    T * ptr_;
    size_t size_;
    size_t count_;
};

template <typename T>
allocator<T>::allocator(size_t size) : ptr_((T*)(operator new(size*sizeof(T)))), size_(size), count_(0){};

template<typename T>
allocator<T>::~allocator(){ operator delete(ptr_); }

template<typename T>
auto allocator<T>::swap(allocator & other) -> void {
	std::swap(ptr_, other.ptr_);
	std::swap(count_, other.count_);
	std::swap(size_, other.size_);
}

template <typename T>
class stack : private allocator<T>
{
public:
	stack(size_t size = 0 ); //noexcept
	stack(stack const &);  //strong
	~stack(); //noexcept
	size_t count() const;  //noexcept
	auto push(T const &) -> void; //strong
	void pop(); //strong
	const T& top(); //strong
	auto operator=(stack const & right)->stack &; //strong
	auto empty() const -> bool; //noexcept

};
template <typename T>
size_t stack<T>::count() const
{
	return allocator<T>::count_;
}
template <typename T>
stack<T>::stack(size_t size):allocator<T>(size){}

template <typename T>
stack<T>::stack(const stack& item) : allocator<T>(item.size_){
	for (size_t i = 0; i < item.count_; i++) construct(allocator<T>::ptr_ + i, item.ptr_[i]);
	allocator<T>::count_ = item.count_;
};

template <typename T>
stack<T>::~stack()
{
}

template <typename T>
void stack<T>::push(T const &item){
	if (allocator<T>::count_ == allocator<T>::size_) {
		size_t array_size = allocator<T>::size_ * 2 + (allocator<T>::size_ == 0);
		stack<T> temp(array_size);
		while (temp.count() < allocator<T>::count_) temp.push(allocator<T>::ptr_[temp.count()]);
		this->swap(temp);
	}
	construct(allocator<T>::ptr_ + allocator<T>::count_, item);
	++allocator<T>::count_;
}

template<typename T>

void stack<T>::pop()
{
	if (allocator<T>::count_> 0) {
		--allocator<T>::count_;
	}
	else throw ("Stack is empty");
}
template<typename T>
const T& stack<T>::top()
{
	if (allocator<T>::count_ == 0) {
		throw ("Stack is empty!");
	}
	return allocator<T>::ptr_[allocator<T>::count_ - 1];
}

template<typename T>
auto stack<T>::operator=(stack const & right) -> stack & {
	if (this != &right) {
	stack<T> temp (right.size_);
	while (temp.count_ < right.count_){
		construct(temp.ptr_ + temp.count_, right.ptr_[temp.count_]);
		++temp.count_;
	}
	this -> swap(temp);
	}
	return *this;
}

template<typename T>
auto stack<T>::empty() const -> bool{
	if (allocator<T>::count_ == 0){
		return true;
	} else{
		return false;
	}
}

#endif
<|endoftext|>


<commit_before>#include "Graph.hpp"

/*
template <typename Weight>
void add_edge(Graph<Weight> &g, int src, int to) {
  g[src].push_back(Edge<Weight>(to));
  g[to].push_back(Edge<Weight>(src));
}
*/

class LCA {
  int V, LOG_V;
  vector<vector<int>> parent;
  vector<int> depth;
  template<typename T>
  void dfs(const Graph<T> &g, int v, int p, int d) {
    parent[0][v] = p; depth[v] = d;
    for (const Edge<T> &e: g[v]) {
      if (e.to != p) dfs(g, e.to, v, d + 1);
    }
  }
public:
  template<typename T>
  LCA(const Graph<T> &g, int root) : V(g.size()), LOG_V(0), depth(V, 0) {
    for (int v = V; v > 0; v >>= 1) ++LOG_V;
    parent.assign(LOG_V, vector<int>(V, 0));
    dfs(g, root, -1, 0);
    for (int k = 0; k < LOG_V - 1; ++k) {
      for (int v = 0; v < V; ++v) {
        if (parent[k][v] < 0) parent[k + 1][v] = -1;
        else parent[k + 1][v] = parent[k][parent[k][v]];
      }
    }
  }
  int lca(int u, int v) {
    if (depth[u] > depth[v]) swap(u, v);
    for (int k = 0; k < LOG_V; ++k)
      if (((depth[v] - depth[u]) >> k) & 1) v = parent[k][v];
    if (u == v) return u;
    for (int k = LOG_V - 1; k >= 0; k--) {
      if (parent[k][u] != parent[k][v]) {
        u = parent[k][u];
        v = parent[k][v];
      }
    }
    return parent[0][u];
  }
};
<commit_msg>add verifier of lca<commit_after>#include "Graph.hpp"

/*
template <typename Weight>
void add_edge(Graph<Weight> &g, int src, int to) {
  g[src].push_back(Edge<Weight>(to));
  g[to].push_back(Edge<Weight>(src));
}
*/

class LCA {
  int V, LOG_V;
  vector<vector<int>> parent;
  vector<int> depth;
  template<typename T>
  void dfs(const Graph<T> &g, int v, int p, int d) {
    parent[0][v] = p; depth[v] = d;
    for (const Edge<T> &e: g[v]) {
      if (e.to != p) dfs(g, e.to, v, d + 1);
    }
  }
public:
  template<typename T>
  LCA(const Graph<T> &g, int root) : V(g.size()), LOG_V(0), depth(V, 0) {
    for (int v = V; v > 0; v >>= 1) ++LOG_V;
    parent.assign(LOG_V, vector<int>(V, 0));
    dfs(g, root, -1, 0);
    for (int k = 0; k < LOG_V - 1; ++k) {
      for (int v = 0; v < V; ++v) {
        if (parent[k][v] < 0) parent[k + 1][v] = -1;
        else parent[k + 1][v] = parent[k][parent[k][v]];
      }
    }
  }
  int query(int u, int v) {
    if (depth[u] > depth[v]) swap(u, v);
    for (int k = 0; k < LOG_V; ++k)
      if (((depth[v] - depth[u]) >> k) & 1) v = parent[k][v];
    if (u == v) return u;
    for (int k = LOG_V - 1; k >= 0; k--) {
      if (parent[k][u] != parent[k][v]) {
        u = parent[k][u];
        v = parent[k][v];
      }
    }
    return parent[0][u];
  }
};

// Verified : AOJ GRL_5_C (Lowest Common Ancestor)
/*
int main() {
  int n, q;
  cin >> n;
  Graph<int> g(n);
  for (int i = 0; i < n; ++i) {
    int k, c;
    cin >> k;
    while (k--) {
      cin >> c;
      add_edge(g, i, c);
    }
  }
  LCA lca(g, 0);
  cin >> q;
  while (q--) {
    int u, v;
    cin >> u >> v;
    cout << lca.query(u, v) << endl;
  }
  return 0;
}
*/
<|endoftext|>


<commit_before>#include <algorithm>

#include "Graphics.h"

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480	//minimum size to allow for 64x64 maps

Graphics::Graphics(uint16_t xSize, uint16_t tileOffset, uint16_t tileAmount) {
    this->selXMin = std::min(8*64, 8*xSize) + 1;
    this->xDisplaySize = std::min(64, 0+xSize);
    this->tileOffset = tileOffset;
    this->tileAmount = tileAmount;
    this->currentPal = 0;
    this->highPriorityDisplay = true;
    this->lowPriorityDisplay = true;
    this->screenTileYOffset = 0;
    this->screenTileXOffset = 0;
    this->selTileYOffset = 0;

    /* calculate selector width */
    this->selectorWidth = 8;
    while (8*tileAmount / selectorWidth > SCREEN_HEIGHT) {
        if (8 * (xSize+selectorWidth) < SCREEN_WIDTH) selectorWidth += 8;
        else break;
    }

    if (SDL_Init(SDL_INIT_VIDEO)<0) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to init SDL video", SDL_GetError(), NULL);
        exit(1);
    }
    atexit(SDL_Quit);

    window = SDL_CreateWindow("Captain PlaneEd", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    if (window == NULL)
    {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to init SDL Window", SDL_GetError(), NULL);
        exit(1);
    }

    render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (render == NULL)
    {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to init SDL Renderer", SDL_GetError(), NULL);
        exit(1);
    }

    SDL_RenderSetLogicalSize(render, SCREEN_WIDTH, SCREEN_HEIGHT);

    screen = SDL_CreateRGBSurface(0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0, 0, 0, 0);
    if (screen==NULL) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to init screen SDL Surface", SDL_GetError(), NULL);
        exit(1);
    }
    texture = SDL_CreateTextureFromSurface(render, screen);
    if (texture==NULL) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to init screen SDL Texture", SDL_GetError(), NULL);
        exit(1);
    }
}

void Graphics::ReadPalette(const char* const filename) {
    FILE* palfile = fopen(filename,"rb");
    if (palfile==NULL) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Internal Error", "Decompressed palette file not found.", NULL);
        exit(1);
    }

    fseek(palfile, 0, SEEK_END);
    paletteLines = ftell(palfile)/0x20;
    rewind(palfile);

    if (paletteLines > 4) {
	    paletteLines = 4;
    }
    else if (paletteLines == 0) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Palette file too small. It must contain at least one palette line.", NULL);
        exit(1);
    }

    palette = new uint16_t[paletteLines][16];
    for (int i=0; i < paletteLines; ++i)
        fread(palette[i], sizeof(unsigned char), 32, palfile);
    fclose(palfile);
    remove(filename);
}
#define getrgb(v) ((v&0xF000)>>8)|(v&0x0F0F|0xF000)	// Corrects G value, and sets alpha to max, so we can see
void Graphics::ReadTiles(const char* const filename) {
    FILE* tilefile = fopen(filename,"rb");
    if (tilefile==NULL) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Art file not found. Are you sure the path is correct?", NULL);
        exit(1);
    }
    unsigned char tilebuffer[32]; //space for one tile
    tileData = new uint16_t***[tileAmount];
    for (int t=0; t < tileAmount; ++t) {
        fread(tilebuffer, sizeof(unsigned char), 32, tilefile);
        tileData[t] = new uint16_t**[paletteLines];
        for (int p=0; p < paletteLines; ++p) {
            tileData[t][p] = new uint16_t*[4];
            for (int f=0; f < 4; ++f) tileData[t][p][f] = new uint16_t[64];
            for (int i=0; i < 32; ++i) {
                tileData[t][p][0][2*i]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]);
                tileData[t][p][0][2*i+1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
                tileData[t][p][1][8*(i/4)+7-2*(i%4)]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]); //X-flip
                tileData[t][p][1][8*(i/4)+7-2*(i%4)-1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
                tileData[t][p][2][56-8*(i/4)+2*(i%4)]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]); //Y-flip
                tileData[t][p][2][56-8*(i/4)+2*(i%4)+1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
                tileData[t][p][3][63-2*i]   = getrgb(palette[p][(tilebuffer[i] & 0xF0)>>4]); //XY-flip
                tileData[t][p][3][63-2*i-1] = getrgb(palette[p][(tilebuffer[i] & 0x0F)]);
            }
        }
    }
    fclose(tilefile);
    remove(filename);
}

void Graphics::CreateTiles(){
    tiles = new SDL_Surface***[tileAmount];
    for (int t=0; t < tileAmount; ++t)
    {
        tiles[t] = new SDL_Surface**[paletteLines];
        for (int p=0; p < paletteLines; ++p)
        {
            tiles[t][p] = new SDL_Surface*[4];
            for (int f=0; f < 4; ++f)
                tiles[t][p][f] = InitSurface(tileData[t][p][f], 8, 8, 16);
        }
    }
}

SDL_Surface* Graphics::InitSurface(uint16_t *pixelsT, int width, int height, int bbp) {
    void* pixels = pixelsT;
    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom (pixels, width,
                         height, bbp, width*((bbp+7)/8), 0x0F00, 0x00F0, 0x000F, 0xF000);

    if (surface == NULL)
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Cannot make SDL Surface from tiles", SDL_GetError(), NULL);

    return(surface);
}

void Graphics::DrawSurface(SDL_Surface *img, SDL_Surface *screen, int x, int y) {
    SDL_Rect RectTemp;
    RectTemp.x = x;
    RectTemp.y = y;
    SDL_BlitSurface(img, NULL, screen, &RectTemp);
}

void Graphics::ClearMap() {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    SDL_Rect RectTemp;
    RectTemp.x = 0;
    RectTemp.y = 0;
    RectTemp.w = selXMin-1;
    RectTemp.h = SCREEN_HEIGHT;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::ClearSelector() {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    SDL_Rect RectTemp;
    RectTemp.x = selXMin;
    RectTemp.y = 0;
    RectTemp.w = 8*selectorWidth;
    RectTemp.h = SCREEN_HEIGHT;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::DrawSelector() {
    ClearSelector();
    for (int i=0; i < tileAmount; ++i)
        DrawSurface(tiles[i][currentPal][0], this->screen, selXMin + 8*(i%selectorWidth), 8*(i/selectorWidth - selTileYOffset));
    //SDL_Flip(screen);
    ProcessDisplay();
}

void Graphics::ProcessDisplay()
{
	SDL_UpdateTexture(texture, NULL, screen->pixels, screen->pitch);
	SDL_RenderClear(render);
	SDL_RenderCopy(render, texture, NULL, NULL);
	SDL_RenderPresent(render);
}

/* map coords */
void Graphics::DrawTileSingle(int x, int y, Tile tile) {
    y -= screenTileYOffset;
    x -= screenTileXOffset;
    if (x >= xDisplaySize) return;
    if ((tile.priority && highPriorityDisplay) || (!tile.priority && lowPriorityDisplay)) {
        if ((tile.tileID) - tileOffset >= this->tileAmount) {
            DrawTileNone(x, y);
            DrawTileInvalid(x, y);
        } else if ((tile.tileID || !this->tileOffset) && tile.paletteLine < paletteLines)
            DrawSurface(tiles[(tile.tileID) - tileOffset][tile.paletteLine][tile.xFlip | (tile.yFlip<<1)], screen, 8*x, 8*y);
        else DrawTileBlank(x, y, tile);
    } else DrawTileNone(x, y);
}

bool Graphics::CheckSelValidPos(int x, int y) {
    if (x>=selXMin && x<selXMin+8*selectorWidth && y>=0 && (x-selXMin)/8+selectorWidth*(y/8 + selTileYOffset)<GetTileAmount()) return true;
    else return false;
}

void Graphics::DrawTileNone(int x, int y) {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    DrawTileFullColor(x, y, color);
}

void Graphics::DrawTileBlank(int x, int y, Tile tile) {
    Uint32 color = SDL_MapRGB(
        screen->format,
        (palette[tile.paletteLine][0] & 0x0F00)>>4,
        (palette[tile.paletteLine][0] & 0x00F0),
        (palette[tile.paletteLine][0] & 0x000F)<<4
    );
    DrawTileFullColor(x, y, color);
}

void Graphics::DrawTileFullColor(int x, int y, Uint32 color) {
    SDL_Rect RectTemp;
    RectTemp.x = 8*x;
    RectTemp.y = 8*y;
    RectTemp.w = 8;
    RectTemp.h = 8;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::DrawTileInvalid(int x, int y) {
    //PosTileToScreen(&x, &y);
    for (int i=0; i < 8; ++i) {
        DrawPixel(8*x+i, 8*y+i);
        DrawPixel(8*x+i, 8*y+7-i);
    }
}

void Graphics::DrawPixel(int x, int y) {
    if (x<0 || x>=SCREEN_WIDTH || y<0 || y>=SCREEN_HEIGHT) return;
    Uint32 color = SDL_MapRGB(screen->format, 0xE0, 0xB0, 0xD0);

    Uint32 *pixel;
    pixel = (Uint32*) screen->pixels + y*screen->pitch/4 + x;
    *pixel = color;
}

/* map coords */
void Graphics::DrawRect(int x, int y) {
    PosTileToScreen(&x, &y);
    for (int i=0; i < 8; ++i) {
        DrawPixel(x+i, y);
        DrawPixel(x+i, y+7);
        DrawPixel(x, y+i);
        DrawPixel(x+7, y+i);
    }
}

/* map coords */
void Graphics::DrawFreeRect(int x, int y, int xSize, int ySize) {
    PosTileToScreen(&x, &y);
    for (int i=0; i < 8*ySize; ++i) {
        DrawPixel(x, y+i);
        DrawPixel(x + 8*xSize - 1, y+i);
    }
    for (int i=0; i < 8*xSize; ++i) {
        DrawPixel(x+i, y);
        DrawPixel(x+i, y + 8*ySize - 1);
    }
}

void Graphics::PosScreenToTile(int* x, int* y) {
    *x /= 8;
    *y /= 8;
    *y += screenTileYOffset;
    *x += screenTileXOffset;
}

void Graphics::PosScreenToTileRound(int* x, int* y) {
    *x = ((*x)+4)/8;
    *y = ((*y)+4)/8;
    *y += screenTileYOffset;
    *x += screenTileXOffset;
}

void Graphics::PosTileToScreen(int* x, int* y) {
    *y -= screenTileYOffset;
    *x -= screenTileXOffset;
    *x *= 8;
    *y *= 8;
}
<commit_msg>Improving BGR->RGB conversion (and fixing an old bug)<commit_after>#include <algorithm>

#include "Graphics.h"

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480	//minimum size to allow for 64x64 maps

Graphics::Graphics(uint16_t xSize, uint16_t tileOffset, uint16_t tileAmount) {
    this->selXMin = std::min(8*64, 8*xSize) + 1;
    this->xDisplaySize = std::min(64, 0+xSize);
    this->tileOffset = tileOffset;
    this->tileAmount = tileAmount;
    this->currentPal = 0;
    this->highPriorityDisplay = true;
    this->lowPriorityDisplay = true;
    this->screenTileYOffset = 0;
    this->screenTileXOffset = 0;
    this->selTileYOffset = 0;

    /* calculate selector width */
    this->selectorWidth = 8;
    while (8*tileAmount / selectorWidth > SCREEN_HEIGHT) {
        if (8 * (xSize+selectorWidth) < SCREEN_WIDTH) selectorWidth += 8;
        else break;
    }

    if (SDL_Init(SDL_INIT_VIDEO)<0) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to init SDL video", SDL_GetError(), NULL);
        exit(1);
    }
    atexit(SDL_Quit);

    window = SDL_CreateWindow("Captain PlaneEd", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    if (window == NULL)
    {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to init SDL Window", SDL_GetError(), NULL);
        exit(1);
    }

    render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (render == NULL)
    {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to init SDL Renderer", SDL_GetError(), NULL);
        exit(1);
    }

    SDL_RenderSetLogicalSize(render, SCREEN_WIDTH, SCREEN_HEIGHT);

    screen = SDL_CreateRGBSurface(0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, 0, 0, 0, 0);
    if (screen==NULL) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to init screen SDL Surface", SDL_GetError(), NULL);
        exit(1);
    }
    texture = SDL_CreateTextureFromSurface(render, screen);
    if (texture==NULL) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Unable to init screen SDL Texture", SDL_GetError(), NULL);
        exit(1);
    }
}

void Graphics::ReadPalette(const char* const filename) {
    FILE* palfile = fopen(filename,"rb");
    if (palfile==NULL) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Internal Error", "Decompressed palette file not found.", NULL);
        exit(1);
    }

    fseek(palfile, 0, SEEK_END);
    paletteLines = ftell(palfile)/0x20;
    rewind(palfile);

    if (paletteLines > 4) {
	    paletteLines = 4;
    }
    else if (paletteLines == 0) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Palette file too small. It must contain at least one palette line.", NULL);
        exit(1);
    }

    palette = new uint16_t[paletteLines][16];
    for (int line=0; line < paletteLines; ++line)
        for (int entry=0; entry < 16; ++entry)
	{
		// Convert BGR to RGB
		uint16_t palette_entry = (fgetc(palfile)<<8)|fgetc(palfile);
		uint16_t blue = (palette_entry&0x0F00) >> 8;
		uint16_t green = palette_entry&0x00F0;
		uint16_t red = (palette_entry&0x000F) << 8;
		uint16_t alpha = 0xF000;
		palette[line][entry] = red|green|blue|alpha;
	}

    fclose(palfile);
    remove(filename);
}

void Graphics::ReadTiles(const char* const filename) {
    FILE* tilefile = fopen(filename,"rb");
    if (tilefile==NULL) {
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Art file not found. Are you sure the path is correct?", NULL);
        exit(1);
    }
    unsigned char tilebuffer[32]; //space for one tile
    tileData = new uint16_t***[tileAmount];
    for (int t=0; t < tileAmount; ++t) {
        fread(tilebuffer, sizeof(unsigned char), 32, tilefile);
        tileData[t] = new uint16_t**[paletteLines];
        for (int p=0; p < paletteLines; ++p) {
            tileData[t][p] = new uint16_t*[4];
            for (int f=0; f < 4; ++f) tileData[t][p][f] = new uint16_t[64];
            for (int i=0; i < 32; ++i) {
                tileData[t][p][0][2*i]   = palette[p][(tilebuffer[i] & 0xF0)>>4];
                tileData[t][p][0][2*i+1] = palette[p][(tilebuffer[i] & 0x0F)];
                tileData[t][p][1][8*(i/4)+7-2*(i%4)]   = palette[p][(tilebuffer[i] & 0xF0)>>4]; //X-flip
                tileData[t][p][1][8*(i/4)+7-2*(i%4)-1] = palette[p][(tilebuffer[i] & 0x0F)];
                tileData[t][p][2][56-8*(i/4)+2*(i%4)]   = palette[p][(tilebuffer[i] & 0xF0)>>4]; //Y-flip
                tileData[t][p][2][56-8*(i/4)+2*(i%4)+1] = palette[p][(tilebuffer[i] & 0x0F)];
                tileData[t][p][3][63-2*i]   = palette[p][(tilebuffer[i] & 0xF0)>>4]; //XY-flip
                tileData[t][p][3][63-2*i-1] = palette[p][(tilebuffer[i] & 0x0F)];
            }
        }
    }
    fclose(tilefile);
    remove(filename);
}

void Graphics::CreateTiles(){
    tiles = new SDL_Surface***[tileAmount];
    for (int t=0; t < tileAmount; ++t)
    {
        tiles[t] = new SDL_Surface**[paletteLines];
        for (int p=0; p < paletteLines; ++p)
        {
            tiles[t][p] = new SDL_Surface*[4];
            for (int f=0; f < 4; ++f)
                tiles[t][p][f] = InitSurface(tileData[t][p][f], 8, 8, 16);
        }
    }
}

SDL_Surface* Graphics::InitSurface(uint16_t *pixelsT, int width, int height, int bbp) {
    void* pixels = pixelsT;
    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom (pixels, width,
                         height, bbp, width*((bbp+7)/8), 0x0F00, 0x00F0, 0x000F, 0xF000);

    if (surface == NULL)
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Cannot make SDL Surface from tiles", SDL_GetError(), NULL);

    return(surface);
}

void Graphics::DrawSurface(SDL_Surface *img, SDL_Surface *screen, int x, int y) {
    SDL_Rect RectTemp;
    RectTemp.x = x;
    RectTemp.y = y;
    SDL_BlitSurface(img, NULL, screen, &RectTemp);
}

void Graphics::ClearMap() {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    SDL_Rect RectTemp;
    RectTemp.x = 0;
    RectTemp.y = 0;
    RectTemp.w = selXMin-1;
    RectTemp.h = SCREEN_HEIGHT;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::ClearSelector() {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    SDL_Rect RectTemp;
    RectTemp.x = selXMin;
    RectTemp.y = 0;
    RectTemp.w = 8*selectorWidth;
    RectTemp.h = SCREEN_HEIGHT;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::DrawSelector() {
    ClearSelector();
    for (int i=0; i < tileAmount; ++i)
        DrawSurface(tiles[i][currentPal][0], this->screen, selXMin + 8*(i%selectorWidth), 8*(i/selectorWidth - selTileYOffset));
    //SDL_Flip(screen);
    ProcessDisplay();
}

void Graphics::ProcessDisplay()
{
	SDL_UpdateTexture(texture, NULL, screen->pixels, screen->pitch);
	SDL_RenderClear(render);
	SDL_RenderCopy(render, texture, NULL, NULL);
	SDL_RenderPresent(render);
}

/* map coords */
void Graphics::DrawTileSingle(int x, int y, Tile tile) {
    y -= screenTileYOffset;
    x -= screenTileXOffset;
    if (x >= xDisplaySize) return;
    if ((tile.priority && highPriorityDisplay) || (!tile.priority && lowPriorityDisplay)) {
        if ((tile.tileID) - tileOffset >= this->tileAmount) {
            DrawTileNone(x, y);
            DrawTileInvalid(x, y);
        } else if ((tile.tileID || !this->tileOffset) && tile.paletteLine < paletteLines)
            DrawSurface(tiles[(tile.tileID) - tileOffset][tile.paletteLine][tile.xFlip | (tile.yFlip<<1)], screen, 8*x, 8*y);
        else DrawTileBlank(x, y, tile);
    } else DrawTileNone(x, y);
}

bool Graphics::CheckSelValidPos(int x, int y) {
    if (x>=selXMin && x<selXMin+8*selectorWidth && y>=0 && (x-selXMin)/8+selectorWidth*(y/8 + selTileYOffset)<GetTileAmount()) return true;
    else return false;
}

void Graphics::DrawTileNone(int x, int y) {
    Uint32 color = SDL_MapRGB(screen->format, 0, 0, 0);
    DrawTileFullColor(x, y, color);
}

void Graphics::DrawTileBlank(int x, int y, Tile tile) {
    Uint32 color = SDL_MapRGB(
        screen->format,
        (palette[tile.paletteLine][0] & 0x0F00)>>4,
        (palette[tile.paletteLine][0] & 0x00F0),
        (palette[tile.paletteLine][0] & 0x000F)<<4
    );
    DrawTileFullColor(x, y, color);
}

void Graphics::DrawTileFullColor(int x, int y, Uint32 color) {
    SDL_Rect RectTemp;
    RectTemp.x = 8*x;
    RectTemp.y = 8*y;
    RectTemp.w = 8;
    RectTemp.h = 8;
    SDL_FillRect(this->screen, &RectTemp, color);
}

void Graphics::DrawTileInvalid(int x, int y) {
    //PosTileToScreen(&x, &y);
    for (int i=0; i < 8; ++i) {
        DrawPixel(8*x+i, 8*y+i);
        DrawPixel(8*x+i, 8*y+7-i);
    }
}

void Graphics::DrawPixel(int x, int y) {
    if (x<0 || x>=SCREEN_WIDTH || y<0 || y>=SCREEN_HEIGHT) return;
    Uint32 color = SDL_MapRGB(screen->format, 0xE0, 0xB0, 0xD0);

    Uint32 *pixel;
    pixel = (Uint32*) screen->pixels + y*screen->pitch/4 + x;
    *pixel = color;
}

/* map coords */
void Graphics::DrawRect(int x, int y) {
    PosTileToScreen(&x, &y);
    for (int i=0; i < 8; ++i) {
        DrawPixel(x+i, y);
        DrawPixel(x+i, y+7);
        DrawPixel(x, y+i);
        DrawPixel(x+7, y+i);
    }
}

/* map coords */
void Graphics::DrawFreeRect(int x, int y, int xSize, int ySize) {
    PosTileToScreen(&x, &y);
    for (int i=0; i < 8*ySize; ++i) {
        DrawPixel(x, y+i);
        DrawPixel(x + 8*xSize - 1, y+i);
    }
    for (int i=0; i < 8*xSize; ++i) {
        DrawPixel(x+i, y);
        DrawPixel(x+i, y + 8*ySize - 1);
    }
}

void Graphics::PosScreenToTile(int* x, int* y) {
    *x /= 8;
    *y /= 8;
    *y += screenTileYOffset;
    *x += screenTileXOffset;
}

void Graphics::PosScreenToTileRound(int* x, int* y) {
    *x = ((*x)+4)/8;
    *y = ((*y)+4)/8;
    *y += screenTileYOffset;
    *x += screenTileXOffset;
}

void Graphics::PosTileToScreen(int* x, int* y) {
    *y -= screenTileYOffset;
    *x -= screenTileXOffset;
    *x *= 8;
    *y *= 8;
}
<|endoftext|>


<commit_before>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <iostream>
#include <cassert>
#include <cstring>

#include <qimessaging/message.hpp>
#include <qimessaging/datastream.hpp>

#include <qi/atomic.hpp>
#include <qi/log.hpp>

#include "src/buffer_p.hpp"
#include "src/message_p.hpp"

namespace qi {

#include <event2/buffer.h>

  const unsigned int messageMagic = 0x42adde42;

  unsigned int newMessageId()
  {
    static qi::atomic<long> id(0);
    ++id;
    return *id;
  }

  Message::Message()
    : _p(new qi::MessagePrivate())
  {
    memset(_p, 0, sizeof(MessagePrivate));
    _p->id = newMessageId();
    _p->magic = messageMagic;
    _p->buffer = new qi::Buffer();
    _p->deleteBuffer = true;
  }

  Message::Message(Buffer *buf)
    : _p(new qi::MessagePrivate())
  {
    memset(_p, 0, sizeof(MessagePrivate));
    _p->id = newMessageId();
    _p->magic = messageMagic;
    _p->buffer = buf;
    _p->deleteBuffer = false;
  }

  Message::Message(const Message &msg)
    : _p(0)
  {
    memcpy(_p, msg._p, sizeof(MessagePrivate));
    _p->buffer = msg._p->buffer;
    _p->deleteBuffer = false;
  }

  Message &Message::operator=(const Message &msg) {
    memcpy(_p, msg._p, sizeof(MessagePrivate));
    _p->buffer = msg._p->buffer;
    _p->deleteBuffer = false;
    return *this;
  }

  Message::~Message()
  {
    if (_p->deleteBuffer)
      delete _p->buffer;
    delete _p;
  }

  void Message::setBuffer(qi::Buffer *buffer) {
    _p->buffer = buffer;
    _p->deleteBuffer = false;
  }

  std::ostream& operator<<(std::ostream& os, const qi::Message& msg) {
    os << "message {"
       << "size=" << msg.size()
       << ", id=" << msg.id()
       << ", type=" << msg.type()
       << ", serv=" << msg.service()
       << ", path=" << msg.path()
       << ", func=" << msg.function()
       << "}";
    return os;
  }

  qi::DataStream& operator<<(qi::DataStream& os, const qi::Message& msg)
  {
    os << msg._p->magic
       << msg.id()
       << msg.size()
       << msg.type()
       << msg.service()
       << msg.path()
       << msg.function()
       << msg._p->reserved;

    qi::Buffer *buf = reinterpret_cast<qi::Buffer *>(os.ioDevice());
    evbuffer_add_buffer(buf->_p->data(), msg.buffer()->_p->data());
    return os;
  }

  unsigned int Message::size() const
  {
    return _p->buffer->size();
  }

  void Message::setId(uint32_t id)
  {
    _p->id = id;
  }

  unsigned int Message::id() const
  {
    return _p->id;
  }

  void Message::setType(uint32_t type)
  {
    _p->type = type;
  }

  unsigned int Message::type() const
  {
    return _p->type;
  }

  void Message::setService(uint32_t service)
  {
    _p->service = service;
  }

  unsigned int Message::service() const
  {
    return _p->service;
  }

  void Message::setPath(uint32_t path)
  {
    _p->path = path;
  }

  unsigned int Message::path() const
  {
    return _p->path;
  }

  void Message::setFunction(uint32_t function)
  {
    _p->function = function;
  }

  unsigned int Message::function() const
  {
    return _p->function;
  }

  qi::Buffer *Message::buffer() const
  {
    return _p->buffer;
  }

  void Message::buildReplyFrom(const Message &call)
  {
    setId(call.id());
    setType(qi::Message::Type_Reply);
    setService(call.service());
    setPath(call.path());
    setFunction(call.function());
  }

  void Message::buildForwardFrom(const Message &msg)
  {
    setType(msg.type());
    setService(msg.service());
    setPath(msg.path());
    setFunction(msg.function());
  }

  void Message::swap(Message &msg)
  {
    MessagePrivate *p = _p;
    _p = msg._p;
    msg._p = p;
  }

  bool Message::isValid() const
  {
    return (messageMagic == _p->magic);
  }
}
<commit_msg>message: fix copy constructor<commit_after>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <iostream>
#include <cassert>
#include <cstring>

#include <qimessaging/message.hpp>
#include <qimessaging/datastream.hpp>

#include <qi/atomic.hpp>
#include <qi/log.hpp>

#include "src/buffer_p.hpp"
#include "src/message_p.hpp"

namespace qi {

#include <event2/buffer.h>

  const unsigned int messageMagic = 0x42adde42;

  unsigned int newMessageId()
  {
    static qi::atomic<long> id(0);
    ++id;
    return *id;
  }

  Message::Message()
    : _p(new qi::MessagePrivate())
  {
    memset(_p, 0, sizeof(MessagePrivate));
    _p->id = newMessageId();
    _p->magic = messageMagic;
    _p->buffer = new qi::Buffer();
    _p->deleteBuffer = true;
  }

  Message::Message(Buffer *buf)
    : _p(new qi::MessagePrivate())
  {
    memset(_p, 0, sizeof(MessagePrivate));
    _p->id = newMessageId();
    _p->magic = messageMagic;
    _p->buffer = buf;
    _p->deleteBuffer = false;
  }

  Message::Message(const Message &msg)
    : _p(new qi::MessagePrivate())
  {
    memcpy(_p, msg._p, sizeof(MessagePrivate));
    _p->deleteBuffer = false;
  }

  Message &Message::operator=(const Message &msg) {
    memcpy(_p, msg._p, sizeof(MessagePrivate));
    _p->buffer = msg._p->buffer;
    _p->deleteBuffer = false;
    return *this;
  }

  Message::~Message()
  {
    if (_p->deleteBuffer)
      delete _p->buffer;
    delete _p;
  }

  void Message::setBuffer(qi::Buffer *buffer) {
    _p->buffer = buffer;
    _p->deleteBuffer = false;
  }

  std::ostream& operator<<(std::ostream& os, const qi::Message& msg) {
    os << "message {"
       << "size=" << msg.size()
       << ", id=" << msg.id()
       << ", type=" << msg.type()
       << ", serv=" << msg.service()
       << ", path=" << msg.path()
       << ", func=" << msg.function()
       << "}";
    return os;
  }

  qi::DataStream& operator<<(qi::DataStream& os, const qi::Message& msg)
  {
    os << msg._p->magic
       << msg.id()
       << msg.size()
       << msg.type()
       << msg.service()
       << msg.path()
       << msg.function()
       << msg._p->reserved;

    qi::Buffer *buf = reinterpret_cast<qi::Buffer *>(os.ioDevice());
    evbuffer_add_buffer(buf->_p->data(), msg.buffer()->_p->data());
    return os;
  }

  unsigned int Message::size() const
  {
    return _p->buffer->size();
  }

  void Message::setId(uint32_t id)
  {
    _p->id = id;
  }

  unsigned int Message::id() const
  {
    return _p->id;
  }

  void Message::setType(uint32_t type)
  {
    _p->type = type;
  }

  unsigned int Message::type() const
  {
    return _p->type;
  }

  void Message::setService(uint32_t service)
  {
    _p->service = service;
  }

  unsigned int Message::service() const
  {
    return _p->service;
  }

  void Message::setPath(uint32_t path)
  {
    _p->path = path;
  }

  unsigned int Message::path() const
  {
    return _p->path;
  }

  void Message::setFunction(uint32_t function)
  {
    _p->function = function;
  }

  unsigned int Message::function() const
  {
    return _p->function;
  }

  qi::Buffer *Message::buffer() const
  {
    return _p->buffer;
  }

  void Message::buildReplyFrom(const Message &call)
  {
    setId(call.id());
    setType(qi::Message::Type_Reply);
    setService(call.service());
    setPath(call.path());
    setFunction(call.function());
  }

  void Message::buildForwardFrom(const Message &msg)
  {
    setType(msg.type());
    setService(msg.service());
    setPath(msg.path());
    setFunction(msg.function());
  }

  void Message::swap(Message &msg)
  {
    MessagePrivate *p = _p;
    _p = msg._p;
    msg._p = p;
  }

  bool Message::isValid() const
  {
    return (messageMagic == _p->magic);
  }
}
<|endoftext|>


<commit_before>/*
 * Universe
 *
 * Copyright 2015 Lubosz Sarnecki <lubosz@gmail.com>
 *
 */

#include <stdio.h>
#include <string>
#include <iostream>

#include "Simulator.h"
#include "Renderer.h"
#include "util.h"
#include <GL/glx.h>

Simulator::Simulator() {
    printf("Initialize OpenCL object and context\n");
    // setup devices and context
    std::vector<cl::Platform> platforms;
    err = cl::Platform::get(&platforms);
    printf("cl::Platform::get(): %s\n", oclErrorString(err));
    printf("platforms.size(): %ld\n", platforms.size());

    deviceUsed = 0;
    err = platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
    printf("getDevices: %s\n", oclErrorString(err));
    printf("devices.size(): %ld\n", devices.size());
    int t = devices.front().getInfo<CL_DEVICE_TYPE>();
    printf("type: device: %d CL_DEVICE_TYPE_GPU: %d \n", t, CL_DEVICE_TYPE_GPU);

    cl_context_properties props[] = {
        CL_GL_CONTEXT_KHR,
        reinterpret_cast<cl_context_properties>(glXGetCurrentContext()),
        CL_GLX_DISPLAY_KHR,
        reinterpret_cast<cl_context_properties>(glXGetCurrentDisplay()),
        CL_CONTEXT_PLATFORM,
        reinterpret_cast<cl_context_properties>((platforms[0])()),
        0
    };
    // cl_context cxGPUContext =
    // clCreateContext(props, 1, &cdDevices[uiDeviceUsed], NULL, NULL, &err);
    try {
        context = cl::Context(CL_DEVICE_TYPE_GPU, props);
    } catch (cl::Error er) {
        printf("ERROR: %s(%s)\n", er.what(), oclErrorString(er.err()));
    }

    // create the command queue we will use to execute OpenCL commands
    try {
        queue = cl::CommandQueue(context, devices[deviceUsed], 0, &err);
    } catch (cl::Error er) {
        printf("ERROR: %s(%d)\n", er.what(), er.err());
    }
}

Simulator::~Simulator() {}

void Simulator::loadProgram(std::string kernel_source) {
    // Program Setup
    int pl = kernel_source.size();
    try {
        cl::Program::Sources source(
                    1, std::make_pair(kernel_source.c_str(), pl));
        program = cl::Program(context, source);
    }
    catch (cl::Error er) {
        printf("ERROR: %s(%s)\n", er.what(), oclErrorString(er.err()));
    }

    try {
        // err = program.build(devices,
        // "-cl-nv-verbose -cl-nv-maxrregcount=100");
        err = program.build(devices);
    }
    catch (cl::Error er) {
        printf("program.build: %s\n", oclErrorString(er.err()));
    }
    std::cout << "Build Status: "
              << program.getBuildInfo<CL_PROGRAM_BUILD_STATUS>(devices[0])
              << std::endl << "Build Options:\t"
              << program.getBuildInfo<CL_PROGRAM_BUILD_OPTIONS>(devices[0])
              << std::endl << "Build Log:\t "
              << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0])
              << std::endl;
}

void Simulator::loadData(std::vector<Vec4> pos,
        std::vector<Vec4> vel,
        std::vector<Vec4> col,
        std::vector<float> mass) {
    // store the number of particles and the size in bytes of our arrays
    particleCount = pos.size();
    array_size = particleCount * sizeof(Vec4);
    // create VBOs (defined in util.cpp)
    positionVBO = Renderer::createVBO(
                &pos[0], array_size, GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW);
    colorVBO = Renderer::createVBO(
                &col[0], array_size, GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW);
    massVBO = Renderer::createVBO(
                mass.data(), particleCount * sizeof(GLfloat),
                GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW);
    // make sure OpenGL is finished before we proceed
    glFinish();
    printf("gl interop!\n");
    // create OpenCL buffer from GL VBO
    cl_vbos.push_back(cl::BufferGL(
                          context, CL_MEM_READ_WRITE, positionVBO, &err));
    cl_vbos.push_back(cl::BufferGL(
                          context, CL_MEM_READ_WRITE, colorVBO, &err));

    cl_vbos.push_back(cl::BufferGL(
                          context, CL_MEM_READ_WRITE, massVBO, &err));

    // create the OpenCL only arrays
    velocityBuffer =
            cl::Buffer(context, CL_MEM_WRITE_ONLY, array_size, NULL, &err);
    initialPositionBuffer =
            cl::Buffer(context, CL_MEM_WRITE_ONLY, array_size, NULL, &err);
    initivalVelocityBuffer =
            cl::Buffer(context, CL_MEM_WRITE_ONLY, array_size, NULL, &err);

    printf("Pushing data to the GPU\n");
    // push our CPU arrays to the GPU
    // data is tightly packed in std::vector
    // starting with the adress of the first element
    err = queue.enqueueWriteBuffer(
                velocityBuffer, CL_TRUE, 0, array_size,
                &vel[0], NULL, &event);
    err = queue.enqueueWriteBuffer(
                initialPositionBuffer, CL_TRUE, 0, array_size,
                &pos[0], NULL, &event);
    err = queue.enqueueWriteBuffer(
                initivalVelocityBuffer, CL_TRUE, 0, array_size,
                &vel[0], NULL, &event);
    queue.finish();
}

void Simulator::initKernel() {
    try {
        kernel = cl::Kernel(program, "vortex", &err);
    }
    catch (cl::Error er) {
        printf("ERROR: %s(%s)\n", er.what(), oclErrorString(er.err()));
    }

    try {
        err = kernel.setArg(0, cl_vbos[0]);
        err = kernel.setArg(1, cl_vbos[1]);
        err = kernel.setArg(2, cl_vbos[2]);
        err = kernel.setArg(3, velocityBuffer);
        err = kernel.setArg(4, initialPositionBuffer);
        err = kernel.setArg(5, initivalVelocityBuffer);
    }
    catch (cl::Error er) {
        printf("ERROR: %s(%s)\n", er.what(), oclErrorString(er.err()));
    }
    // Wait for the command queue to finish these commands before proceeding
    queue.finish();
}

void Simulator::runKernel() {
    // this will update our system by calculating new velocity
    // and updating the positions of our particles
    // Make sure OpenGL is done using our VBOs
    glFinish();
    // map OpenGL buffer object for writing from OpenCL
    // this passes in the vector of VBO buffer objects (position and color)
    err = queue.enqueueAcquireGLObjects(&cl_vbos, NULL, &event);

    // pass in the timestep
    float dt = .01f;
    kernel.setArg(6, dt);
    // execute the kernel
    err = queue.enqueueNDRangeKernel(
                kernel,
                cl::NullRange,
                cl::NDRange(particleCount),
                cl::NullRange, NULL, &event);
    // printf("clEnqueueNDRangeKernel: %s\n", oclErrorString(err));
    queue.finish();

    // Release the VBOs so OpenGL can play with them
    err = queue.enqueueReleaseGLObjects(&cl_vbos, NULL, &event);
    queue.finish();
}

const char* Simulator::oclErrorString(cl_int error) {
    static const char* errorString[] = {
        "CL_SUCCESS",
        "CL_DEVICE_NOT_FOUND",
        "CL_DEVICE_NOT_AVAILABLE",
        "CL_COMPILER_NOT_AVAILABLE",
        "CL_MEM_OBJECT_ALLOCATION_FAILURE",
        "CL_OUT_OF_RESOURCES",
        "CL_OUT_OF_HOST_MEMORY",
        "CL_PROFILING_INFO_NOT_AVAILABLE",
        "CL_MEM_COPY_OVERLAP",
        "CL_IMAGE_FORMAT_MISMATCH",
        "CL_IMAGE_FORMAT_NOT_SUPPORTED",
        "CL_BUILD_PROGRAM_FAILURE",
        "CL_MAP_FAILURE",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "CL_INVALID_VALUE",
        "CL_INVALID_DEVICE_TYPE",
        "CL_INVALID_PLATFORM",
        "CL_INVALID_DEVICE",
        "CL_INVALID_CONTEXT",
        "CL_INVALID_QUEUE_PROPERTIES",
        "CL_INVALID_COMMAND_QUEUE",
        "CL_INVALID_HOST_PTR",
        "CL_INVALID_MEM_OBJECT",
        "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR",
        "CL_INVALID_IMAGE_SIZE",
        "CL_INVALID_SAMPLER",
        "CL_INVALID_BINARY",
        "CL_INVALID_BUILD_OPTIONS",
        "CL_INVALID_PROGRAM",
        "CL_INVALID_PROGRAM_EXECUTABLE",
        "CL_INVALID_KERNEL_NAME",
        "CL_INVALID_KERNEL_DEFINITION",
        "CL_INVALID_KERNEL",
        "CL_INVALID_ARG_INDEX",
        "CL_INVALID_ARG_VALUE",
        "CL_INVALID_ARG_SIZE",
        "CL_INVALID_KERNEL_ARGS",
        "CL_INVALID_WORK_DIMENSION",
        "CL_INVALID_WORK_GROUP_SIZE",
        "CL_INVALID_WORK_ITEM_SIZE",
        "CL_INVALID_GLOBAL_OFFSET",
        "CL_INVALID_EVENT_WAIT_LIST",
        "CL_INVALID_EVENT",
        "CL_INVALID_OPERATION",
        "CL_INVALID_GL_OBJECT",
        "CL_INVALID_BUFFER_SIZE",
        "CL_INVALID_MIP_LEVEL",
        "CL_INVALID_GLOBAL_WORK_SIZE",
    };
    const int errorCount = sizeof(errorString) / sizeof(errorString[0]);
    const int index = -error;
    return (index >= 0 && index < errorCount) ? errorString[index] : "";
}
<commit_msg>sim: print platforms, cat getDevices error.<commit_after>/*
 * Universe
 *
 * Copyright 2015 Lubosz Sarnecki <lubosz@gmail.com>
 *
 */

#include <stdio.h>
#include <string>
#include <iostream>

#include "Simulator.h"
#include "Renderer.h"
#include "util.h"
#include <GL/glx.h>

Simulator::Simulator() {
    printf("Initialize OpenCL object and context\n");
    // setup devices and context
    std::vector<cl::Platform> platforms;
    err = cl::Platform::get(&platforms);
    printf("cl::Platform::get(): %s\n", oclErrorString(err));
    printf("platforms.size(): %ld\n", platforms.size());

    for (auto platform : platforms) {
        std::string platformName;
        platform.getInfo(CL_PLATFORM_NAME, &platformName);
        std::cout << platformName << "\n";
    }

    deviceUsed = 0;

    try {
        err = platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
    } catch (cl::Error er) {
        printf("ERROR: %s(%s)\n", er.what(), oclErrorString(er.err()));
    }

    printf("getDevices: %s\n", oclErrorString(err));
    printf("devices.size(): %ld\n", devices.size());
    int t = devices.front().getInfo<CL_DEVICE_TYPE>();
    printf("type: device: %d CL_DEVICE_TYPE_GPU: %d \n", t, CL_DEVICE_TYPE_GPU);

    cl_context_properties props[] = {
        CL_GL_CONTEXT_KHR,
        reinterpret_cast<cl_context_properties>(glXGetCurrentContext()),
        CL_GLX_DISPLAY_KHR,
        reinterpret_cast<cl_context_properties>(glXGetCurrentDisplay()),
        CL_CONTEXT_PLATFORM,
        reinterpret_cast<cl_context_properties>((platforms[0])()),
        0
    };
    // cl_context cxGPUContext =
    // clCreateContext(props, 1, &cdDevices[uiDeviceUsed], NULL, NULL, &err);
    try {
        context = cl::Context(CL_DEVICE_TYPE_GPU, props);
    } catch (cl::Error er) {
        printf("ERROR: %s(%s)\n", er.what(), oclErrorString(er.err()));
    }

    // create the command queue we will use to execute OpenCL commands
    try {
        queue = cl::CommandQueue(context, devices[deviceUsed], 0, &err);
    } catch (cl::Error er) {
        printf("ERROR: %s(%d)\n", er.what(), er.err());
    }
}

Simulator::~Simulator() {}

void Simulator::loadProgram(std::string kernel_source) {
    // Program Setup
    int pl = kernel_source.size();
    try {
        cl::Program::Sources source(
                    1, std::make_pair(kernel_source.c_str(), pl));
        program = cl::Program(context, source);
    }
    catch (cl::Error er) {
        printf("ERROR: %s(%s)\n", er.what(), oclErrorString(er.err()));
    }

    try {
        // err = program.build(devices,
        // "-cl-nv-verbose -cl-nv-maxrregcount=100");
        err = program.build(devices);
    }
    catch (cl::Error er) {
        printf("program.build: %s\n", oclErrorString(er.err()));
    }
    std::cout << "Build Status: "
              << program.getBuildInfo<CL_PROGRAM_BUILD_STATUS>(devices[0])
              << std::endl << "Build Options:\t"
              << program.getBuildInfo<CL_PROGRAM_BUILD_OPTIONS>(devices[0])
              << std::endl << "Build Log:\t "
              << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0])
              << std::endl;
}

void Simulator::loadData(std::vector<Vec4> pos,
        std::vector<Vec4> vel,
        std::vector<Vec4> col,
        std::vector<float> mass) {
    // store the number of particles and the size in bytes of our arrays
    particleCount = pos.size();
    array_size = particleCount * sizeof(Vec4);
    // create VBOs (defined in util.cpp)
    positionVBO = Renderer::createVBO(
                &pos[0], array_size, GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW);
    colorVBO = Renderer::createVBO(
                &col[0], array_size, GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW);
    massVBO = Renderer::createVBO(
                mass.data(), particleCount * sizeof(GLfloat),
                GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW);
    // make sure OpenGL is finished before we proceed
    glFinish();
    printf("gl interop!\n");
    // create OpenCL buffer from GL VBO
    cl_vbos.push_back(cl::BufferGL(
                          context, CL_MEM_READ_WRITE, positionVBO, &err));
    cl_vbos.push_back(cl::BufferGL(
                          context, CL_MEM_READ_WRITE, colorVBO, &err));

    cl_vbos.push_back(cl::BufferGL(
                          context, CL_MEM_READ_WRITE, massVBO, &err));

    // create the OpenCL only arrays
    velocityBuffer =
            cl::Buffer(context, CL_MEM_WRITE_ONLY, array_size, NULL, &err);
    initialPositionBuffer =
            cl::Buffer(context, CL_MEM_WRITE_ONLY, array_size, NULL, &err);
    initivalVelocityBuffer =
            cl::Buffer(context, CL_MEM_WRITE_ONLY, array_size, NULL, &err);

    printf("Pushing data to the GPU\n");
    // push our CPU arrays to the GPU
    // data is tightly packed in std::vector
    // starting with the adress of the first element
    err = queue.enqueueWriteBuffer(
                velocityBuffer, CL_TRUE, 0, array_size,
                &vel[0], NULL, &event);
    err = queue.enqueueWriteBuffer(
                initialPositionBuffer, CL_TRUE, 0, array_size,
                &pos[0], NULL, &event);
    err = queue.enqueueWriteBuffer(
                initivalVelocityBuffer, CL_TRUE, 0, array_size,
                &vel[0], NULL, &event);
    queue.finish();
}

void Simulator::initKernel() {
    try {
        kernel = cl::Kernel(program, "vortex", &err);
    }
    catch (cl::Error er) {
        printf("ERROR: %s(%s)\n", er.what(), oclErrorString(er.err()));
    }

    try {
        err = kernel.setArg(0, cl_vbos[0]);
        err = kernel.setArg(1, cl_vbos[1]);
        err = kernel.setArg(2, cl_vbos[2]);
        err = kernel.setArg(3, velocityBuffer);
        err = kernel.setArg(4, initialPositionBuffer);
        err = kernel.setArg(5, initivalVelocityBuffer);
    }
    catch (cl::Error er) {
        printf("ERROR: %s(%s)\n", er.what(), oclErrorString(er.err()));
    }
    // Wait for the command queue to finish these commands before proceeding
    queue.finish();
}

void Simulator::runKernel() {
    // this will update our system by calculating new velocity
    // and updating the positions of our particles
    // Make sure OpenGL is done using our VBOs
    glFinish();
    // map OpenGL buffer object for writing from OpenCL
    // this passes in the vector of VBO buffer objects (position and color)
    err = queue.enqueueAcquireGLObjects(&cl_vbos, NULL, &event);

    // pass in the timestep
    float dt = .01f;
    kernel.setArg(6, dt);
    // execute the kernel
    err = queue.enqueueNDRangeKernel(
                kernel,
                cl::NullRange,
                cl::NDRange(particleCount),
                cl::NullRange, NULL, &event);
    // printf("clEnqueueNDRangeKernel: %s\n", oclErrorString(err));
    queue.finish();

    // Release the VBOs so OpenGL can play with them
    err = queue.enqueueReleaseGLObjects(&cl_vbos, NULL, &event);
    queue.finish();
}

const char* Simulator::oclErrorString(cl_int error) {
    static const char* errorString[] = {
        "CL_SUCCESS",
        "CL_DEVICE_NOT_FOUND",
        "CL_DEVICE_NOT_AVAILABLE",
        "CL_COMPILER_NOT_AVAILABLE",
        "CL_MEM_OBJECT_ALLOCATION_FAILURE",
        "CL_OUT_OF_RESOURCES",
        "CL_OUT_OF_HOST_MEMORY",
        "CL_PROFILING_INFO_NOT_AVAILABLE",
        "CL_MEM_COPY_OVERLAP",
        "CL_IMAGE_FORMAT_MISMATCH",
        "CL_IMAGE_FORMAT_NOT_SUPPORTED",
        "CL_BUILD_PROGRAM_FAILURE",
        "CL_MAP_FAILURE",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "CL_INVALID_VALUE",
        "CL_INVALID_DEVICE_TYPE",
        "CL_INVALID_PLATFORM",
        "CL_INVALID_DEVICE",
        "CL_INVALID_CONTEXT",
        "CL_INVALID_QUEUE_PROPERTIES",
        "CL_INVALID_COMMAND_QUEUE",
        "CL_INVALID_HOST_PTR",
        "CL_INVALID_MEM_OBJECT",
        "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR",
        "CL_INVALID_IMAGE_SIZE",
        "CL_INVALID_SAMPLER",
        "CL_INVALID_BINARY",
        "CL_INVALID_BUILD_OPTIONS",
        "CL_INVALID_PROGRAM",
        "CL_INVALID_PROGRAM_EXECUTABLE",
        "CL_INVALID_KERNEL_NAME",
        "CL_INVALID_KERNEL_DEFINITION",
        "CL_INVALID_KERNEL",
        "CL_INVALID_ARG_INDEX",
        "CL_INVALID_ARG_VALUE",
        "CL_INVALID_ARG_SIZE",
        "CL_INVALID_KERNEL_ARGS",
        "CL_INVALID_WORK_DIMENSION",
        "CL_INVALID_WORK_GROUP_SIZE",
        "CL_INVALID_WORK_ITEM_SIZE",
        "CL_INVALID_GLOBAL_OFFSET",
        "CL_INVALID_EVENT_WAIT_LIST",
        "CL_INVALID_EVENT",
        "CL_INVALID_OPERATION",
        "CL_INVALID_GL_OBJECT",
        "CL_INVALID_BUFFER_SIZE",
        "CL_INVALID_MIP_LEVEL",
        "CL_INVALID_GLOBAL_WORK_SIZE",
    };
    const int errorCount = sizeof(errorString) / sizeof(errorString[0]);
    const int index = -error;
    return (index >= 0 && index < errorCount) ? errorString[index] : "";
}
<|endoftext|>


<commit_before>#ifndef TYPES_HPP
#define TYPES_HPP

#include <stdint.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/optional.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

enum user_status_enum {
  user_status_pending,
  user_status_active,
  user_status_confirmed,
  user_status_suspended,
  user_status_deleted
};

enum format_enum {
  format_html,
  format_markdown,
  format_text
};

enum nwr_enum {
  nwr_node,
  nwr_way,
  nwr_relation
};

struct user {
  static const int num_keys = 1;
  static const std::vector<std::string> &column_names();

  int64_t id;
  std::string display_name;
  bool data_public;
};

BOOST_FUSION_ADAPT_STRUCT(
  user,
  (int64_t, id)
  (std::string, display_name)
  (bool, data_public)
  )

struct changeset {
  static const int num_keys = 1;
  static const std::vector<std::string> &column_names();

  int64_t id;
  int32_t uid;
  boost::posix_time::ptime created_at;
  boost::optional<int32_t> min_lat, max_lat, min_lon, max_lon;
  boost::posix_time::ptime closed_at;
  int32_t num_changes;
};

BOOST_FUSION_ADAPT_STRUCT(
  changeset,
  (int64_t, id)
  (int32_t, uid)
  (boost::posix_time::ptime, created_at)
  (boost::optional<int32_t>, min_lat)
  (boost::optional<int32_t>, max_lat)
  (boost::optional<int32_t>, min_lon)
  (boost::optional<int32_t>, max_lon)
  (boost::posix_time::ptime, closed_at)
  (int32_t, num_changes)
  )

struct current_tag {
  static const int num_keys = 2;
  static const std::vector<std::string> &column_names();

  int64_t element_id;
  std::string key, value;
};

BOOST_FUSION_ADAPT_STRUCT(
  current_tag,
  (int64_t, element_id)
  (std::string, key)
  (std::string, value)
  )

struct old_tag {
  static const int num_keys = 3;
  static const std::vector<std::string> &column_names();

  int64_t element_id, version;
  std::string key, value;
};

BOOST_FUSION_ADAPT_STRUCT(
  old_tag,
  (int64_t, element_id)
  (int64_t, version)
  (std::string, key)
  (std::string, value)
  )

struct node {
  static const int num_keys = 2;
  static const std::vector<std::string> &column_names();
  static const std::string table_name();
  static const std::string tag_table_name();
  static const std::string inner_table_name();

  typedef old_tag tag_type;
  typedef int inner_type;

  int64_t id, version, changeset_id;
  bool visible;
  boost::posix_time::ptime timestamp;
  int32_t latitude, longitude;
};

BOOST_FUSION_ADAPT_STRUCT(
  node,
  (int64_t, id)
  (int64_t, version)
  (int64_t, changeset_id)
  (bool, visible)
  (boost::posix_time::ptime, timestamp)
  (int32_t, latitude)
  (int32_t, longitude)
  )

struct way_node {
  static const int num_keys = 3;
  static const std::vector<std::string> &column_names();

  int64_t way_id, version, sequence_id, node_id;
};

BOOST_FUSION_ADAPT_STRUCT(
  way_node,
  (int64_t, way_id)
  (int64_t, version)
  (int64_t, sequence_id)
  (int64_t, node_id)
  )

struct way {
  static const int num_keys = 2;
  static const std::vector<std::string> &column_names();
  static const std::string table_name();
  static const std::string tag_table_name();
  static const std::string inner_table_name();

  typedef old_tag tag_type;
  typedef way_node inner_type;

  int64_t id, version, changeset_id;
  bool visible;
  boost::posix_time::ptime timestamp;
};

BOOST_FUSION_ADAPT_STRUCT(
  way,
  (int64_t, id)
  (int64_t, version)
  (int64_t, changeset_id)
  (bool, visible)
  (boost::posix_time::ptime, timestamp)
  )

struct relation_member {
  static const int num_keys = 3;
  static const std::vector<std::string> &column_names();

  int64_t relation_id, version, sequence_id;
  nwr_enum member_type;
  int64_t member_id;
  std::string member_role;
};

BOOST_FUSION_ADAPT_STRUCT(
  relation_member,
  (int64_t, relation_id)
  (int64_t, version)
  (int64_t, sequence_id)
  (nwr_enum, member_type)
  (int64_t, member_id)
  (std::string, member_role)
  )

struct relation {
  static const int num_keys = 2;
  static const std::vector<std::string> &column_names();
  static const std::string table_name();
  static const std::string tag_table_name();
  static const std::string inner_table_name();

  typedef old_tag tag_type;
  typedef relation_member inner_type;

  int64_t id, version, changeset_id;
  bool visible;
  boost::posix_time::ptime timestamp;
};

BOOST_FUSION_ADAPT_STRUCT(
  relation,
  (int64_t, id)
  (int64_t, version)
  (int64_t, changeset_id)
  (bool, visible)
  (boost::posix_time::ptime, timestamp)
  )

#endif /* TYPES_HPP */
<commit_msg>Added redaction IDs to nodes, ways, relations.<commit_after>#ifndef TYPES_HPP
#define TYPES_HPP

#include <stdint.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/optional.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

enum user_status_enum {
  user_status_pending,
  user_status_active,
  user_status_confirmed,
  user_status_suspended,
  user_status_deleted
};

enum format_enum {
  format_html,
  format_markdown,
  format_text
};

enum nwr_enum {
  nwr_node,
  nwr_way,
  nwr_relation
};

struct user {
  static const int num_keys = 1;
  static const std::vector<std::string> &column_names();

  int64_t id;
  std::string display_name;
  bool data_public;
};

BOOST_FUSION_ADAPT_STRUCT(
  user,
  (int64_t, id)
  (std::string, display_name)
  (bool, data_public)
  )

struct changeset {
  static const int num_keys = 1;
  static const std::vector<std::string> &column_names();

  int64_t id;
  int32_t uid;
  boost::posix_time::ptime created_at;
  boost::optional<int32_t> min_lat, max_lat, min_lon, max_lon;
  boost::posix_time::ptime closed_at;
  int32_t num_changes;
};

BOOST_FUSION_ADAPT_STRUCT(
  changeset,
  (int64_t, id)
  (int32_t, uid)
  (boost::posix_time::ptime, created_at)
  (boost::optional<int32_t>, min_lat)
  (boost::optional<int32_t>, max_lat)
  (boost::optional<int32_t>, min_lon)
  (boost::optional<int32_t>, max_lon)
  (boost::posix_time::ptime, closed_at)
  (int32_t, num_changes)
  )

struct current_tag {
  static const int num_keys = 2;
  static const std::vector<std::string> &column_names();

  int64_t element_id;
  std::string key, value;
};

BOOST_FUSION_ADAPT_STRUCT(
  current_tag,
  (int64_t, element_id)
  (std::string, key)
  (std::string, value)
  )

struct old_tag {
  static const int num_keys = 3;
  static const std::vector<std::string> &column_names();

  int64_t element_id, version;
  std::string key, value;
};

BOOST_FUSION_ADAPT_STRUCT(
  old_tag,
  (int64_t, element_id)
  (int64_t, version)
  (std::string, key)
  (std::string, value)
  )

struct node {
  static const int num_keys = 2;
  static const std::vector<std::string> &column_names();
  static const std::string table_name();
  static const std::string tag_table_name();
  static const std::string inner_table_name();

  typedef old_tag tag_type;
  typedef int inner_type;

  int64_t id, version, changeset_id;
  bool visible;
  boost::posix_time::ptime timestamp;
  boost::optional<int64_t> redaction_id;
  int32_t latitude, longitude;
};

BOOST_FUSION_ADAPT_STRUCT(
  node,
  (int64_t, id)
  (int64_t, version)
  (int64_t, changeset_id)
  (bool, visible)
  (boost::posix_time::ptime, timestamp)
  (boost::optional<int64_t>, redaction_id)
  (int32_t, latitude)
  (int32_t, longitude)
  )

struct way_node {
  static const int num_keys = 3;
  static const std::vector<std::string> &column_names();

  int64_t way_id, version, sequence_id, node_id;
};

BOOST_FUSION_ADAPT_STRUCT(
  way_node,
  (int64_t, way_id)
  (int64_t, version)
  (int64_t, sequence_id)
  (int64_t, node_id)
  )

struct way {
  static const int num_keys = 2;
  static const std::vector<std::string> &column_names();
  static const std::string table_name();
  static const std::string tag_table_name();
  static const std::string inner_table_name();

  typedef old_tag tag_type;
  typedef way_node inner_type;

  int64_t id, version, changeset_id;
  bool visible;
  boost::posix_time::ptime timestamp;
  boost::optional<int64_t> redaction_id;
};

BOOST_FUSION_ADAPT_STRUCT(
  way,
  (int64_t, id)
  (int64_t, version)
  (int64_t, changeset_id)
  (bool, visible)
  (boost::posix_time::ptime, timestamp)
  (boost::optional<int64_t>, redaction_id)
  )

struct relation_member {
  static const int num_keys = 3;
  static const std::vector<std::string> &column_names();

  int64_t relation_id, version, sequence_id;
  nwr_enum member_type;
  int64_t member_id;
  std::string member_role;
};

BOOST_FUSION_ADAPT_STRUCT(
  relation_member,
  (int64_t, relation_id)
  (int64_t, version)
  (int64_t, sequence_id)
  (nwr_enum, member_type)
  (int64_t, member_id)
  (std::string, member_role)
  )

struct relation {
  static const int num_keys = 2;
  static const std::vector<std::string> &column_names();
  static const std::string table_name();
  static const std::string tag_table_name();
  static const std::string inner_table_name();

  typedef old_tag tag_type;
  typedef relation_member inner_type;

  int64_t id, version, changeset_id;
  bool visible;
  boost::posix_time::ptime timestamp;
  boost::optional<int64_t> redaction_id;
};

BOOST_FUSION_ADAPT_STRUCT(
  relation,
  (int64_t, id)
  (int64_t, version)
  (int64_t, changeset_id)
  (bool, visible)
  (boost::posix_time::ptime, timestamp)
  (boost::optional<int64_t>, redaction_id)
  )

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


<commit_before>/** \brief Command-line utility to send email messages.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2018,2019 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 <iostream>
#include <cstdlib>
#include "IniFile.h"
#include "EmailSender.h"
#include "FileUtil.h"
#include "MiscUtil.h"
#include "StringUtil.h"
#include "TextUtil.h"
#include "UBTools.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname << " [--sender=sender] [-reply-to=reply_to] --recipients=recipients\n"
              << "  [--cc-recipients=cc_recipients] [--bcc-recipients=bcc_recipients] [--expand-newline-escapes]\n"
              << "  --subject=subject --message-body=message_body [--priority=priority] [--format=format]\n"
              << "  [--attachment=file1 --attachment=file2 .. --attachment=fileN]\n\n"
              << "       \"priority\" has to be one of \"very_low\", \"low\", \"medium\", \"high\", or\n"
              << "       \"very_high\".  \"format\" has to be one of \"plain_text\" or \"html\"  At least one\n"
              << "       of \"sender\" or \"reply-to\" has to be specified. If \"--expand-newline-escapes\" has\n"
              << "       been specified, all occurrences of \\n in the message body will be replaced by a line feed\n"
              << "       and a double backslash by a single backslash.  The message body is assumed to be UTF-8!\n\n";
    std::exit(EXIT_FAILURE);
}

EmailSender::Priority StringToPriority(const std::string &priority_candidate) {
    if (priority_candidate == "very_low")
        return EmailSender::VERY_LOW;
    if (priority_candidate == "low")
        return EmailSender::LOW;
    if (priority_candidate == "medium")
        return EmailSender::MEDIUM;
    if (priority_candidate == "high")
        return EmailSender::HIGH;
    if (priority_candidate == "very_high")
        return EmailSender::VERY_HIGH;
    LOG_ERROR("\"" + priority_candidate + "\" is an unknown priority!");
}

EmailSender::Format StringToFormat(const std::string &format_candidate) {
    if (format_candidate == "plain_text")
        return EmailSender::PLAIN_TEXT;
    else if (format_candidate == "html")
        return EmailSender::HTML;
    LOG_ERROR("\"" + format_candidate + "\" is an unknown format!");
}

bool ExtractArg(const char * const argument, const std::string &arg_name, std::string * const arg_value) {
    if (StringUtil::StartsWith(argument, "--" + arg_name + "=")) {
        *arg_value = argument + arg_name.length() + 3 /* two dashes and one equal sign */;
        if (arg_value->empty())
            LOG_ERROR(arg_name + " is missing!");

        return true;
    }

    return false;
}

void ParseCommandLine(char **argv, std::string * const sender, std::string * const reply_to, std::string * const recipients,
                      std::string * const cc_recipients, std::string * const bcc_recipients, std::string * const subject,
                      std::string * const message_body, std::string * const priority, std::string * const format,
                      bool * const expand_newline_escapes, std::vector<std::string> * const attachments)
{
    *expand_newline_escapes = false;
    std::string attachment;
    while (*argv != nullptr) {
        if (std::strcmp(*argv, "--expand-newline-escapes") == 0) {
            *expand_newline_escapes = true;
            ++argv;
        } else if (ExtractArg(*argv, "attachment", &attachment)) {
            if (not FileUtil::IsReadable(attachment))
                LOG_ERROR("attachment \"" + attachment + "\" does not exist or isn't readable!");
            attachments->emplace_back(attachment);
            ++argv;
        } else if (ExtractArg(*argv, "sender", sender) or ExtractArg(*argv, "reply-to", reply_to)
            or ExtractArg(*argv, "recipients", recipients) or ExtractArg(*argv, "cc-recipients", cc_recipients)
            or ExtractArg(*argv, "bcc-recipients", bcc_recipients) or ExtractArg(*argv, "subject", subject)
            or ExtractArg(*argv, "message-body", message_body) or ExtractArg(*argv, "priority", priority)
            or ExtractArg(*argv, "format", format))
            ++argv;
        else
            LOG_ERROR("unknown argument: " + std::string(*argv));
    }

    if (recipients->empty() and cc_recipients->empty() and bcc_recipients->empty())
        LOG_ERROR("you must specify a recipient!");
    if (subject->empty())
        LOG_ERROR("you must specify a subject!");
    if (message_body->empty())
        LOG_ERROR("you must specify a message-body!");
}

std::vector<std::string> SplitRecipients(const std::string &recipients) {
    std::vector<std::string> individual_recipients;
    StringUtil::Split(recipients, ',', &individual_recipients, /* suppress_empty_components = */true);
    return individual_recipients;
}

// "text" is assumed to be UTF-8 encoded.
std::string ExpandNewlineEscapes(const std::string &text) {
    std::wstring escaped_string;
    if (unlikely(not TextUtil::UTF8ToWCharString(text, &escaped_string)))
        LOG_ERROR("can't convert a supposed UTF-8 string to a wide string!");

    std::wstring unescaped_string;
    bool backslash_seen(false);
    for (auto ch : escaped_string) {
        if (backslash_seen) {
            if (ch == '\\')
                unescaped_string += '\\';
            else if (ch == 'n')
                unescaped_string += '\n';
            else {
                std::string utf8_string;
                TextUtil::WCharToUTF8String(ch, &utf8_string);
                LOG_ERROR("unknown escape: \\" + utf8_string + "!");
            }
            backslash_seen = false;
        } else if (ch == '\\')
            backslash_seen = true;
        else
            unescaped_string += ch;
    }

    std::string utf8_string;
    if (unlikely(not TextUtil::WCharToUTF8String(unescaped_string, &utf8_string)))
        LOG_ERROR("can't convert a supposed wide string to a UTF-8 string!");

    return utf8_string;
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc == 1)
        Usage();

    EmailSender::Priority priority(EmailSender::DO_NOT_SET_PRIORITY);
    EmailSender::Format format(EmailSender::PLAIN_TEXT);

    std::string sender, reply_to, recipients, cc_recipients, bcc_recipients, subject, message_body, priority_as_string,
        format_as_string;
    bool expand_newline_escapes;
    std::vector<std::string> attachments;
    ParseCommandLine(++argv, &sender, &reply_to, &recipients, &cc_recipients, &bcc_recipients, &subject, &message_body,
                     &priority_as_string, &format_as_string, &expand_newline_escapes, &attachments);

    if (sender.empty() and reply_to.empty()) {
        IniFile ini_file(UBTools::GetTuelibPath() + "cronjobs/smtp_server.conf");
        sender = ini_file.getString("SMTPServer", "server_user") + "@uni-tuebingen.de";
    }

    if (not priority_as_string.empty())
        priority = StringToPriority(priority_as_string);
    if (not format_as_string.empty())
        format = StringToFormat(format_as_string);

    if (expand_newline_escapes)
        message_body = ExpandNewlineEscapes(message_body);

    const unsigned short response_code(EmailSender::SendEmail(sender, SplitRecipients(recipients), SplitRecipients(cc_recipients),
                                                              SplitRecipients(bcc_recipients), subject, message_body, priority, format,
                                                              reply_to, /* use_ssl = */true, /* use_authentication = */true, attachments));
    if (response_code >= 300) {
        if (not MiscUtil::EnvironmentVariableExists("ENABLE_SMPT_CLIENT_PERFORM_LOGGING"))
            LOG_ERROR("failed to send your email, the response code was: " + std::to_string(response_code)
                      + " (You may want to set the ENABLE_SMPT_CLIENT_PERFORM_LOGGING to debug the problem.)");
        else
            LOG_ERROR("failed to send your email, the response code was: " + std::to_string(response_code));
    }

    return EXIT_SUCCESS;
}
<commit_msg>Added support for tilde expansion.<commit_after>/** \brief Command-line utility to send email messages.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2018,2019 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 <iostream>
#include <cstdlib>
#include "IniFile.h"
#include "EmailSender.h"
#include "FileUtil.h"
#include "MiscUtil.h"
#include "StringUtil.h"
#include "TextUtil.h"
#include "UBTools.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname << " [--sender=sender] [-reply-to=reply_to] --recipients=recipients\n"
              << "  [--cc-recipients=cc_recipients] [--bcc-recipients=bcc_recipients] [--expand-newline-escapes]\n"
              << "  --subject=subject --message-body=message_body [--priority=priority] [--format=format]\n"
              << "  [--attachment=file1 --attachment=file2 .. --attachment=fileN]\n\n"
              << "       \"priority\" has to be one of \"very_low\", \"low\", \"medium\", \"high\", or\n"
              << "       \"very_high\".  \"format\" has to be one of \"plain_text\" or \"html\"  At least one\n"
              << "       of \"sender\" or \"reply-to\" has to be specified. If \"--expand-newline-escapes\" has\n"
              << "       been specified, all occurrences of \\n in the message body will be replaced by a line feed\n"
              << "       and a double backslash by a single backslash.  The message body is assumed to be UTF-8!\n\n";
    std::exit(EXIT_FAILURE);
}

EmailSender::Priority StringToPriority(const std::string &priority_candidate) {
    if (priority_candidate == "very_low")
        return EmailSender::VERY_LOW;
    if (priority_candidate == "low")
        return EmailSender::LOW;
    if (priority_candidate == "medium")
        return EmailSender::MEDIUM;
    if (priority_candidate == "high")
        return EmailSender::HIGH;
    if (priority_candidate == "very_high")
        return EmailSender::VERY_HIGH;
    LOG_ERROR("\"" + priority_candidate + "\" is an unknown priority!");
}

EmailSender::Format StringToFormat(const std::string &format_candidate) {
    if (format_candidate == "plain_text")
        return EmailSender::PLAIN_TEXT;
    else if (format_candidate == "html")
        return EmailSender::HTML;
    LOG_ERROR("\"" + format_candidate + "\" is an unknown format!");
}

bool ExtractArg(const char * const argument, const std::string &arg_name, std::string * const arg_value) {
    if (StringUtil::StartsWith(argument, "--" + arg_name + "=")) {
        *arg_value = argument + arg_name.length() + 3 /* two dashes and one equal sign */;
        if (arg_value->empty())
            LOG_ERROR(arg_name + " is missing!");

        return true;
    }

    return false;
}

void ParseCommandLine(char **argv, std::string * const sender, std::string * const reply_to, std::string * const recipients,
                      std::string * const cc_recipients, std::string * const bcc_recipients, std::string * const subject,
                      std::string * const message_body, std::string * const priority, std::string * const format,
                      bool * const expand_newline_escapes, std::vector<std::string> * const attachments)
{
    *expand_newline_escapes = false;
    std::string attachment;
    while (*argv != nullptr) {
        if (std::strcmp(*argv, "--expand-newline-escapes") == 0) {
            *expand_newline_escapes = true;
            ++argv;
        } else if (ExtractArg(*argv, "attachment", &attachment)) {
            attachment = FileUtil::ExpandTildePath(attachment);
            if (not FileUtil::IsReadable(attachment))
                LOG_ERROR("attachment \"" + attachment + "\" does not exist or isn't readable!");
            attachments->emplace_back(attachment);
            ++argv;
        } else if (ExtractArg(*argv, "sender", sender) or ExtractArg(*argv, "reply-to", reply_to)
            or ExtractArg(*argv, "recipients", recipients) or ExtractArg(*argv, "cc-recipients", cc_recipients)
            or ExtractArg(*argv, "bcc-recipients", bcc_recipients) or ExtractArg(*argv, "subject", subject)
            or ExtractArg(*argv, "message-body", message_body) or ExtractArg(*argv, "priority", priority)
            or ExtractArg(*argv, "format", format))
            ++argv;
        else
            LOG_ERROR("unknown argument: " + std::string(*argv));
    }

    if (recipients->empty() and cc_recipients->empty() and bcc_recipients->empty())
        LOG_ERROR("you must specify a recipient!");
    if (subject->empty())
        LOG_ERROR("you must specify a subject!");
    if (message_body->empty())
        LOG_ERROR("you must specify a message-body!");
}

std::vector<std::string> SplitRecipients(const std::string &recipients) {
    std::vector<std::string> individual_recipients;
    StringUtil::Split(recipients, ',', &individual_recipients, /* suppress_empty_components = */true);
    return individual_recipients;
}

// "text" is assumed to be UTF-8 encoded.
std::string ExpandNewlineEscapes(const std::string &text) {
    std::wstring escaped_string;
    if (unlikely(not TextUtil::UTF8ToWCharString(text, &escaped_string)))
        LOG_ERROR("can't convert a supposed UTF-8 string to a wide string!");

    std::wstring unescaped_string;
    bool backslash_seen(false);
    for (auto ch : escaped_string) {
        if (backslash_seen) {
            if (ch == '\\')
                unescaped_string += '\\';
            else if (ch == 'n')
                unescaped_string += '\n';
            else {
                std::string utf8_string;
                TextUtil::WCharToUTF8String(ch, &utf8_string);
                LOG_ERROR("unknown escape: \\" + utf8_string + "!");
            }
            backslash_seen = false;
        } else if (ch == '\\')
            backslash_seen = true;
        else
            unescaped_string += ch;
    }

    std::string utf8_string;
    if (unlikely(not TextUtil::WCharToUTF8String(unescaped_string, &utf8_string)))
        LOG_ERROR("can't convert a supposed wide string to a UTF-8 string!");

    return utf8_string;
}

} // unnamed namespace

int Main(int argc, char *argv[]) {
    if (argc == 1)
        Usage();

    EmailSender::Priority priority(EmailSender::DO_NOT_SET_PRIORITY);
    EmailSender::Format format(EmailSender::PLAIN_TEXT);

    std::string sender, reply_to, recipients, cc_recipients, bcc_recipients, subject, message_body, priority_as_string,
        format_as_string;
    bool expand_newline_escapes;
    std::vector<std::string> attachments;
    ParseCommandLine(++argv, &sender, &reply_to, &recipients, &cc_recipients, &bcc_recipients, &subject, &message_body,
                     &priority_as_string, &format_as_string, &expand_newline_escapes, &attachments);

    if (sender.empty() and reply_to.empty()) {
        IniFile ini_file(UBTools::GetTuelibPath() + "cronjobs/smtp_server.conf");
        sender = ini_file.getString("SMTPServer", "server_user") + "@uni-tuebingen.de";
    }

    if (not priority_as_string.empty())
        priority = StringToPriority(priority_as_string);
    if (not format_as_string.empty())
        format = StringToFormat(format_as_string);

    if (expand_newline_escapes)
        message_body = ExpandNewlineEscapes(message_body);

    const unsigned short response_code(EmailSender::SendEmail(sender, SplitRecipients(recipients), SplitRecipients(cc_recipients),
                                                              SplitRecipients(bcc_recipients), subject, message_body, priority, format,
                                                              reply_to, /* use_ssl = */true, /* use_authentication = */true, attachments));
    if (response_code >= 300) {
        if (not MiscUtil::EnvironmentVariableExists("ENABLE_SMPT_CLIENT_PERFORM_LOGGING"))
            LOG_ERROR("failed to send your email, the response code was: " + std::to_string(response_code)
                      + " (You may want to set the ENABLE_SMPT_CLIENT_PERFORM_LOGGING to debug the problem.)");
        else
            LOG_ERROR("failed to send your email, the response code was: " + std::to_string(response_code));
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "scanner.h"

#include <cassert>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <string>

#include "pettable.h"

static int base = 10;

static bool is_integer(const char* s, int base) {
    if (*s == '-') {
        ++s;
        if (!*s) {
            return false;
        }
    }
    while (*s) {
        int n = *s;
        n -= '0';
        if (n > 9) {
            n += '0' - 'a' + 10;
        }
        if (n < 0 || n >= base) {
            return false;
        }
        ++s;
    }
    return true;
}

// Handles #nnnn.
static bool is_decimal_integer(const char* s) {
    if (*s != '#') {
        return false;
    }
    return is_integer(s + 1, 10);
}

// Handles $nnnn.
static bool is_hexadecimal_integer(const char* s) {
    if (*s != '$') {
        return false;
    }
    return is_integer(s + 1, 16);
}

static bool is_number(const char* s) {
    return is_decimal_integer(s) || is_hexadecimal_integer(s) || is_integer(s, base);
}

static int parse_number(const char* s, int base) {
    bool negate = false;
    if (*s == '-') {
        negate = true;
        ++s;
    }
    int i = 0;
    while (*s) {
        i *= base;
        char c = *s;
        if (c < 'a') {
            c -= '0';
        } else {
            c -= 'a';
            c += 10;
        }
        i += c;
        ++s;
    }
    return negate ? -i : i;
}

static int parse_number(const char* s) {
    if (*s == '$') {
        ++s;
        return parse_number(s, 16);
    }
    if (*s == '#') {
        ++s;
        return parse_number(s, 10);
    }
    return parse_number(s, base);
}

static void consumeWord(const char*& s) {
    while (*s && !isspace(*s)) {
        ++s;
    }
    while (*s && isspace(*s)) {
        ++s;
    }
}

static std::string toLowerCase(const char* s) {
    std::string word;
    while (*s && !isspace(*s)) {
        char c = *s;
        if (c >= 'A' && c <= 'Z') {
            c += 'a' - 'A';
        }
        word += c;
        ++s;
    }
    return word;
}

static TokenType getSimpleToken(const std::string& wordName) {
    struct SimpleScannedWord {
        const char* name;
        TokenType tokenType;
    };
    static const SimpleScannedWord simpleScannedWords[] = {
        { ":", Colon },
        { ";", SemiColon },
        { "if", If },
        { "then", Then },
        { "variable", Variable },
        { "allot", Allot },
        { "cells", Cells },
        { "create", Create },
        { "else", Else },
        { "!", Store },
        { "begin", Begin },
        { "again", Again },
        { "value", Value },
        { "do", Do },
        { "drop", Drop },
        { "i", I },
        { "leave", Leave },
        { "loop", Loop },
        { "repeat", Repeat },
        { "while", While },
        { "constant", Constant },
        { "here", Here },
        { ",", Comma },
        { "c,", CComma },
        { "chars", Nop },
        { "align", Nop },
        { "aligned", Nop },
        { nullptr, None }
    };
    const SimpleScannedWord* it = simpleScannedWords;
    while (it->name) {
        if (wordName == it->name) {
            return it->tokenType;
        }
        ++it;
    }
    return None;
}

static Token token(const char*& s) {
    while (isspace(*s)) {
        ++s;
    }
    const std::string wordName = toLowerCase(s);

    {
        const TokenType tokenType = getSimpleToken(wordName);
        if (tokenType != None) {
            consumeWord(s);
            return Token(tokenType);
        }
    }

    if (wordName == "\\") {  // Comment.
        while (*s != '\n') {
            ++s;
        }
        ++s;
        return token(s);
    } else if (wordName == "(") {  // Comment.
        while (!isspace(s[0]) || s[1] != ')' || !isspace(s[2])) {
            ++s;
        }
        s += 3;
        return token(s);
    } else if (wordName == "hex") {
        consumeWord(s);
        base = 16;
        return token(s);
    } else if (wordName == "s\"") {
        s += strlen("s\" ");
        while (isspace(*s)) {
            ++s;
        }
        std::string stringData;
        while (*s != '"') {
            stringData.push_back(*s);
            ++s;
        }
        ++s;
        Token t(String);
        t.stringData = (char*)malloc(stringData.size() + 1);
        strcpy(t.stringData, stringData.c_str());
        return t;
    } else if (wordName == ":code") {
        s += strlen(":code ");
        while (isspace(*s)) {
            ++s;
        }
        std::string code;
        while (memcmp(";code", s, strlen(";code"))) {
            code.push_back(*s);
            ++s;
        }
        s += strlen(";code");
        while (isspace(*s)) {
            ++s;
        }
        Token t(Code);
        t.stringData = (char*)malloc(code.size() + 1);
        strcpy(t.stringData, code.c_str());
        return t;
    } else if (is_number(wordName.c_str())) {
        consumeWord(s);
        Token t(Number);
        t.intData = parse_number(wordName.c_str());
        return t;
    } else if (wordName == "char" || wordName == "[char]") {
		consumeWord(s);
		Token t(Number);
		t.intData = ascToPetTable[(unsigned char)*s];
		consumeWord(s);
		return t;
	}

    Token t(WordName);
    t.stringData = (char*)malloc(wordName.length() + 1);
    assert(t.stringData);
    strcpy(t.stringData, wordName.c_str());
    consumeWord(s);
    return t;
}

Tokens scan(const char* s) {
    assert(s);
    Tokens tokens;
    while (*s) {
        tokens.push_back(token(s));
    }
    return tokens;
}
<commit_msg>tidy up code words (no trailing whitespace in assembly)<commit_after>#include "scanner.h"

#include <cassert>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <string>

#include "pettable.h"

static int base = 10;

static bool is_integer(const char* s, int base) {
    if (*s == '-') {
        ++s;
        if (!*s) {
            return false;
        }
    }
    while (*s) {
        int n = *s;
        n -= '0';
        if (n > 9) {
            n += '0' - 'a' + 10;
        }
        if (n < 0 || n >= base) {
            return false;
        }
        ++s;
    }
    return true;
}

// Handles #nnnn.
static bool is_decimal_integer(const char* s) {
    if (*s != '#') {
        return false;
    }
    return is_integer(s + 1, 10);
}

// Handles $nnnn.
static bool is_hexadecimal_integer(const char* s) {
    if (*s != '$') {
        return false;
    }
    return is_integer(s + 1, 16);
}

static bool is_number(const char* s) {
    return is_decimal_integer(s) || is_hexadecimal_integer(s) || is_integer(s, base);
}

static int parse_number(const char* s, int base) {
    bool negate = false;
    if (*s == '-') {
        negate = true;
        ++s;
    }
    int i = 0;
    while (*s) {
        i *= base;
        char c = *s;
        if (c < 'a') {
            c -= '0';
        } else {
            c -= 'a';
            c += 10;
        }
        i += c;
        ++s;
    }
    return negate ? -i : i;
}

static int parse_number(const char* s) {
    if (*s == '$') {
        ++s;
        return parse_number(s, 16);
    }
    if (*s == '#') {
        ++s;
        return parse_number(s, 10);
    }
    return parse_number(s, base);
}

static void consumeWord(const char*& s) {
    while (*s && !isspace(*s)) {
        ++s;
    }
    while (*s && isspace(*s)) {
        ++s;
    }
}

static std::string toLowerCase(const char* s) {
    std::string word;
    while (*s && !isspace(*s)) {
        char c = *s;
        if (c >= 'A' && c <= 'Z') {
            c += 'a' - 'A';
        }
        word += c;
        ++s;
    }
    return word;
}

static TokenType getSimpleToken(const std::string& wordName) {
    struct SimpleScannedWord {
        const char* name;
        TokenType tokenType;
    };
    static const SimpleScannedWord simpleScannedWords[] = {
        { ":", Colon },
        { ";", SemiColon },
        { "if", If },
        { "then", Then },
        { "variable", Variable },
        { "allot", Allot },
        { "cells", Cells },
        { "create", Create },
        { "else", Else },
        { "!", Store },
        { "begin", Begin },
        { "again", Again },
        { "value", Value },
        { "do", Do },
        { "drop", Drop },
        { "i", I },
        { "leave", Leave },
        { "loop", Loop },
        { "repeat", Repeat },
        { "while", While },
        { "constant", Constant },
        { "here", Here },
        { ",", Comma },
        { "c,", CComma },
        { "chars", Nop },
        { "align", Nop },
        { "aligned", Nop },
        { nullptr, None }
    };
    const SimpleScannedWord* it = simpleScannedWords;
    while (it->name) {
        if (wordName == it->name) {
            return it->tokenType;
        }
        ++it;
    }
    return None;
}

static Token token(const char*& s) {
    while (isspace(*s)) {
        ++s;
    }
    const std::string wordName = toLowerCase(s);

    {
        const TokenType tokenType = getSimpleToken(wordName);
        if (tokenType != None) {
            consumeWord(s);
            return Token(tokenType);
        }
    }

    if (wordName == "\\") {  // Comment.
        while (*s != '\n') {
            ++s;
        }
        ++s;
        return token(s);
    } else if (wordName == "(") {  // Comment.
        while (!isspace(s[0]) || s[1] != ')' || !isspace(s[2])) {
            ++s;
        }
        s += 3;
        return token(s);
    } else if (wordName == "hex") {
        consumeWord(s);
        base = 16;
        return token(s);
    } else if (wordName == "s\"") {
        s += strlen("s\" ");
        while (isspace(*s)) {
            ++s;
        }
        std::string stringData;
        while (*s != '"') {
            stringData.push_back(*s);
            ++s;
        }
        ++s;
        Token t(String);
        t.stringData = (char*)malloc(stringData.size() + 1);
        strcpy(t.stringData, stringData.c_str());
        return t;
    } else if (wordName == ":code") {
        s += strlen(":code ");
        while (isspace(*s)) {
            ++s;
        }
        std::string code;
        while (!isspace(*s) || memcmp(";code", s + 1, strlen(";code"))) {
            code.push_back(*s);
            ++s;
        }
        s += strlen(" ;code");
        while (isspace(*s)) {
            ++s;
        }
        Token t(Code);
        t.stringData = (char*)malloc(code.size() + 1);
        strcpy(t.stringData, code.c_str());
        return t;
    } else if (is_number(wordName.c_str())) {
        consumeWord(s);
        Token t(Number);
        t.intData = parse_number(wordName.c_str());
        return t;
    } else if (wordName == "char" || wordName == "[char]") {
		consumeWord(s);
		Token t(Number);
		t.intData = ascToPetTable[(unsigned char)*s];
		consumeWord(s);
		return t;
	}

    Token t(WordName);
    t.stringData = (char*)malloc(wordName.length() + 1);
    assert(t.stringData);
    strcpy(t.stringData, wordName.c_str());
    consumeWord(s);
    return t;
}

Tokens scan(const char* s) {
    assert(s);
    Tokens tokens;
    while (*s) {
        tokens.push_back(token(s));
    }
    return tokens;
}
<|endoftext|>