<commit_before>//
// $Id$
//

#include "FFMpegDecoder.h"

#include "IDisplayEngine.h"
#include "Player.h"
#include "../base/Exception.h"
#include "../base/Logger.h"

#include <iostream>
#include <sstream>
#include <unistd.h>

using namespace std;

namespace avg {

bool FFMpegDecoder::m_bInitialized = false;

FFMpegDecoder::FFMpegDecoder ()
    : m_pFormatContext(0),
      m_pVStream(0),
      m_pPacketData(0)
{
    initVideoSupport();
}

FFMpegDecoder::~FFMpegDecoder ()
{
    if (m_pFormatContext) {
        close();
    }
}

void avcodecError(const string & filename, int err)
{
    switch(err) {
        case AVERROR_NUMEXPECTED:
            AVG_TRACE(Logger::ERROR,
                    filename << ": Incorrect image filename syntax.");
            AVG_TRACE(Logger::ERROR,
                    "Use '%%d' to specify the image number:");
            AVG_TRACE(Logger::ERROR,
                    "  for img1.jpg, img2.jpg, ..., use 'img%%d.jpg';");
            AVG_TRACE(Logger::ERROR,
                    "  for img001.jpg, img002.jpg, ..., use 'img%%03d.jpg'.");
            break;
        case AVERROR_INVALIDDATA:
            AVG_TRACE(Logger::ERROR,
                    filename << ": Error while parsing header");
            break;
        case AVERROR_NOFMT:
            AVG_TRACE(Logger::ERROR,
                    filename << ": Unknown format");
            break;
        default:
            AVG_TRACE(Logger::ERROR,
                    filename << ": Error while opening file (Num:" << err << ")");
            break;
    }
    // TODO: Continue without video.
    exit(-1);
}

void dump_stream_info(AVFormatContext *s)
{
    cerr << "Stream info: " << endl;
    if (s->track != 0)
        fprintf(stderr, "  Track: %d\n", s->track);
    if (s->title[0] != '\0')
        fprintf(stderr, "  Title: %s\n", s->title);
    if (s->author[0] != '\0')
        fprintf(stderr, "  Author: %s\n", s->author);
    if (s->album[0] != '\0')
        fprintf(stderr, "  Album: %s\n", s->album);
    if (s->year != 0)
        fprintf(stderr, "  Year: %d\n", s->year);
    if (s->genre[0] != '\0')
        fprintf(stderr, "  Genre: %s\n", s->genre);
}

bool FFMpegDecoder::open (const std::string& sFilename,
        int* pWidth, int* pHeight)
{
    AVFormatParameters params;
    int err;
    m_sFilename = sFilename;

    AVG_TRACE(Logger::PROFILE, "Opening " << sFilename);
    memset(&params, 0, sizeof(params));
    params.image_format = 0;

    err = av_open_input_file(&m_pFormatContext, sFilename.c_str(),
            0, 0, &params);
    if (err < 0) {
        avcodecError(sFilename, err);
    }

    err = av_find_stream_info(m_pFormatContext);
    if (err < 0) {
        AVG_TRACE(Logger::ERROR,
                    sFilename << ": Could not find codec parameters.");
        return false;
    }

    av_read_play(m_pFormatContext);

    m_VStreamIndex = -1;
    for(int i = 0; i < m_pFormatContext->nb_streams; i++) {
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
        AVCodecContext *enc = &m_pFormatContext->streams[i]->codec;
#else
        AVCodecContext *enc = m_pFormatContext->streams[i]->codec;
#endif
        switch(enc->codec_type) {
/*
           case CODEC_TYPE_AUDIO:
               if (audio_index < 0 && !audio_disable)
               audio_index = i;
               break;
*/
            case CODEC_TYPE_VIDEO:
                if (m_VStreamIndex < 0)
                    m_VStreamIndex = i;
                break;
            default:
                break;
        }
    }
//    dump_format(m_pFormatContext, 0, m_sFilename.c_str(), 0);
//    dump_stream_info(m_pFormatContext);
    if (m_VStreamIndex < 0) {
        AVG_TRACE(Logger::ERROR,
                    sFilename << " does not contain any video streams.");
        return false;
    }
    AVCodecContext *enc;
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
    enc = &(m_pFormatContext->streams[m_VStreamIndex]->codec);
#else
    enc = m_pFormatContext->streams[m_VStreamIndex]->codec;
#endif
//    enc->debug = 0x0001; // see avcodec.h

    AVCodec * codec = avcodec_find_decoder(enc->codec_id);
    if (!codec ||
        avcodec_open(enc, codec) < 0)
    {
        AVG_TRACE(Logger::ERROR,
                    sFilename << ": could not open codec (?!).");
        return false;
    }
    m_pVStream = m_pFormatContext->streams[m_VStreamIndex];
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
    *pWidth =  m_pVStream->codec.width;
    *pHeight = m_pVStream->codec.height;
#else
    *pWidth =  m_pVStream->codec->width;
    *pHeight = m_pVStream->codec->height;
#endif
    m_bFirstPacket = true;
    m_PacketLenLeft = 0;
    m_bEOF = false;
    return true;
}

void FFMpegDecoder::close()
{
    AVG_TRACE(Logger::PROFILE, "Closing " << m_sFilename);
    AVCodecContext * enc;
    enc = &(m_pFormatContext->streams[m_VStreamIndex]->codec);
    if (!m_bFirstPacket) {
        av_free_packet(&m_Packet);
    }
    m_pPacketData = 0;
    avcodec_close(enc);
    m_pVStream = 0;
    av_close_input_file(m_pFormatContext);
    m_pFormatContext = 0;
}

void FFMpegDecoder::seek(int DestFrame, int CurFrame)
{
#if LIBAVFORMAT_BUILD <= 4616
    av_seek_frame(m_pFormatContext, m_VStreamIndex,
            int((double(DestFrame)*1000000*1000)/m_pVStream->r_frame_rate));
#else
    av_seek_frame(m_pFormatContext, m_VStreamIndex,
            int((double(DestFrame)*1000000*1000)/m_pVStream->r_frame_rate), 0);
#endif
}

int FFMpegDecoder::getNumFrames()
{
    // This is broken for some videos, but the code here is correct.
    // So fix the videos or ffmpeg :-).
    return m_pVStream->r_frame_rate*(m_pVStream->duration/AV_TIME_BASE);
}

double FFMpegDecoder::getFPS()
{
    return m_pVStream->r_frame_rate;
}

bool FFMpegDecoder::renderToBmp(BitmapPtr pBmp)
{
/* Speedup possibilities:
    fast YUV->RGB conversion? incl. scaling?
    draw_horiz_band?
*/
    AVFrame Frame;
    readFrame(Frame);
    if (!m_bEOF) {
        AVPicture DestPict;
        int x1 = 0;
        int y1 = 0;
        unsigned char * pDestBits = pBmp->getPixels()+pBmp->getStride()*y1+3*x1;
        DestPict.data[0] = pDestBits;
        DestPict.data[1] = pDestBits+1;
        DestPict.data[2] = pDestBits+2;
        DestPict.linesize[0] = pBmp->getStride();
        DestPict.linesize[1] = pBmp->getStride();
        DestPict.linesize[2] = pBmp->getStride();
        int DestFmt;
        switch(pBmp->getPixelFormat()) {
            case R8G8B8:
                DestFmt = PIX_FMT_RGB24;
                break;
            case B8G8R8:
                DestFmt = PIX_FMT_BGR24;
                break;
            default:
                assert(false);
        }
        img_convert(&DestPict, DestFmt,
                (AVPicture*)&Frame, m_pVStream->codec.pix_fmt,
                m_pVStream->codec.width, m_pVStream->codec.height);
    }
    return m_bEOF;
}

bool FFMpegDecoder::canRenderToBuffer(int BPP)
{
//TODO: This is a bug: We should enable direct rendering if DFB is being
//      used and not just compiled in!
#ifdef AVG_ENABLE_DFB
    return (BPP == 24);
#else
    return false;
#endif
}

void FFMpegDecoder::initVideoSupport()
{
    if (!m_bInitialized) {
        av_register_all();
        m_bInitialized = true;
        // Avoid libavcodec console spam - turn this up again when libavcodec
        // doesn't spam anymore :-).
        av_log_set_level(AV_LOG_QUIET);
    }
}

void FFMpegDecoder::readFrame(AVFrame& Frame)
{
    if (m_pVStream->codec.codec_id == CODEC_ID_RAWVIDEO) {
        AVPacket Packet;
        m_bEOF = getNextVideoPacket(Packet);
        if (m_bEOF) {
            return ;
        }
        avpicture_fill((AVPicture*)&Frame, Packet.data,
                m_pVStream->codec.pix_fmt,
                m_pVStream->codec.width, m_pVStream->codec.height);
    } else {
        int gotPicture = 0;
        while (!gotPicture) {
            if (m_PacketLenLeft <= 0) {
                if (!m_bFirstPacket) {
                    av_free_packet(&m_Packet);
                }
                m_bFirstPacket = false;
                m_bEOF = getNextVideoPacket(m_Packet);
                if (m_bEOF) {
                    return ;
                }
                m_PacketLenLeft = m_Packet.size;
                m_pPacketData = m_Packet.data;
            }
            int Len1 = avcodec_decode_video(&m_pVStream->codec, &Frame,
                    &gotPicture, m_pPacketData, m_PacketLenLeft);
            if (Len1 < 0) {
                AVG_TRACE(Logger::WARNING, "Error decoding " <<
                        m_sFilename);
                // TODO: simulate eof.
            }
            m_pPacketData += Len1;
            m_PacketLenLeft -= Len1;
        }
/*
        cerr << "coded_picture_number: " << Frame.coded_picture_number <<
                ", display_picture_number: " << Frame.display_picture_number <<
                ", pts: " << Frame.pts << endl;

        cerr << "key_frame: " << Frame.key_frame <<
               ", pict_type: " << Frame.pict_type << endl;
        AVFrac spts = m_pVStream->pts;
        cerr << "Stream.pts: " << spts.val + double(spts.num)/spts.den << endl;
*/
    }
}

bool FFMpegDecoder::getNextVideoPacket(AVPacket & Packet) {
    AVPacket CurPacket;
    int err = av_read_frame(m_pFormatContext, &CurPacket);
    if (err < 0) {
        return true;
    }
    while (CurPacket.stream_index != m_VStreamIndex) {
        av_free_packet(&CurPacket);
        int err = av_read_frame(m_pFormatContext, &CurPacket);
        if (err < 0) {
            return true;
        }
    }
    Packet = CurPacket;
/*    if (Packet.pts != AV_NOPTS_VALUE) {
        cerr << "Packet.pts: " <<
            double(Packet.pts)*m_pFormatContext->pts_num/m_pFormatContext->pts_den << endl;
    }
*/
    return false;
}

}

<commit_msg>more libavcodec compatibility<commit_after>//
// $Id$
//

#include "FFMpegDecoder.h"

#include "IDisplayEngine.h"
#include "Player.h"
#include "../base/Exception.h"
#include "../base/Logger.h"

#include <iostream>
#include <sstream>
#include <unistd.h>

using namespace std;

namespace avg {

bool FFMpegDecoder::m_bInitialized = false;

FFMpegDecoder::FFMpegDecoder ()
    : m_pFormatContext(0),
      m_pVStream(0),
      m_pPacketData(0)
{
    initVideoSupport();
}

FFMpegDecoder::~FFMpegDecoder ()
{
    if (m_pFormatContext) {
        close();
    }
}

void avcodecError(const string & filename, int err)
{
    switch(err) {
        case AVERROR_NUMEXPECTED:
            AVG_TRACE(Logger::ERROR,
                    filename << ": Incorrect image filename syntax.");
            AVG_TRACE(Logger::ERROR,
                    "Use '%%d' to specify the image number:");
            AVG_TRACE(Logger::ERROR,
                    "  for img1.jpg, img2.jpg, ..., use 'img%%d.jpg';");
            AVG_TRACE(Logger::ERROR,
                    "  for img001.jpg, img002.jpg, ..., use 'img%%03d.jpg'.");
            break;
        case AVERROR_INVALIDDATA:
            AVG_TRACE(Logger::ERROR,
                    filename << ": Error while parsing header");
            break;
        case AVERROR_NOFMT:
            AVG_TRACE(Logger::ERROR,
                    filename << ": Unknown format");
            break;
        default:
            AVG_TRACE(Logger::ERROR,
                    filename << ": Error while opening file (Num:" << err << ")");
            break;
    }
    // TODO: Continue without video.
    exit(-1);
}

void dump_stream_info(AVFormatContext *s)
{
    cerr << "Stream info: " << endl;
    if (s->track != 0)
        fprintf(stderr, "  Track: %d\n", s->track);
    if (s->title[0] != '\0')
        fprintf(stderr, "  Title: %s\n", s->title);
    if (s->author[0] != '\0')
        fprintf(stderr, "  Author: %s\n", s->author);
    if (s->album[0] != '\0')
        fprintf(stderr, "  Album: %s\n", s->album);
    if (s->year != 0)
        fprintf(stderr, "  Year: %d\n", s->year);
    if (s->genre[0] != '\0')
        fprintf(stderr, "  Genre: %s\n", s->genre);
}

bool FFMpegDecoder::open (const std::string& sFilename,
        int* pWidth, int* pHeight)
{
    AVFormatParameters params;
    int err;
    m_sFilename = sFilename;

    AVG_TRACE(Logger::PROFILE, "Opening " << sFilename);
    memset(&params, 0, sizeof(params));
    params.image_format = 0;

    err = av_open_input_file(&m_pFormatContext, sFilename.c_str(),
            0, 0, &params);
    if (err < 0) {
        avcodecError(sFilename, err);
    }

    err = av_find_stream_info(m_pFormatContext);
    if (err < 0) {
        AVG_TRACE(Logger::ERROR,
                    sFilename << ": Could not find codec parameters.");
        return false;
    }

    av_read_play(m_pFormatContext);

    m_VStreamIndex = -1;
    for(int i = 0; i < m_pFormatContext->nb_streams; i++) {
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
        AVCodecContext *enc = &m_pFormatContext->streams[i]->codec;
#else
        AVCodecContext *enc = m_pFormatContext->streams[i]->codec;
#endif
        switch(enc->codec_type) {
/*
           case CODEC_TYPE_AUDIO:
               if (audio_index < 0 && !audio_disable)
               audio_index = i;
               break;
*/
            case CODEC_TYPE_VIDEO:
                if (m_VStreamIndex < 0)
                    m_VStreamIndex = i;
                break;
            default:
                break;
        }
    }
//    dump_format(m_pFormatContext, 0, m_sFilename.c_str(), 0);
//    dump_stream_info(m_pFormatContext);
    if (m_VStreamIndex < 0) {
        AVG_TRACE(Logger::ERROR,
                    sFilename << " does not contain any video streams.");
        return false;
    }
    AVCodecContext *enc;
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
    enc = &(m_pFormatContext->streams[m_VStreamIndex]->codec);
#else
    enc = m_pFormatContext->streams[m_VStreamIndex]->codec;
#endif
//    enc->debug = 0x0001; // see avcodec.h

    AVCodec * codec = avcodec_find_decoder(enc->codec_id);
    if (!codec ||
        avcodec_open(enc, codec) < 0)
    {
        AVG_TRACE(Logger::ERROR,
                    sFilename << ": could not open codec (?!).");
        return false;
    }
    m_pVStream = m_pFormatContext->streams[m_VStreamIndex];
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
    *pWidth =  m_pVStream->codec.width;
    *pHeight = m_pVStream->codec.height;
#else
    *pWidth =  m_pVStream->codec->width;
    *pHeight = m_pVStream->codec->height;
#endif
    m_bFirstPacket = true;
    m_PacketLenLeft = 0;
    m_bEOF = false;
    return true;
}

void FFMpegDecoder::close()
{
    AVG_TRACE(Logger::PROFILE, "Closing " << m_sFilename);
    AVCodecContext * enc;
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
    enc = &(m_pFormatContext->streams[m_VStreamIndex]->codec);
#else
    enc = m_pFormatContext->streams[m_VStreamIndex]->codec;
#endif
    if (!m_bFirstPacket) {
        av_free_packet(&m_Packet);
    }
    m_pPacketData = 0;
    avcodec_close(enc);
    m_pVStream = 0;
    av_close_input_file(m_pFormatContext);
    m_pFormatContext = 0;
}

void FFMpegDecoder::seek(int DestFrame, int CurFrame)
{
#if LIBAVFORMAT_BUILD <= 4616
    av_seek_frame(m_pFormatContext, m_VStreamIndex,
            int((double(DestFrame)*1000000*1000)/m_pVStream->r_frame_rate));
#else
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
    av_seek_frame(m_pFormatContext, m_VStreamIndex,
            int((double(DestFrame)*1000000*1000)/m_pVStream->r_frame_rate), 0);
#else
    double framerate = (m_pVStream->r_frame_rate.num)/m_pVStream->r_frame_rate.den;
    av_seek_frame(m_pFormatContext, m_VStreamIndex,
            int((double(DestFrame)*1000000*1000)/framerate), 0);
#endif
#endif
}

int FFMpegDecoder::getNumFrames()
{
    // This is broken for some videos, but the code here is correct.
    // So fix the videos or ffmpeg :-).
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
    return m_pVStream->r_frame_rate*(m_pVStream->duration/AV_TIME_BASE);
#else
    return (m_pVStream->r_frame_rate.num/m_pVStream->r_frame_rate.den)*(m_pVStream->duration/AV_TIME_BASE);
#endif
}

double FFMpegDecoder::getFPS()
{
#if LIBAVFORMAT_BUILD < ((49<<16)+(0<<8)+0)
    return m_pVStream->r_frame_rate;
#else
    return (m_pVStream->r_frame_rate.num/m_pVStream->r_frame_rate.den);
#endif
}

bool FFMpegDecoder::renderToBmp(BitmapPtr pBmp)
{
/* Speedup possibilities:
    fast YUV->RGB conversion? incl. scaling?
    draw_horiz_band?
*/
    AVFrame Frame;
    readFrame(Frame);
    if (!m_bEOF) {
        AVPicture DestPict;
        int x1 = 0;
        int y1 = 0;
        unsigned char * pDestBits = pBmp->getPixels()+pBmp->getStride()*y1+3*x1;
        DestPict.data[0] = pDestBits;
        DestPict.data[1] = pDestBits+1;
        DestPict.data[2] = pDestBits+2;
        DestPict.linesize[0] = pBmp->getStride();
        DestPict.linesize[1] = pBmp->getStride();
        DestPict.linesize[2] = pBmp->getStride();
        int DestFmt;
        switch(pBmp->getPixelFormat()) {
            case R8G8B8:
                DestFmt = PIX_FMT_RGB24;
                break;
            case B8G8R8:
                DestFmt = PIX_FMT_BGR24;
                break;
            default:
                assert(false);
        }
        img_convert(&DestPict, DestFmt,
                (AVPicture*)&Frame, m_pVStream->codec.pix_fmt,
                m_pVStream->codec.width, m_pVStream->codec.height);
    }
    return m_bEOF;
}

bool FFMpegDecoder::canRenderToBuffer(int BPP)
{
//TODO: This is a bug: We should enable direct rendering if DFB is being
//      used and not just compiled in!
#ifdef AVG_ENABLE_DFB
    return (BPP == 24);
#else
    return false;
#endif
}

void FFMpegDecoder::initVideoSupport()
{
    if (!m_bInitialized) {
        av_register_all();
        m_bInitialized = true;
        // Avoid libavcodec console spam - turn this up again when libavcodec
        // doesn't spam anymore :-).
        av_log_set_level(AV_LOG_QUIET);
    }
}

void FFMpegDecoder::readFrame(AVFrame& Frame)
{
    if (m_pVStream->codec.codec_id == CODEC_ID_RAWVIDEO) {
        AVPacket Packet;
        m_bEOF = getNextVideoPacket(Packet);
        if (m_bEOF) {
            return ;
        }
        avpicture_fill((AVPicture*)&Frame, Packet.data,
                m_pVStream->codec.pix_fmt,
                m_pVStream->codec.width, m_pVStream->codec.height);
    } else {
        int gotPicture = 0;
        while (!gotPicture) {
            if (m_PacketLenLeft <= 0) {
                if (!m_bFirstPacket) {
                    av_free_packet(&m_Packet);
                }
                m_bFirstPacket = false;
                m_bEOF = getNextVideoPacket(m_Packet);
                if (m_bEOF) {
                    return ;
                }
                m_PacketLenLeft = m_Packet.size;
                m_pPacketData = m_Packet.data;
            }
            int Len1 = avcodec_decode_video(&m_pVStream->codec, &Frame,
                    &gotPicture, m_pPacketData, m_PacketLenLeft);
            if (Len1 < 0) {
                AVG_TRACE(Logger::WARNING, "Error decoding " <<
                        m_sFilename);
                // TODO: simulate eof.
            }
            m_pPacketData += Len1;
            m_PacketLenLeft -= Len1;
        }
/*
        cerr << "coded_picture_number: " << Frame.coded_picture_number <<
                ", display_picture_number: " << Frame.display_picture_number <<
                ", pts: " << Frame.pts << endl;

        cerr << "key_frame: " << Frame.key_frame <<
               ", pict_type: " << Frame.pict_type << endl;
        AVFrac spts = m_pVStream->pts;
        cerr << "Stream.pts: " << spts.val + double(spts.num)/spts.den << endl;
*/
    }
}

bool FFMpegDecoder::getNextVideoPacket(AVPacket & Packet) {
    AVPacket CurPacket;
    int err = av_read_frame(m_pFormatContext, &CurPacket);
    if (err < 0) {
        return true;
    }
    while (CurPacket.stream_index != m_VStreamIndex) {
        av_free_packet(&CurPacket);
        int err = av_read_frame(m_pFormatContext, &CurPacket);
        if (err < 0) {
            return true;
        }
    }
    Packet = CurPacket;
/*    if (Packet.pts != AV_NOPTS_VALUE) {
        cerr << "Packet.pts: " <<
            double(Packet.pts)*m_pFormatContext->pts_num/m_pFormatContext->pts_den << endl;
    }
*/
    return false;
}

}

<|endoftext|>


<commit_before>/*
 * Qt4 bitcoin GUI.
 *
 * W.J. van der Laan 2011
 */
#include "bitcoingui.h"
#include "transactiontablemodel.h"
#include "addressbookdialog.h"
#include "sendcoinsdialog.h"
#include "optionsdialog.h"
#include "aboutdialog.h"

#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QIcon>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QWidget>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QTableView>
#include <QLineEdit>
#include <QPushButton>
#include <QHeaderView>
#include <QLocale>
#include <QSortFilterProxyModel>
#include <QClipboard>

#include <QDebug>

#include <iostream>

BitcoinGUI::BitcoinGUI(QWidget *parent):
    QMainWindow(parent), trayIcon(0)
{
    resize(850, 550);
    setWindowTitle(tr("Bitcoin"));
    setWindowIcon(QIcon(":icons/bitcoin"));

    createActions();

    /* Menus */
    QMenu *file = menuBar()->addMenu("&File");
    file->addAction(sendcoins);
    file->addSeparator();
    file->addAction(quit);

    QMenu *settings = menuBar()->addMenu("&Settings");
    settings->addAction(receiving_addresses);
    settings->addAction(options);

    QMenu *help = menuBar()->addMenu("&Help");
    help->addAction(about);

    /* Toolbar */
    QToolBar *toolbar = addToolBar("Main toolbar");
    toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    toolbar->addAction(sendcoins);
    toolbar->addAction(addressbook);

    /* Address: <address>: New... : Paste to clipboard */
    QHBoxLayout *hbox_address = new QHBoxLayout();
    hbox_address->addWidget(new QLabel(tr("Your Bitcoin Address:")));
    address = new QLineEdit();
    address->setReadOnly(true);
    hbox_address->addWidget(address);

    QPushButton *button_new = new QPushButton(tr("&New..."));
    QPushButton *button_clipboard = new QPushButton(tr("&Copy to clipboard"));
    hbox_address->addWidget(button_new);
    hbox_address->addWidget(button_clipboard);

    /* Balance: <balance> */
    QHBoxLayout *hbox_balance = new QHBoxLayout();
    hbox_balance->addWidget(new QLabel(tr("Balance:")));
    hbox_balance->addSpacing(5);/* Add some spacing between the label and the text */

    labelBalance = new QLabel();
    labelBalance->setFont(QFont("Teletype"));
    hbox_balance->addWidget(labelBalance);
    hbox_balance->addStretch(1);

    QVBoxLayout *vbox = new QVBoxLayout();
    vbox->addLayout(hbox_address);
    vbox->addLayout(hbox_balance);

    transaction_model = new TransactionTableModel(this);

    vbox->addWidget(createTabs());

    QWidget *centralwidget = new QWidget(this);
    centralwidget->setLayout(vbox);
    setCentralWidget(centralwidget);

    /* Create status bar */
    statusBar();

    labelConnections = new QLabel();
    labelConnections->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    labelConnections->setMinimumWidth(130);

    labelBlocks = new QLabel();
    labelBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    labelBlocks->setMinimumWidth(130);

    labelTransactions = new QLabel();
    labelTransactions->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    labelTransactions->setMinimumWidth(130);

    statusBar()->addPermanentWidget(labelConnections);
    statusBar()->addPermanentWidget(labelBlocks);
    statusBar()->addPermanentWidget(labelTransactions);

    /* Action bindings */
    connect(button_new, SIGNAL(clicked()), this, SLOT(newAddressClicked()));
    connect(button_clipboard, SIGNAL(clicked()), this, SLOT(copyClipboardClicked()));

    createTrayIcon();
}

void BitcoinGUI::createActions()
{
    quit = new QAction(QIcon(":/icons/quit"), tr("&Exit"), this);
    sendcoins = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
    addressbook = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this);
    about = new QAction(QIcon(":/icons/bitcoin"), tr("&About"), this);
    receiving_addresses = new QAction(QIcon(":/icons/receiving-addresses"), tr("Your &Receiving Addresses..."), this);
    options = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
    openBitCoin = new QAction(QIcon(":/icons/bitcoin"), "Open Bitcoin", this);

    connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));
    connect(sendcoins, SIGNAL(triggered()), this, SLOT(sendcoinsClicked()));
    connect(addressbook, SIGNAL(triggered()), this, SLOT(addressbookClicked()));
    connect(receiving_addresses, SIGNAL(triggered()), this, SLOT(receivingAddressesClicked()));
    connect(options, SIGNAL(triggered()), this, SLOT(optionsClicked()));
    connect(about, SIGNAL(triggered()), this, SLOT(aboutClicked()));
}

void BitcoinGUI::createTrayIcon()
{
    QMenu *trayIconMenu = new QMenu(this);
    trayIconMenu->addAction(openBitCoin);
    trayIconMenu->addAction(sendcoins);
    trayIconMenu->addAction(options);
    trayIconMenu->addSeparator();
    trayIconMenu->addAction(quit);

    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setContextMenu(trayIconMenu);
    trayIcon->setIcon(QIcon(":/icons/toolbar"));
    trayIcon->show();
}

QWidget *BitcoinGUI::createTabs()
{
    QStringList tab_filters, tab_labels;
    tab_filters << "^."
            << "^["+TransactionTableModel::Sent+TransactionTableModel::Received+"]"
            << "^["+TransactionTableModel::Sent+"]"
            << "^["+TransactionTableModel::Received+"]";
    tab_labels  << tr("All transactions")
                << tr("Sent/Received")
                << tr("Sent")
                << tr("Received");
    QTabWidget *tabs = new QTabWidget(this);

    for(int i = 0; i < tab_labels.size(); ++i)
    {
        QSortFilterProxyModel *proxy_model = new QSortFilterProxyModel(this);
        proxy_model->setSourceModel(transaction_model);
        proxy_model->setDynamicSortFilter(true);
        proxy_model->setFilterRole(Qt::UserRole);
        proxy_model->setFilterKeyColumn(TransactionTableModel::Type);
        proxy_model->setFilterRegExp(QRegExp(tab_filters.at(i)));

        QTableView *transaction_table = new QTableView(this);
        transaction_table->setModel(proxy_model);
        transaction_table->setSelectionBehavior(QAbstractItemView::SelectRows);
        transaction_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
        transaction_table->verticalHeader()->hide();

        transaction_table->horizontalHeader()->resizeSection(
                TransactionTableModel::Status, 112);
        transaction_table->horizontalHeader()->resizeSection(
                TransactionTableModel::Date, 112);
        transaction_table->horizontalHeader()->setResizeMode(
                TransactionTableModel::Description, QHeaderView::Stretch);
        transaction_table->horizontalHeader()->resizeSection(
                TransactionTableModel::Debit, 79);
        transaction_table->horizontalHeader()->resizeSection(
                TransactionTableModel::Credit, 79);
        transaction_table->setColumnHidden(TransactionTableModel::Type, true);

        tabs->addTab(transaction_table, tab_labels.at(i));
    }
    return tabs;
}

void BitcoinGUI::sendcoinsClicked()
{
    qDebug() << "Send coins clicked";
    SendCoinsDialog dlg;
    dlg.exec();
}

void BitcoinGUI::addressbookClicked()
{
    qDebug() << "Address book clicked";
    AddressBookDialog dlg;
    dlg.setTab(AddressBookDialog::SendingTab);
    /* if an address accepted, do a 'send' to specified address */
    if(dlg.exec())
    {
        SendCoinsDialog send(0, dlg.getReturnValue());
        send.exec();
    }
}

void BitcoinGUI::receivingAddressesClicked()
{
    qDebug() << "Receiving addresses clicked";
    AddressBookDialog dlg;
    dlg.setTab(AddressBookDialog::ReceivingTab);
    dlg.exec();
}

void BitcoinGUI::optionsClicked()
{
    qDebug() << "Options clicked";
    OptionsDialog dlg;
    dlg.exec();
}

void BitcoinGUI::aboutClicked()
{
    qDebug() << "About clicked";
    AboutDialog dlg;
    dlg.exec();
}

void BitcoinGUI::newAddressClicked()
{
    qDebug() << "New address clicked";
    /* TODO: generate new address */
}

void BitcoinGUI::copyClipboardClicked()
{
    qDebug() << "Copy to clipboard";
    /* Copy text in address to clipboard */
    QApplication::clipboard()->setText(address->text());
}

void BitcoinGUI::setBalance(double balance)
{
    labelBalance->setText(QLocale::system().toString(balance, 8));
}

void BitcoinGUI::setAddress(const QString &addr)
{
    address->setText(addr);
}

void BitcoinGUI::setNumConnections(int count)
{
    labelConnections->setText(QLocale::system().toString(count)+" "+tr("connections"));
}

void BitcoinGUI::setNumBlocks(int count)
{
    labelBlocks->setText(QLocale::system().toString(count)+" "+tr("blocks"));
}

void BitcoinGUI::setNumTransactions(int count)
{
    labelTransactions->setText(QLocale::system().toString(count)+" "+tr("transactions"));
}
<commit_msg>remove debug stuff for implemented methods<commit_after>/*
 * Qt4 bitcoin GUI.
 *
 * W.J. van der Laan 2011
 */
#include "bitcoingui.h"
#include "transactiontablemodel.h"
#include "addressbookdialog.h"
#include "sendcoinsdialog.h"
#include "optionsdialog.h"
#include "aboutdialog.h"

#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QIcon>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QWidget>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QTableView>
#include <QLineEdit>
#include <QPushButton>
#include <QHeaderView>
#include <QLocale>
#include <QSortFilterProxyModel>
#include <QClipboard>

#include <QDebug>

#include <iostream>

BitcoinGUI::BitcoinGUI(QWidget *parent):
    QMainWindow(parent), trayIcon(0)
{
    resize(850, 550);
    setWindowTitle(tr("Bitcoin"));
    setWindowIcon(QIcon(":icons/bitcoin"));

    createActions();

    /* Menus */
    QMenu *file = menuBar()->addMenu("&File");
    file->addAction(sendcoins);
    file->addSeparator();
    file->addAction(quit);

    QMenu *settings = menuBar()->addMenu("&Settings");
    settings->addAction(receiving_addresses);
    settings->addAction(options);

    QMenu *help = menuBar()->addMenu("&Help");
    help->addAction(about);

    /* Toolbar */
    QToolBar *toolbar = addToolBar("Main toolbar");
    toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    toolbar->addAction(sendcoins);
    toolbar->addAction(addressbook);

    /* Address: <address>: New... : Paste to clipboard */
    QHBoxLayout *hbox_address = new QHBoxLayout();
    hbox_address->addWidget(new QLabel(tr("Your Bitcoin Address:")));
    address = new QLineEdit();
    address->setReadOnly(true);
    hbox_address->addWidget(address);

    QPushButton *button_new = new QPushButton(tr("&New..."));
    QPushButton *button_clipboard = new QPushButton(tr("&Copy to clipboard"));
    hbox_address->addWidget(button_new);
    hbox_address->addWidget(button_clipboard);

    /* Balance: <balance> */
    QHBoxLayout *hbox_balance = new QHBoxLayout();
    hbox_balance->addWidget(new QLabel(tr("Balance:")));
    hbox_balance->addSpacing(5);/* Add some spacing between the label and the text */

    labelBalance = new QLabel();
    labelBalance->setFont(QFont("Teletype"));
    hbox_balance->addWidget(labelBalance);
    hbox_balance->addStretch(1);

    QVBoxLayout *vbox = new QVBoxLayout();
    vbox->addLayout(hbox_address);
    vbox->addLayout(hbox_balance);

    transaction_model = new TransactionTableModel(this);

    vbox->addWidget(createTabs());

    QWidget *centralwidget = new QWidget(this);
    centralwidget->setLayout(vbox);
    setCentralWidget(centralwidget);

    /* Create status bar */
    statusBar();

    labelConnections = new QLabel();
    labelConnections->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    labelConnections->setMinimumWidth(130);

    labelBlocks = new QLabel();
    labelBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    labelBlocks->setMinimumWidth(130);

    labelTransactions = new QLabel();
    labelTransactions->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    labelTransactions->setMinimumWidth(130);

    statusBar()->addPermanentWidget(labelConnections);
    statusBar()->addPermanentWidget(labelBlocks);
    statusBar()->addPermanentWidget(labelTransactions);

    /* Action bindings */
    connect(button_new, SIGNAL(clicked()), this, SLOT(newAddressClicked()));
    connect(button_clipboard, SIGNAL(clicked()), this, SLOT(copyClipboardClicked()));

    createTrayIcon();
}

void BitcoinGUI::createActions()
{
    quit = new QAction(QIcon(":/icons/quit"), tr("&Exit"), this);
    sendcoins = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
    addressbook = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this);
    about = new QAction(QIcon(":/icons/bitcoin"), tr("&About"), this);
    receiving_addresses = new QAction(QIcon(":/icons/receiving-addresses"), tr("Your &Receiving Addresses..."), this);
    options = new QAction(QIcon(":/icons/options"), tr("&Options..."), this);
    openBitCoin = new QAction(QIcon(":/icons/bitcoin"), "Open Bitcoin", this);

    connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));
    connect(sendcoins, SIGNAL(triggered()), this, SLOT(sendcoinsClicked()));
    connect(addressbook, SIGNAL(triggered()), this, SLOT(addressbookClicked()));
    connect(receiving_addresses, SIGNAL(triggered()), this, SLOT(receivingAddressesClicked()));
    connect(options, SIGNAL(triggered()), this, SLOT(optionsClicked()));
    connect(about, SIGNAL(triggered()), this, SLOT(aboutClicked()));
}

void BitcoinGUI::createTrayIcon()
{
    QMenu *trayIconMenu = new QMenu(this);
    trayIconMenu->addAction(openBitCoin);
    trayIconMenu->addAction(sendcoins);
    trayIconMenu->addAction(options);
    trayIconMenu->addSeparator();
    trayIconMenu->addAction(quit);

    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setContextMenu(trayIconMenu);
    trayIcon->setIcon(QIcon(":/icons/toolbar"));
    trayIcon->show();
}

QWidget *BitcoinGUI::createTabs()
{
    QStringList tab_filters, tab_labels;
    tab_filters << "^."
            << "^["+TransactionTableModel::Sent+TransactionTableModel::Received+"]"
            << "^["+TransactionTableModel::Sent+"]"
            << "^["+TransactionTableModel::Received+"]";
    tab_labels  << tr("All transactions")
                << tr("Sent/Received")
                << tr("Sent")
                << tr("Received");
    QTabWidget *tabs = new QTabWidget(this);

    for(int i = 0; i < tab_labels.size(); ++i)
    {
        QSortFilterProxyModel *proxy_model = new QSortFilterProxyModel(this);
        proxy_model->setSourceModel(transaction_model);
        proxy_model->setDynamicSortFilter(true);
        proxy_model->setFilterRole(Qt::UserRole);
        proxy_model->setFilterKeyColumn(TransactionTableModel::Type);
        proxy_model->setFilterRegExp(QRegExp(tab_filters.at(i)));

        QTableView *transaction_table = new QTableView(this);
        transaction_table->setModel(proxy_model);
        transaction_table->setSelectionBehavior(QAbstractItemView::SelectRows);
        transaction_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
        transaction_table->verticalHeader()->hide();

        transaction_table->horizontalHeader()->resizeSection(
                TransactionTableModel::Status, 112);
        transaction_table->horizontalHeader()->resizeSection(
                TransactionTableModel::Date, 112);
        transaction_table->horizontalHeader()->setResizeMode(
                TransactionTableModel::Description, QHeaderView::Stretch);
        transaction_table->horizontalHeader()->resizeSection(
                TransactionTableModel::Debit, 79);
        transaction_table->horizontalHeader()->resizeSection(
                TransactionTableModel::Credit, 79);
        transaction_table->setColumnHidden(TransactionTableModel::Type, true);

        tabs->addTab(transaction_table, tab_labels.at(i));
    }
    return tabs;
}

void BitcoinGUI::sendcoinsClicked()
{
    SendCoinsDialog dlg;
    dlg.exec();
}

void BitcoinGUI::addressbookClicked()
{
    AddressBookDialog dlg;
    dlg.setTab(AddressBookDialog::SendingTab);
    /* if an address accepted, do a 'send' to specified address */
    if(dlg.exec())
    {
        SendCoinsDialog send(0, dlg.getReturnValue());
        send.exec();
    }
}

void BitcoinGUI::receivingAddressesClicked()
{
    AddressBookDialog dlg;
    dlg.setTab(AddressBookDialog::ReceivingTab);
    dlg.exec();
}

void BitcoinGUI::optionsClicked()
{
    OptionsDialog dlg;
    dlg.exec();
}

void BitcoinGUI::aboutClicked()
{
    AboutDialog dlg;
    dlg.exec();
}

void BitcoinGUI::newAddressClicked()
{
    qDebug() << "New address clicked";
    /* TODO: generate new address */
}

void BitcoinGUI::copyClipboardClicked()
{
    /* Copy text in address to clipboard */
    QApplication::clipboard()->setText(address->text());
}

void BitcoinGUI::setBalance(double balance)
{
    labelBalance->setText(QLocale::system().toString(balance, 8));
}

void BitcoinGUI::setAddress(const QString &addr)
{
    address->setText(addr);
}

void BitcoinGUI::setNumConnections(int count)
{
    labelConnections->setText(QLocale::system().toString(count)+" "+tr("connections"));
}

void BitcoinGUI::setNumBlocks(int count)
{
    labelBlocks->setText(QLocale::system().toString(count)+" "+tr("blocks"));
}

void BitcoinGUI::setNumTransactions(int count)
{
    labelTransactions->setText(QLocale::system().toString(count)+" "+tr("transactions"));
}
<|endoftext|>


<commit_before><commit_msg>Draw transparent background on window_content() only for TYPE_CHILD.  Transparent background is draws on GtkWindow for window types. This was necessary only for TYPE_CHILD.<commit_after><|endoftext|>


<commit_before><commit_msg>Add a TODO, remove NOTIMPLEMENTED to quiet things down.<commit_after><|endoftext|>


<commit_before>#include <SFML/Graphics.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>

#include "renderer.h"
#include "player.h"
#include "coord.h"

GLuint Texture = 0;

GLdouble norm = 1 / sqrt( 3 );

GLdouble x = 0;
GLdouble y = 0;
GLdouble z = 0;
GLdouble radius = 1;
  GLdouble vertices[24] = { x - radius, y - radius, z + radius,
							x + radius, y - radius, z + radius,
							x + radius, y + radius, z + radius,
							x - radius, y + radius, z + radius,
							x - radius, y - radius, z - radius,
							x + radius, y - radius, z - radius,
							x + radius, y + radius, z - radius,
							x - radius, y + radius, z - radius };

  GLdouble normals[24] = { -norm, -norm,  norm,
						    norm, -norm,  norm,
						    norm,  norm,  norm,
						   -norm,  norm,  norm,
						   -norm, -norm, -norm,
						    norm, -norm, -norm,
						    norm,  norm, -norm,
						   -norm,  norm, -norm };

  GLdouble texcoords[24] = { 0.125, 0.0, 0.0,
						     0.0, 0.125, 0.0,
						     0.0, 0.0, 0.0,
						     0.125, 0.0, 0.0,
						     0.0, 0.125, 0.0,
						     0.0, 0.0, 0.0,
						     0.125, 0.0, 0.0,
						     0.0, 0.125, 0.0 };

  GLubyte indices[24] = { 7, 6, 5, 4,
						  5, 6, 2, 1,
						  4, 5, 1, 0,
						  1, 2, 3, 0,
						  3, 7, 4, 0,
						  6, 7, 3, 2 };

Renderer::Renderer(Terrain initterrain, Player* player) : terrain(initterrain), player(player) {
    // Set color and depth clear value
    glClearDepth(1.f);
    glClearColor(0.f, 0.f, 0.f, 1.f); // black

    // Enable Z-buffer read and write
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

    // Face culling to render half the polys
    glEnable(GL_CULL_FACE);

    // Lighting
    GLfloat LightAmbient[]  = { 0.5f, 0.5f, 0.5f, 1.0f }; // Ambient Light Values
    GLfloat LightDiffuse[]  = { 1.0f, 1.0f, 1.0f, 1.0f };	// Diffuse Light Values
    GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };	// Light Position
    glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);				// Setup The Ambient Light
    glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);				// Setup The Diffuse Light
    glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);			// Position The Light
    glEnable(GL_LIGHT1);							// Enable Light One

    //glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); // Let glcolor work with lighting
    //glEnable(GL_COLOR_MATERIAL); // Enable lighting colors
    //glEnable(GL_LIGHTING); // Enable lighting
    glEnable(GL_TEXTURE_2D); // Enable textures

    glShadeModel(GL_SMOOTH); // Enable Smooth Shading

    // Load texture
    sf::Image Image;
    if (!Image.LoadFromFile("data/tiles.png"))
        return;

    glGenTextures(1, &Texture);
    glBindTexture(GL_TEXTURE_2D, Texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, Image.GetWidth(), Image.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, Image.GetPixelsPtr());
}

// Don't forget to destroy our texture
//glDeleteTextures(1, &Texture);

void drawCube(float x, float y, float z, float length) {
    float subsize = length / 2;

    // Apply some transformations
    glLoadIdentity();
    glTranslatef(x + subsize, y + subsize, z + subsize);
    glScalef(subsize, subsize, subsize);

    glDrawElements( GL_QUADS, 24, GL_UNSIGNED_BYTE, indices );
}

bool current;

void Renderer::renderNode(Octree<bool> terrain, float x, float y, float z, float size) {
    // Collision check against player
    if (player->X > x && player->Y > y && player->Z - 2.f > z
     && player->X < x + size && player->Y < y + size && player->Z - 2.f < z + size)
        current = true;

    if (terrain.hasChildren) {
        float subsize = size / 2;
        renderNode(terrain.children[0], x,         y,         z,         subsize);
        renderNode(terrain.children[1], x+subsize, y,         z,         subsize);
        renderNode(terrain.children[2], x,         y+subsize, z,         subsize);
        renderNode(terrain.children[3], x+subsize, y+subsize, z,         subsize);
        renderNode(terrain.children[4], x,         y,         z+subsize, subsize);
        renderNode(terrain.children[5], x+subsize, y,         z+subsize, subsize);
        renderNode(terrain.children[6], x,         y+subsize, z+subsize, subsize);
        renderNode(terrain.children[7], x+subsize, y+subsize, z+subsize, subsize);
    } else if (terrain.value) {
        drawCube(x, y, z, size);
    }
}

void Renderer::render() {

    // Clear color and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Apply some transformations
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90.f, 1.f, 1.f, 500.f);
    glRotatef(-90 + player->Yrot, 1.f, 0.f, 0.f);
    glRotatef(player->Zrot, 0.f, 0.f, 1.f);
    glTranslatef(-player->X, -player->Y, -player->Z);    // Translate The Scene Based On Player Position

    glMatrixMode(GL_MODELVIEW);

    glBindTexture(GL_TEXTURE_2D, Texture);

    glEnableClientState( GL_VERTEX_ARRAY );
    glEnableClientState( GL_NORMAL_ARRAY );
    glEnableClientState( GL_TEXTURE_COORD_ARRAY );

    glVertexPointer( 3, GL_DOUBLE, 0, &vertices[0] );
    glNormalPointer( GL_DOUBLE, 0, &normals[0] );
    glTexCoordPointer( 3, GL_DOUBLE, 0, &texcoords[0] );

    // Store current cube
    current = false;

    // Loop through chunks and render them
    int i, j, k;
    for(i = 0; i < terrain.sizeX; i++)
        for(j = 0; j < terrain.sizeY; j++)
            for(k = 0; k < terrain.sizeZ; k++)
                renderNode(terrain.GeneratedTerrain[Coord(i,j,k)], i*terrain.chunkSize, j*terrain.chunkSize, k*terrain.chunkSize, terrain.chunkSize);

    if (!current) {
        player->Z -= 0.1f;
    }

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
<commit_msg>Haha, collision checking was a fail.<commit_after>#include <SFML/Graphics.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>

#include "renderer.h"
#include "player.h"
#include "coord.h"

GLuint Texture = 0;

GLdouble norm = 1 / sqrt( 3 );

GLdouble x = 0;
GLdouble y = 0;
GLdouble z = 0;
GLdouble radius = 1;
  GLdouble vertices[24] = { x - radius, y - radius, z + radius,
							x + radius, y - radius, z + radius,
							x + radius, y + radius, z + radius,
							x - radius, y + radius, z + radius,
							x - radius, y - radius, z - radius,
							x + radius, y - radius, z - radius,
							x + radius, y + radius, z - radius,
							x - radius, y + radius, z - radius };

  GLdouble normals[24] = { -norm, -norm,  norm,
						    norm, -norm,  norm,
						    norm,  norm,  norm,
						   -norm,  norm,  norm,
						   -norm, -norm, -norm,
						    norm, -norm, -norm,
						    norm,  norm, -norm,
						   -norm,  norm, -norm };

  GLdouble texcoords[24] = { 0.125, 0.0, 0.0,
						     0.0, 0.125, 0.0,
						     0.0, 0.0, 0.0,
						     0.125, 0.0, 0.0,
						     0.0, 0.125, 0.0,
						     0.0, 0.0, 0.0,
						     0.125, 0.0, 0.0,
						     0.0, 0.125, 0.0 };

  GLubyte indices[24] = { 7, 6, 5, 4,
						  5, 6, 2, 1,
						  4, 5, 1, 0,
						  1, 2, 3, 0,
						  3, 7, 4, 0,
						  6, 7, 3, 2 };

Renderer::Renderer(Terrain initterrain, Player* player) : terrain(initterrain), player(player) {
    // Set color and depth clear value
    glClearDepth(1.f);
    glClearColor(0.f, 0.f, 0.f, 1.f); // black

    // Enable Z-buffer read and write
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

    // Face culling to render half the polys
    glEnable(GL_CULL_FACE);

    // Lighting
    GLfloat LightAmbient[]  = { 0.5f, 0.5f, 0.5f, 1.0f }; // Ambient Light Values
    GLfloat LightDiffuse[]  = { 1.0f, 1.0f, 1.0f, 1.0f };	// Diffuse Light Values
    GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };	// Light Position
    glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);				// Setup The Ambient Light
    glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);				// Setup The Diffuse Light
    glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);			// Position The Light
    glEnable(GL_LIGHT1);							// Enable Light One

    //glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); // Let glcolor work with lighting
    //glEnable(GL_COLOR_MATERIAL); // Enable lighting colors
    //glEnable(GL_LIGHTING); // Enable lighting
    glEnable(GL_TEXTURE_2D); // Enable textures

    glShadeModel(GL_SMOOTH); // Enable Smooth Shading

    // Load texture
    sf::Image Image;
    if (!Image.LoadFromFile("data/tiles.png"))
        return;

    glGenTextures(1, &Texture);
    glBindTexture(GL_TEXTURE_2D, Texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, Image.GetWidth(), Image.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, Image.GetPixelsPtr());
}

// Don't forget to destroy our texture
//glDeleteTextures(1, &Texture);

void drawCube(float x, float y, float z, float length) {
    float subsize = length / 2;

    // Apply some transformations
    glLoadIdentity();
    glTranslatef(x + subsize, y + subsize, z + subsize);
    glScalef(subsize, subsize, subsize);

    glDrawElements( GL_QUADS, 24, GL_UNSIGNED_BYTE, indices );
}

bool current;

void Renderer::renderNode(Octree<bool> terrain, float x, float y, float z, float size) {
    if (terrain.hasChildren) {
        float subsize = size / 2;
        renderNode(terrain.children[0], x,         y,         z,         subsize);
        renderNode(terrain.children[1], x+subsize, y,         z,         subsize);
        renderNode(terrain.children[2], x,         y+subsize, z,         subsize);
        renderNode(terrain.children[3], x+subsize, y+subsize, z,         subsize);
        renderNode(terrain.children[4], x,         y,         z+subsize, subsize);
        renderNode(terrain.children[5], x+subsize, y,         z+subsize, subsize);
        renderNode(terrain.children[6], x,         y+subsize, z+subsize, subsize);
        renderNode(terrain.children[7], x+subsize, y+subsize, z+subsize, subsize);
    } else if (terrain.value) {
        // Collision check against player
        if (player->X > x && player->Y > y && player->Z - 2.f > z
         && player->X < x + size && player->Y < y + size && player->Z - 2.f < z + size)
            current = true;

        drawCube(x, y, z, size);
    }
}

void Renderer::render() {

    // Clear color and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Apply some transformations
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90.f, 1.f, 1.f, 500.f);
    glRotatef(-90 + player->Yrot, 1.f, 0.f, 0.f);
    glRotatef(player->Zrot, 0.f, 0.f, 1.f);
    glTranslatef(-player->X, -player->Y, -player->Z);    // Translate The Scene Based On Player Position

    glMatrixMode(GL_MODELVIEW);

    glBindTexture(GL_TEXTURE_2D, Texture);

    glEnableClientState( GL_VERTEX_ARRAY );
    glEnableClientState( GL_NORMAL_ARRAY );
    glEnableClientState( GL_TEXTURE_COORD_ARRAY );

    glVertexPointer( 3, GL_DOUBLE, 0, &vertices[0] );
    glNormalPointer( GL_DOUBLE, 0, &normals[0] );
    glTexCoordPointer( 3, GL_DOUBLE, 0, &texcoords[0] );

    // Store current cube
    current = false;

    // Loop through chunks and render them
    int i, j, k;
    for(i = 0; i < terrain.sizeX; i++)
        for(j = 0; j < terrain.sizeY; j++)
            for(k = 0; k < terrain.sizeZ; k++)
                renderNode(terrain.GeneratedTerrain[Coord(i,j,k)], i*terrain.chunkSize, j*terrain.chunkSize, k*terrain.chunkSize, terrain.chunkSize);

    if (!current) {
        player->Z -= 0.1f;
    }

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
<|endoftext|>


<commit_before><commit_msg>opengl: More checking for GL errors.<commit_after><|endoftext|>


<commit_before>#define THEWIZARDPLUSPLUS_WIZARD_PARSER_PARSER_MACROSES

#include "vendor/better-enums/enum_strict.hpp"
#include "vendor/docopt/docopt.hpp"
#include "vendor/fmt/format.hpp"
#include "vendor/range/v3/all.hpp"

#include <thewizardplusplus/wizard_parser/exceptions/unexpected_entity_exception.hpp>
#include <thewizardplusplus/wizard_parser/lexer/tokenize.hpp>
#include <thewizardplusplus/wizard_parser/parser/parse.hpp>
#include <thewizardplusplus/wizard_parser/parser/parsers.hpp>

#include <iomanip>
#include <iostream>

using namespace thewizardplusplus::wizard_parser;
using namespace thewizardplusplus::wizard_parser::parser::operators;
using namespace std::literals::string_literals;

struct function final {
	const std::size_t arity;
	const std::function<double(const std::vector<double>&)> handler;
};

BETTER_ENUM(entity_type, std::uint8_t,
	node = exceptions::entity_type::_size(),
	constant,
	function
)

template<entity_type::_integral type>
using unexpected_entity_exception =
	exceptions::base_unexpected_entity_exception<entity_type, type>;

const auto usage =
R"(Usage:
  ./example [options] [--] [<expression>]

Options:
  -h, --help                           - show this message;
  -t TARGET, --target TARGET           - preliminary target of processing
                                       (allowed: tokens, cst);
  -p PRECISION, --precision PRECISION  - precision of a result;
  -s, --stdin                          - read an expression from stdin;
  -V, --verbose                        - mark an error.)";
const auto lexemes = lexer::lexeme_group{
	{std::regex{R"(\+)"}, "plus"},
	{std::regex{R"(-)"}, "minus"},
	{std::regex{R"(\*)"}, "star"},
	{std::regex{R"(/)"}, "slash"},
	{std::regex{R"(%)"}, "percent"},
	{std::regex{R"(\()"}, "opening_parenthesis"},
	{std::regex{R"(\))"}, "closing_parenthesis"},
	{std::regex{R"(,)"}, "comma"},
	{std::regex{R"(\d+(\.\d+)?(e-?\d+)?)"}, "number"},
	{std::regex{R"([A-Za-z_]\w*)"}, "identifier"},
	{std::regex{R"(\s+)"}, "whitespace"}
};
const auto lexemes_exceptions = lexer::type_group{"whitespace"};
// precision is taken from Boost 1.70.0, Math Toolkit 2.9.0
const auto constants = std::unordered_map<std::string, double>{
	{"pi", 3.141592653589793238462643383279502884},
	{"e", 2.718281828459045235360287471352662497}
};
const auto functions = std::unordered_map<std::string, function>{
	{"+", {2, [] (const auto& args) { return args[0] + args[1]; }}},
	{"-", {2, [] (const auto& args) { return args[0] - args[1]; }}},
	{"*", {2, [] (const auto& args) { return args[0] * args[1]; }}},
	{"/", {2, [] (const auto& args) { return args[0] / args[1]; }}},
	{"%", {2, [] (const auto& args) { return std::fmod(args[0], args[1]); }}},
	{"floor", {1, [] (const auto& args) { return std::floor(args[0]); }}},
	{"ceil", {1, [] (const auto& args) { return std::ceil(args[0]); }}},
	{"trunc", {1, [] (const auto& args) { return std::trunc(args[0]); }}},
	{"round", {1, [] (const auto& args) { return std::round(args[0]); }}},
	{"sin", {1, [] (const auto& args) { return std::sin(args[0]); }}},
	{"cos", {1, [] (const auto& args) { return std::cos(args[0]); }}},
	{"tn", {1, [] (const auto& args) { return std::tan(args[0]); }}},
	{"arcsin", {1, [] (const auto& args) { return std::asin(args[0]); }}},
	{"arccos", {1, [] (const auto& args) { return std::acos(args[0]); }}},
	{"arctn", {1, [] (const auto& args) { return std::atan(args[0]); }}},
	{"angle", {2, [] (const auto& args) { return std::atan2(args[1], args[0]); }}},
	{"pow", {2, [] (const auto& args) { return std::pow(args[0], args[1]); }}},
	{"sqrt", {1, [] (const auto& args) { return std::sqrt(args[0]); }}},
	{"exp", {1, [] (const auto& args) { return std::exp(args[0]); }}},
	{"ln", {1, [] (const auto& args) { return std::log(args[0]); }}},
	{"lg", {1, [] (const auto& args) { return std::log10(args[0]); }}},
	{"abs", {1, [] (const auto& args) { return std::abs(args[0]); }}},
};

parser::rule_parser::pointer make_parser() {
	const auto expression_dummy = parser::dummy();
	RULE(function_call) = "identifier"_t >> &"("_v >>
		-(expression_dummy % &","_v)
	>> &")"_v;
	RULE(atom) = "number"_t
		| function_call
		| "identifier"_t
		| (&"("_v >> expression_dummy >> &")"_v);
	RULE(unary) = *("-"_v) >> atom;
	RULE(product) = unary % ("*"_v | "/"_v | "%"_v);
	RULE(sum) = product % ("+"_v | "-"_v);
	expression_dummy->set_parser(sum);

	return sum;
}

double evaluate_ast_node(
	const parser::ast_node& ast,
	const std::unordered_map<std::string, double>& constants,
	const std::unordered_map<std::string, function>& functions
) {
	const auto inspect_sequence = [] (const auto& ast) -> const auto& {
		return ast.children[0].children;
	};
	const auto evaluate_with_context = [&] (const auto& ast) {
		return evaluate_ast_node(ast, constants, functions);
	};

	if (ast.type == "number") {
		return std::stod(ast.value, nullptr);
	} else if (ast.type == "identifier") {
		try {
			return constants.at(ast.value);
		} catch (const std::out_of_range& exception) {
			const auto offset = parser::get_offset(ast);
			throw unexpected_entity_exception<entity_type::constant>{offset};
		}
	} else if (ast.type == "atom") {
		const auto type = (+parser::ast_node_type::sequence)._to_string();
		const auto first_child = ast.children[0].type == type
			? inspect_sequence(ast)[0]
			: ast.children[0];
		return evaluate_with_context(first_child);
	} else if (ast.type == "unary") {
		const auto result = evaluate_with_context(inspect_sequence(ast).back());
		const auto sign = (inspect_sequence(ast).size() - 1) % 2 ? -1 : 1;
		return sign * result;
	} else if (ast.type == "function_call") {
		try {
			const auto name = inspect_sequence(ast)[0].value;
			const auto arguments = inspect_sequence(ast)
				| ranges::view::drop(1)
				| ranges::view::transform([&] (const auto& ast) {
					return evaluate_with_context(ast);
				});
			const auto function = functions.at(name);
			if (arguments.size() != function.arity) {
				const auto unit = function.arity == 1 ? "argument" : "arguments";
				const auto description =
					fmt::format("function requires {:d} {:s}", function.arity, unit);
				const auto offset = parser::get_offset(ast);
				throw exceptions::positional_exception{description, offset};
			}

			return function.handler(arguments);
		} catch (const std::out_of_range& exception) {
			const auto offset = parser::get_offset(ast);
			throw unexpected_entity_exception<entity_type::function>{offset};
		}
	} else if (ast.type == "product" || ast.type == "sum") {
		const auto first_operand = evaluate_with_context(inspect_sequence(ast)[0]);
		const auto children_chunks = inspect_sequence(ast)
			| ranges::view::drop(1)
			| ranges::view::chunk(2)
			| ranges::view::transform([] (const auto& chunk) {
				return chunk | ranges::to_<parser::ast_node_group>();
			});
		return ranges::accumulate(
			children_chunks,
			first_operand,
			[&] (const auto& result, const auto& chunk) {
				const auto name = chunk[0].value;
				const auto second_operand = evaluate_with_context(chunk[1]);
				return functions.at(name).handler({result, second_operand});
			}
		);
	} else {
		const auto offset = parser::get_offset(ast);
		throw unexpected_entity_exception<entity_type::node>{offset};
	}
}

int main(int argc, char* argv[]) {
	const auto exit = [] (const auto& code, const auto& message) {
		(code == EXIT_SUCCESS ? std::cout : std::cerr) << message << '\n';
		std::exit(code);
	};
	const auto enrich =
		[] (const auto& exception, const auto& code, const auto& token_size) {
			const auto mark_offset = std::string(exception.offset, ' ');
			const auto mark = std::string(token_size, '^');
			const auto description_lines = std::vector<std::string>{
				exception.what(),
				fmt::format(R"(| "{:s}")", code),
				fmt::format(R"(|  {:s}{:s})", mark_offset, mark)
			};
			return std::runtime_error{description_lines | ranges::view::join('\n')};
		};

	try {
		const auto options = docopt::docopt(usage, {argv+1, argv+argc}, true);
		const auto expression = options.at("<expression>")
			? options.at("<expression>").asString()
			: "";
		const auto code = options.at("--stdin").asBool()
			? std::string{std::istreambuf_iterator<char>{std::cin}, {}}
			: expression;
		const auto verbose = options.at("--verbose").asBool();
		try {
			auto tokens = lexer::tokenize_all(lexemes, lexemes_exceptions, code);
			if (options.at("--target") == "tokens"s) {
				exit(EXIT_SUCCESS, tokens);
			}

			const auto eoi = exceptions::entity_type::eoi;
			try {
				const auto ast = parser::parse_all(make_parser(), tokens);
				if (options.at("--target") == "cst"s) {
					exit(EXIT_SUCCESS, ast);
				}

				auto buffer = std::ostringstream{};
				const auto precision = options.at("--precision")
					? options.at("--precision").asLong()
					: std::numeric_limits<double>::max_digits10;
				const auto result = evaluate_ast_node(ast, constants, functions);
				buffer << std::setprecision(precision) << result;

				exit(EXIT_SUCCESS, buffer.str());
			} catch (const exceptions::unexpected_entity_exception<eoi>& exception) {
				const auto offset = exception.offset == utilities::integral_infinity
					? code.size()
					: exception.offset;
				throw exceptions::unexpected_entity_exception<eoi>{offset};
			} catch (const exceptions::positional_exception& exception) {
				const auto token = ranges::find_if(tokens, [&] (const auto& token) {
					return token.offset == exception.offset;
				});
				const auto token_size = token->value.size();
				throw verbose
					? enrich(exception, code, token_size)
					: std::runtime_error{exception};
			}
		} catch (const exceptions::positional_exception& exception) {
			throw verbose ? enrich(exception, code, 1) : std::runtime_error{exception};
		}
	} catch (const std::exception& exception) {
		exit(EXIT_FAILURE, fmt::format("error: {:s}", exception.what()));
	}
}
<commit_msg>Refactor of the example, `main()` function: fix a code style<commit_after>#define THEWIZARDPLUSPLUS_WIZARD_PARSER_PARSER_MACROSES

#include "vendor/better-enums/enum_strict.hpp"
#include "vendor/docopt/docopt.hpp"
#include "vendor/fmt/format.hpp"
#include "vendor/range/v3/all.hpp"

#include <thewizardplusplus/wizard_parser/exceptions/unexpected_entity_exception.hpp>
#include <thewizardplusplus/wizard_parser/lexer/tokenize.hpp>
#include <thewizardplusplus/wizard_parser/parser/parse.hpp>
#include <thewizardplusplus/wizard_parser/parser/parsers.hpp>

#include <iomanip>
#include <iostream>

using namespace thewizardplusplus::wizard_parser;
using namespace thewizardplusplus::wizard_parser::parser::operators;
using namespace std::literals::string_literals;

struct function final {
	const std::size_t arity;
	const std::function<double(const std::vector<double>&)> handler;
};

BETTER_ENUM(entity_type, std::uint8_t,
	node = exceptions::entity_type::_size(),
	constant,
	function
)

template<entity_type::_integral type>
using unexpected_entity_exception =
	exceptions::base_unexpected_entity_exception<entity_type, type>;

const auto usage =
R"(Usage:
  ./example [options] [--] [<expression>]

Options:
  -h, --help                           - show this message;
  -t TARGET, --target TARGET           - preliminary target of processing
                                       (allowed: tokens, cst);
  -p PRECISION, --precision PRECISION  - precision of a result;
  -s, --stdin                          - read an expression from stdin;
  -V, --verbose                        - mark an error.)";
const auto lexemes = lexer::lexeme_group{
	{std::regex{R"(\+)"}, "plus"},
	{std::regex{R"(-)"}, "minus"},
	{std::regex{R"(\*)"}, "star"},
	{std::regex{R"(/)"}, "slash"},
	{std::regex{R"(%)"}, "percent"},
	{std::regex{R"(\()"}, "opening_parenthesis"},
	{std::regex{R"(\))"}, "closing_parenthesis"},
	{std::regex{R"(,)"}, "comma"},
	{std::regex{R"(\d+(\.\d+)?(e-?\d+)?)"}, "number"},
	{std::regex{R"([A-Za-z_]\w*)"}, "identifier"},
	{std::regex{R"(\s+)"}, "whitespace"}
};
const auto lexemes_exceptions = lexer::type_group{"whitespace"};
// precision is taken from Boost 1.70.0, Math Toolkit 2.9.0
const auto constants = std::unordered_map<std::string, double>{
	{"pi", 3.141592653589793238462643383279502884},
	{"e", 2.718281828459045235360287471352662497}
};
const auto functions = std::unordered_map<std::string, function>{
	{"+", {2, [] (const auto& args) { return args[0] + args[1]; }}},
	{"-", {2, [] (const auto& args) { return args[0] - args[1]; }}},
	{"*", {2, [] (const auto& args) { return args[0] * args[1]; }}},
	{"/", {2, [] (const auto& args) { return args[0] / args[1]; }}},
	{"%", {2, [] (const auto& args) { return std::fmod(args[0], args[1]); }}},
	{"floor", {1, [] (const auto& args) { return std::floor(args[0]); }}},
	{"ceil", {1, [] (const auto& args) { return std::ceil(args[0]); }}},
	{"trunc", {1, [] (const auto& args) { return std::trunc(args[0]); }}},
	{"round", {1, [] (const auto& args) { return std::round(args[0]); }}},
	{"sin", {1, [] (const auto& args) { return std::sin(args[0]); }}},
	{"cos", {1, [] (const auto& args) { return std::cos(args[0]); }}},
	{"tn", {1, [] (const auto& args) { return std::tan(args[0]); }}},
	{"arcsin", {1, [] (const auto& args) { return std::asin(args[0]); }}},
	{"arccos", {1, [] (const auto& args) { return std::acos(args[0]); }}},
	{"arctn", {1, [] (const auto& args) { return std::atan(args[0]); }}},
	{"angle", {2, [] (const auto& args) { return std::atan2(args[1], args[0]); }}},
	{"pow", {2, [] (const auto& args) { return std::pow(args[0], args[1]); }}},
	{"sqrt", {1, [] (const auto& args) { return std::sqrt(args[0]); }}},
	{"exp", {1, [] (const auto& args) { return std::exp(args[0]); }}},
	{"ln", {1, [] (const auto& args) { return std::log(args[0]); }}},
	{"lg", {1, [] (const auto& args) { return std::log10(args[0]); }}},
	{"abs", {1, [] (const auto& args) { return std::abs(args[0]); }}},
};

parser::rule_parser::pointer make_parser() {
	const auto expression_dummy = parser::dummy();
	RULE(function_call) = "identifier"_t >> &"("_v >>
		-(expression_dummy % &","_v)
	>> &")"_v;
	RULE(atom) = "number"_t
		| function_call
		| "identifier"_t
		| (&"("_v >> expression_dummy >> &")"_v);
	RULE(unary) = *("-"_v) >> atom;
	RULE(product) = unary % ("*"_v | "/"_v | "%"_v);
	RULE(sum) = product % ("+"_v | "-"_v);
	expression_dummy->set_parser(sum);

	return sum;
}

double evaluate_ast_node(
	const parser::ast_node& ast,
	const std::unordered_map<std::string, double>& constants,
	const std::unordered_map<std::string, function>& functions
) {
	const auto inspect_sequence = [] (const auto& ast) -> const auto& {
		return ast.children[0].children;
	};
	const auto evaluate_with_context = [&] (const auto& ast) {
		return evaluate_ast_node(ast, constants, functions);
	};

	if (ast.type == "number") {
		return std::stod(ast.value, nullptr);
	} else if (ast.type == "identifier") {
		try {
			return constants.at(ast.value);
		} catch (const std::out_of_range& exception) {
			const auto offset = parser::get_offset(ast);
			throw unexpected_entity_exception<entity_type::constant>{offset};
		}
	} else if (ast.type == "atom") {
		const auto type = (+parser::ast_node_type::sequence)._to_string();
		const auto first_child = ast.children[0].type == type
			? inspect_sequence(ast)[0]
			: ast.children[0];
		return evaluate_with_context(first_child);
	} else if (ast.type == "unary") {
		const auto result = evaluate_with_context(inspect_sequence(ast).back());
		const auto sign = (inspect_sequence(ast).size() - 1) % 2 ? -1 : 1;
		return sign * result;
	} else if (ast.type == "function_call") {
		try {
			const auto name = inspect_sequence(ast)[0].value;
			const auto arguments = inspect_sequence(ast)
				| ranges::view::drop(1)
				| ranges::view::transform([&] (const auto& ast) {
					return evaluate_with_context(ast);
				});
			const auto function = functions.at(name);
			if (arguments.size() != function.arity) {
				const auto unit = function.arity == 1 ? "argument" : "arguments";
				const auto description =
					fmt::format("function requires {:d} {:s}", function.arity, unit);
				const auto offset = parser::get_offset(ast);
				throw exceptions::positional_exception{description, offset};
			}

			return function.handler(arguments);
		} catch (const std::out_of_range& exception) {
			const auto offset = parser::get_offset(ast);
			throw unexpected_entity_exception<entity_type::function>{offset};
		}
	} else if (ast.type == "product" || ast.type == "sum") {
		const auto first_operand = evaluate_with_context(inspect_sequence(ast)[0]);
		const auto children_chunks = inspect_sequence(ast)
			| ranges::view::drop(1)
			| ranges::view::chunk(2)
			| ranges::view::transform([] (const auto& chunk) {
				return chunk | ranges::to_<parser::ast_node_group>();
			});
		return ranges::accumulate(
			children_chunks,
			first_operand,
			[&] (const auto& result, const auto& chunk) {
				const auto name = chunk[0].value;
				const auto second_operand = evaluate_with_context(chunk[1]);
				return functions.at(name).handler({result, second_operand});
			}
		);
	} else {
		const auto offset = parser::get_offset(ast);
		throw unexpected_entity_exception<entity_type::node>{offset};
	}
}

int main(int argc, char* argv[]) {
	const auto exit = [] (const auto& code, const auto& message) {
		(code == EXIT_SUCCESS ? std::cout : std::cerr) << message << '\n';
		std::exit(code);
	};
	const auto enrich =
		[] (const auto& exception, const auto& code, const auto& token_size) {
			const auto mark_offset = std::string(exception.offset, ' ');
			const auto mark = std::string(token_size, '^');
			const auto description_lines = std::vector<std::string>{
				exception.what(),
				fmt::format(R"(| "{:s}")", code),
				fmt::format(R"(|  {:s}{:s})", mark_offset, mark)
			};
			return std::runtime_error{description_lines | ranges::view::join('\n')};
		};

	try {
		const auto options = docopt::docopt(usage, {argv + 1, argv + argc}, true);
		const auto expression = options.at("<expression>")
			? options.at("<expression>").asString()
			: "";
		const auto code = options.at("--stdin").asBool()
			? std::string{std::istreambuf_iterator<char>{std::cin}, {}}
			: expression;
		const auto verbose = options.at("--verbose").asBool();
		try {
			auto tokens = lexer::tokenize_all(lexemes, lexemes_exceptions, code);
			if (options.at("--target") == "tokens"s) {
				exit(EXIT_SUCCESS, tokens);
			}

			const auto eoi = exceptions::entity_type::eoi;
			try {
				const auto ast = parser::parse_all(make_parser(), tokens);
				if (options.at("--target") == "cst"s) {
					exit(EXIT_SUCCESS, ast);
				}

				auto buffer = std::ostringstream{};
				const auto precision = options.at("--precision")
					? options.at("--precision").asLong()
					: std::numeric_limits<double>::max_digits10;
				const auto result = evaluate_ast_node(ast, constants, functions);
				buffer << std::setprecision(precision) << result;

				exit(EXIT_SUCCESS, buffer.str());
			} catch (const exceptions::unexpected_entity_exception<eoi>& exception) {
				const auto offset = exception.offset == utilities::integral_infinity
					? code.size()
					: exception.offset;
				throw exceptions::unexpected_entity_exception<eoi>{offset};
			} catch (const exceptions::positional_exception& exception) {
				const auto token = ranges::find_if(tokens, [&] (const auto& token) {
					return token.offset == exception.offset;
				});
				const auto token_size = token->value.size();
				throw verbose
					? enrich(exception, code, token_size)
					: std::runtime_error{exception};
			}
		} catch (const exceptions::positional_exception& exception) {
			throw verbose ? enrich(exception, code, 1) : std::runtime_error{exception};
		}
	} catch (const std::exception& exception) {
		exit(EXIT_FAILURE, fmt::format("error: {:s}", exception.what()));
	}
}
<|endoftext|>


<commit_before>/*
  verificationresult.cpp - wraps a gpgme verify result
  Copyright (C) 2004 Klarälvdalens Datakonsult AB

  This file is part of GPGME++.

  GPGME++ is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  GPGME++ 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 Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with GPGME++; see the file COPYING.LIB.  If not, write to the
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include <gpgme++/config-gpgme++.h>
#include <gpgme++/verificationresult.h>
#include <gpgme++/notation.h>
#include "shared.h"
#include "result_p.h"
#include "util.h"

#include <gpgme.h>

#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>

class GpgME::VerificationResult::Private : public GpgME::Shared {
public:
  Private( const gpgme_verify_result_t r ) : Shared() {
    if ( !r )
      return;
#ifdef HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME
    file_name = r->file_name;
#endif
    // copy recursively, using compiler-generated copy ctor.
    // We just need to handle the pointers in the structs:
    for ( gpgme_signature_t is = r->signatures ; is ; is = is->next ) {
      gpgme_signature_t scopy = new _gpgme_signature( *is );
      if ( is->fpr )
	scopy->fpr = strdup( is->fpr );
      scopy->next = 0;
      sigs.push_back( scopy );
      // copy notations:
      nota.push_back( std::vector<Nota>() );
      purls.push_back( 0 );
      for ( gpgme_sig_notation_t in = is->notations ; in ; in = in->next ) {
	if ( !in->name ) {
	  if ( in->value )
	    purls.back() = strdup( in->value ); // policy url
	  continue;
	}
#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
	Nota n = { 0, 0, in->flags };
#else
        Nota n = { 0, 0 };
#endif
	n.name = strdup( in->name );
	if ( in->value )
	  n.value = strdup( in->value );
	nota.back().push_back( n );
      }
    }
  }
  ~Private() {
    for ( std::vector<gpgme_signature_t>::iterator it = sigs.begin() ; it != sigs.end() ; ++it ) {
      std::free( (*it)->fpr );
      delete *it; *it = 0;
    }
    for ( std::vector< std::vector<Nota> >::iterator it = nota.begin() ; it != nota.end() ; ++it )
      for ( std::vector<Nota>::iterator jt = it->begin() ; jt != it->end() ; ++jt ) {
	std::free( jt->name );  jt->name = 0;
	std::free( jt->value ); jt->value = 0;
      }
    std::for_each( purls.begin(), purls.end(), &std::free );
  }

  struct Nota {
    char * name;
    char * value;
#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
    gpgme_sig_notation_flags_t flags;
#endif
  };

  std::vector<gpgme_signature_t> sigs;
  std::vector< std::vector<Nota> > nota;
  std::vector<char*> purls;
  std::string file_name;
};

GpgME::VerificationResult::VerificationResult( gpgme_ctx_t ctx, int error )
  : GpgME::Result( error ), d( 0 )
{
  if ( error || !ctx )
    return;
  gpgme_verify_result_t res = gpgme_op_verify_result( ctx );
  if ( !res )
    return;
  d = new Private( res );
  d->ref();
}

make_standard_stuff(VerificationResult)

const char * GpgME::VerificationResult::fileName() const {
  return d ? d->file_name.c_str() : 0 ;
}

unsigned int GpgME::VerificationResult::numSignatures() const {
  return d ? d->sigs.size() : 0 ;
}

GpgME::Signature GpgME::VerificationResult::signature( unsigned int idx ) const {
  return Signature( d, idx );
}

std::vector<GpgME::Signature> GpgME::VerificationResult::signatures() const {
  if ( !d )
    return std::vector<Signature>();
  std::vector<Signature> result;
  result.reserve( d->sigs.size() );
  for ( unsigned int i = 0 ; i < d->sigs.size() ; ++i )
    result.push_back( Signature( d, i ) );
  return result;
}

GpgME::Signature::Signature( VerificationResult::Private * parent, unsigned int i )
  : d( parent ), idx( i )
{
  if ( d )
    d->ref();
}

GpgME::Signature::Signature() : d( 0 ), idx( 0 ) {}

GpgME::Signature::Signature( const Signature & other )
  : d( other.d ), idx( other.idx )
{
  if ( d )
    d->ref();
}

GpgME::Signature::~Signature() {
  if ( d )
    d->unref();
}

bool GpgME::Signature::isNull() const {
  return !d || idx >= d->sigs.size() ;
}

GpgME::Signature::Summary GpgME::Signature::summary() const {
  if ( isNull() )
    return None;
  gpgme_sigsum_t sigsum = d->sigs[idx]->summary;
  unsigned int result = 0;
  if ( sigsum & GPGME_SIGSUM_VALID       ) result |= Valid;
  if ( sigsum & GPGME_SIGSUM_GREEN       ) result |= Green;
  if ( sigsum & GPGME_SIGSUM_RED         ) result |= Red;
  if ( sigsum & GPGME_SIGSUM_KEY_REVOKED ) result |= KeyRevoked;
  if ( sigsum & GPGME_SIGSUM_KEY_EXPIRED ) result |= KeyExpired;
  if ( sigsum & GPGME_SIGSUM_SIG_EXPIRED ) result |= SigExpired;
  if ( sigsum & GPGME_SIGSUM_KEY_MISSING ) result |= KeyMissing;
  if ( sigsum & GPGME_SIGSUM_CRL_MISSING ) result |= CrlMissing;
  if ( sigsum & GPGME_SIGSUM_CRL_TOO_OLD ) result |= CrlTooOld;
  if ( sigsum & GPGME_SIGSUM_BAD_POLICY  ) result |= BadPolicy;
  if ( sigsum & GPGME_SIGSUM_SYS_ERROR   ) result |= SysError;
  return static_cast<Summary>( result );
}

const char * GpgME::Signature::fingerprint() const {
  return isNull() ? 0 : d->sigs[idx]->fpr ;
}

GpgME::Error GpgME::Signature::status() const {
  return Error( isNull() ? 0 : d->sigs[idx]->status );
}

time_t GpgME::Signature::creationTime() const {
  return static_cast<time_t>( isNull() ? 0 : d->sigs[idx]->timestamp );
}

time_t GpgME::Signature::expirationTime() const {
  return static_cast<time_t>( isNull() ? 0 : d->sigs[idx]->exp_timestamp );
}

bool GpgME::Signature::neverExpires() const {
  return expirationTime() == (time_t)0;
}

bool GpgME::Signature::isWrongKeyUsage() const {
  return !isNull() && d->sigs[idx]->wrong_key_usage;
}

bool GpgME::Signature::isVerifiedUsingChainModel() const {
#ifdef HAVE_GPGME_SIGNATURE_T_CHAIN_MODEL
  return !isNull() && d->sigs[idx]->chain_model;
#else
  return false;
#endif
}

GpgME::Signature::PKAStatus GpgME::Signature::pkaStatus() const {
#ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS
  if ( !isNull() )
    return static_cast<PKAStatus>( d->sigs[idx]->pka_trust );
#endif
  return UnknownPKAStatus;
}

const char * GpgME::Signature::pkaAddress() const {
#ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS
  if ( !isNull() )
    return d->sigs[idx]->pka_address;
#endif
  return 0;
}

GpgME::Signature::Validity GpgME::Signature::validity() const {
  if ( isNull() )
    return Unknown;
  switch ( d->sigs[idx]->validity ) {
  default:
  case GPGME_VALIDITY_UNKNOWN:   return Unknown;
  case GPGME_VALIDITY_UNDEFINED: return Undefined;
  case GPGME_VALIDITY_NEVER:     return Never;
  case GPGME_VALIDITY_MARGINAL:  return Marginal;
  case GPGME_VALIDITY_FULL:      return Full;
  case GPGME_VALIDITY_ULTIMATE:  return Ultimate;
  }
}

char GpgME::Signature::validityAsString() const {
  if ( isNull() )
    return '?';
  switch ( d->sigs[idx]->validity ) {
  default:
  case GPGME_VALIDITY_UNKNOWN:   return '?';
  case GPGME_VALIDITY_UNDEFINED: return 'q';
  case GPGME_VALIDITY_NEVER:     return 'n';
  case GPGME_VALIDITY_MARGINAL:  return 'm';
  case GPGME_VALIDITY_FULL:      return 'f';
  case GPGME_VALIDITY_ULTIMATE:  return 'u';
  }
}

GpgME::Error GpgME::Signature::nonValidityReason() const {
  return Error( isNull() ? 0 : d->sigs[idx]->validity_reason );
}

unsigned int GpgME::Signature::publicKeyAlgorithm() const {
#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
  if ( !isNull() )
    return d->sigs[idx]->pubkey_algo;
#endif
  return 0;
}

const char * GpgME::Signature::publicKeyAlgorithmAsString() const {
#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
  if ( !isNull() )
    return gpgme_pubkey_algo_name( d->sigs[idx]->pubkey_algo );
#endif
  return 0;
}

unsigned int GpgME::Signature::hashAlgorithm() const {
#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
  if ( !isNull() )
    return d->sigs[idx]->hash_algo;
#endif
  return 0;
}

const char * GpgME::Signature::hashAlgorithmAsString() const {
#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
  if ( !isNull() )
    return gpgme_hash_algo_name( d->sigs[idx]->hash_algo );
#endif
  return 0;
}

const char * GpgME::Signature::policyURL() const {
    return isNull() ? 0 : d->purls[idx] ;
}

GpgME::Notation GpgME::Signature::notation( unsigned int nidx ) const {
  return GpgME::Notation( d, idx, nidx );
}

std::vector<GpgME::Notation> GpgME::Signature::notations() const {
  if ( isNull() )
    return std::vector<GpgME::Notation>();
  std::vector<GpgME::Notation> result;
  result.reserve( d->nota[idx].size() );
  for ( unsigned int i = 0 ; i < d->nota[idx].size() ; ++i )
    result.push_back( GpgME::Notation( d, idx, i ) );
  return result;
}

class GpgME::Notation::Private {
public:
    Private() : d( 0 ), sidx( 0 ), nidx( 0 ), nota( 0 ) {}
    Private( VerificationResult::Private * priv, unsigned int sindex, unsigned int nindex )
	: d( priv ), sidx( sindex ), nidx( nindex ), nota( 0 )
    {
      if ( d )
        d->ref();
    }
    Private( gpgme_sig_notation_t n )
	: d( 0 ), sidx( 0 ), nidx( 0 ), nota( n ? new _gpgme_sig_notation( *n ) : 0 )
    {
      if ( nota && nota->name )
        nota->name = strdup( nota->name );
      if ( nota && nota->value )
        nota->value = strdup( nota->value );
    }
    Private( const Private & other )
	: d( other.d ), sidx( other.sidx ), nidx( other.nidx ), nota( other.nota )
    {
      if ( d )
        d->ref();
      if ( nota ) {
        nota->name = strdup( nota->name );
        nota->value = strdup( nota->value );
      }
    }
    ~Private() {
      if ( d )
        d->unref();
      if ( nota ) {
        std::free( nota->name );  nota->name = 0;
        std::free( nota->value ); nota->value = 0;
      }
    }

    VerificationResult::Private * d;
    unsigned int sidx, nidx;
    gpgme_sig_notation_t nota;
};

GpgME::Notation::Notation( VerificationResult::Private * parent, unsigned int sindex, unsigned int nindex )
  : d( new Private( parent, sindex, nindex ) )
{

}

GpgME::Notation::Notation( gpgme_sig_notation_t nota )
  : d( new Private( nota ) )
{

}

GpgME::Notation::Notation() : d( 0 ) {}

GpgME::Notation::Notation( const Notation & other )
  : d( other.d ? new Private( *other.d ) : 0 )
{

}

GpgME::Notation::~Notation() {
  delete d; d = 0;
}

bool GpgME::Notation::isNull() const {
    if ( !d )
	return true;
    if ( d->d )
	return d->sidx >= d->d->nota.size() || d->nidx >= d->d->nota[d->sidx].size() ;
    return !d->nota;
}

const char * GpgME::Notation::name() const {
    return
	isNull() ? 0 :
	d->d ? d->d->nota[d->sidx][d->nidx].name :
	d->nota ? d->nota->name : 0 ;
}

const char * GpgME::Notation::value() const {
    return
	isNull() ? 0 :
	d->d ? d->d->nota[d->sidx][d->nidx].value :
	d->nota ? d->nota->value : 0 ;
}

GpgME::Notation::Flags GpgME::Notation::flags() const {
    return
      convert_from_gpgme_sig_notation_flags_t(
#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
        isNull() ? 0 :
        d->d ? d->d->nota[d->sidx][d->nidx].flags :
        d->nota ? d->nota->flags : 0 );
#else
        0 );
#endif
}

bool GpgME::Notation::isHumanReadable() const {
    return flags() & HumanReadable;
}

bool GpgME::Notation::isCritical() const {
    return flags() & Critical;
}
<commit_msg>Don't crash when the verification job comes back.<commit_after>/*
  verificationresult.cpp - wraps a gpgme verify result
  Copyright (C) 2004 Klarälvdalens Datakonsult AB

  This file is part of GPGME++.

  GPGME++ is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  GPGME++ 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 Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with GPGME++; see the file COPYING.LIB.  If not, write to the
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include <gpgme++/config-gpgme++.h>
#include <gpgme++/verificationresult.h>
#include <gpgme++/notation.h>
#include "shared.h"
#include "result_p.h"
#include "util.h"

#include <gpgme.h>

#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>

class GpgME::VerificationResult::Private : public GpgME::Shared {
public:
  Private( const gpgme_verify_result_t r ) : Shared() {
    if ( !r )
      return;
#ifdef HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME
    if ( r->file_name )
      file_name = r->file_name;
#endif
    // copy recursively, using compiler-generated copy ctor.
    // We just need to handle the pointers in the structs:
    for ( gpgme_signature_t is = r->signatures ; is ; is = is->next ) {
      gpgme_signature_t scopy = new _gpgme_signature( *is );
      if ( is->fpr )
	scopy->fpr = strdup( is->fpr );
      scopy->next = 0;
      sigs.push_back( scopy );
      // copy notations:
      nota.push_back( std::vector<Nota>() );
      purls.push_back( 0 );
      for ( gpgme_sig_notation_t in = is->notations ; in ; in = in->next ) {
	if ( !in->name ) {
	  if ( in->value )
	    purls.back() = strdup( in->value ); // policy url
	  continue;
	}
#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
	Nota n = { 0, 0, in->flags };
#else
        Nota n = { 0, 0 };
#endif
	n.name = strdup( in->name );
	if ( in->value )
	  n.value = strdup( in->value );
	nota.back().push_back( n );
      }
    }
  }
  ~Private() {
    for ( std::vector<gpgme_signature_t>::iterator it = sigs.begin() ; it != sigs.end() ; ++it ) {
      std::free( (*it)->fpr );
      delete *it; *it = 0;
    }
    for ( std::vector< std::vector<Nota> >::iterator it = nota.begin() ; it != nota.end() ; ++it )
      for ( std::vector<Nota>::iterator jt = it->begin() ; jt != it->end() ; ++jt ) {
	std::free( jt->name );  jt->name = 0;
	std::free( jt->value ); jt->value = 0;
      }
    std::for_each( purls.begin(), purls.end(), &std::free );
  }

  struct Nota {
    char * name;
    char * value;
#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
    gpgme_sig_notation_flags_t flags;
#endif
  };

  std::vector<gpgme_signature_t> sigs;
  std::vector< std::vector<Nota> > nota;
  std::vector<char*> purls;
  std::string file_name;
};

GpgME::VerificationResult::VerificationResult( gpgme_ctx_t ctx, int error )
  : GpgME::Result( error ), d( 0 )
{
  if ( error || !ctx )
    return;
  gpgme_verify_result_t res = gpgme_op_verify_result( ctx );
  if ( !res )
    return;
  d = new Private( res );
  d->ref();
}

make_standard_stuff(VerificationResult)

const char * GpgME::VerificationResult::fileName() const {
  return d ? d->file_name.c_str() : 0 ;
}

unsigned int GpgME::VerificationResult::numSignatures() const {
  return d ? d->sigs.size() : 0 ;
}

GpgME::Signature GpgME::VerificationResult::signature( unsigned int idx ) const {
  return Signature( d, idx );
}

std::vector<GpgME::Signature> GpgME::VerificationResult::signatures() const {
  if ( !d )
    return std::vector<Signature>();
  std::vector<Signature> result;
  result.reserve( d->sigs.size() );
  for ( unsigned int i = 0 ; i < d->sigs.size() ; ++i )
    result.push_back( Signature( d, i ) );
  return result;
}

GpgME::Signature::Signature( VerificationResult::Private * parent, unsigned int i )
  : d( parent ), idx( i )
{
  if ( d )
    d->ref();
}

GpgME::Signature::Signature() : d( 0 ), idx( 0 ) {}

GpgME::Signature::Signature( const Signature & other )
  : d( other.d ), idx( other.idx )
{
  if ( d )
    d->ref();
}

GpgME::Signature::~Signature() {
  if ( d )
    d->unref();
}

bool GpgME::Signature::isNull() const {
  return !d || idx >= d->sigs.size() ;
}

GpgME::Signature::Summary GpgME::Signature::summary() const {
  if ( isNull() )
    return None;
  gpgme_sigsum_t sigsum = d->sigs[idx]->summary;
  unsigned int result = 0;
  if ( sigsum & GPGME_SIGSUM_VALID       ) result |= Valid;
  if ( sigsum & GPGME_SIGSUM_GREEN       ) result |= Green;
  if ( sigsum & GPGME_SIGSUM_RED         ) result |= Red;
  if ( sigsum & GPGME_SIGSUM_KEY_REVOKED ) result |= KeyRevoked;
  if ( sigsum & GPGME_SIGSUM_KEY_EXPIRED ) result |= KeyExpired;
  if ( sigsum & GPGME_SIGSUM_SIG_EXPIRED ) result |= SigExpired;
  if ( sigsum & GPGME_SIGSUM_KEY_MISSING ) result |= KeyMissing;
  if ( sigsum & GPGME_SIGSUM_CRL_MISSING ) result |= CrlMissing;
  if ( sigsum & GPGME_SIGSUM_CRL_TOO_OLD ) result |= CrlTooOld;
  if ( sigsum & GPGME_SIGSUM_BAD_POLICY  ) result |= BadPolicy;
  if ( sigsum & GPGME_SIGSUM_SYS_ERROR   ) result |= SysError;
  return static_cast<Summary>( result );
}

const char * GpgME::Signature::fingerprint() const {
  return isNull() ? 0 : d->sigs[idx]->fpr ;
}

GpgME::Error GpgME::Signature::status() const {
  return Error( isNull() ? 0 : d->sigs[idx]->status );
}

time_t GpgME::Signature::creationTime() const {
  return static_cast<time_t>( isNull() ? 0 : d->sigs[idx]->timestamp );
}

time_t GpgME::Signature::expirationTime() const {
  return static_cast<time_t>( isNull() ? 0 : d->sigs[idx]->exp_timestamp );
}

bool GpgME::Signature::neverExpires() const {
  return expirationTime() == (time_t)0;
}

bool GpgME::Signature::isWrongKeyUsage() const {
  return !isNull() && d->sigs[idx]->wrong_key_usage;
}

bool GpgME::Signature::isVerifiedUsingChainModel() const {
#ifdef HAVE_GPGME_SIGNATURE_T_CHAIN_MODEL
  return !isNull() && d->sigs[idx]->chain_model;
#else
  return false;
#endif
}

GpgME::Signature::PKAStatus GpgME::Signature::pkaStatus() const {
#ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS
  if ( !isNull() )
    return static_cast<PKAStatus>( d->sigs[idx]->pka_trust );
#endif
  return UnknownPKAStatus;
}

const char * GpgME::Signature::pkaAddress() const {
#ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS
  if ( !isNull() )
    return d->sigs[idx]->pka_address;
#endif
  return 0;
}

GpgME::Signature::Validity GpgME::Signature::validity() const {
  if ( isNull() )
    return Unknown;
  switch ( d->sigs[idx]->validity ) {
  default:
  case GPGME_VALIDITY_UNKNOWN:   return Unknown;
  case GPGME_VALIDITY_UNDEFINED: return Undefined;
  case GPGME_VALIDITY_NEVER:     return Never;
  case GPGME_VALIDITY_MARGINAL:  return Marginal;
  case GPGME_VALIDITY_FULL:      return Full;
  case GPGME_VALIDITY_ULTIMATE:  return Ultimate;
  }
}

char GpgME::Signature::validityAsString() const {
  if ( isNull() )
    return '?';
  switch ( d->sigs[idx]->validity ) {
  default:
  case GPGME_VALIDITY_UNKNOWN:   return '?';
  case GPGME_VALIDITY_UNDEFINED: return 'q';
  case GPGME_VALIDITY_NEVER:     return 'n';
  case GPGME_VALIDITY_MARGINAL:  return 'm';
  case GPGME_VALIDITY_FULL:      return 'f';
  case GPGME_VALIDITY_ULTIMATE:  return 'u';
  }
}

GpgME::Error GpgME::Signature::nonValidityReason() const {
  return Error( isNull() ? 0 : d->sigs[idx]->validity_reason );
}

unsigned int GpgME::Signature::publicKeyAlgorithm() const {
#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
  if ( !isNull() )
    return d->sigs[idx]->pubkey_algo;
#endif
  return 0;
}

const char * GpgME::Signature::publicKeyAlgorithmAsString() const {
#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
  if ( !isNull() )
    return gpgme_pubkey_algo_name( d->sigs[idx]->pubkey_algo );
#endif
  return 0;
}

unsigned int GpgME::Signature::hashAlgorithm() const {
#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
  if ( !isNull() )
    return d->sigs[idx]->hash_algo;
#endif
  return 0;
}

const char * GpgME::Signature::hashAlgorithmAsString() const {
#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
  if ( !isNull() )
    return gpgme_hash_algo_name( d->sigs[idx]->hash_algo );
#endif
  return 0;
}

const char * GpgME::Signature::policyURL() const {
    return isNull() ? 0 : d->purls[idx] ;
}

GpgME::Notation GpgME::Signature::notation( unsigned int nidx ) const {
  return GpgME::Notation( d, idx, nidx );
}

std::vector<GpgME::Notation> GpgME::Signature::notations() const {
  if ( isNull() )
    return std::vector<GpgME::Notation>();
  std::vector<GpgME::Notation> result;
  result.reserve( d->nota[idx].size() );
  for ( unsigned int i = 0 ; i < d->nota[idx].size() ; ++i )
    result.push_back( GpgME::Notation( d, idx, i ) );
  return result;
}

class GpgME::Notation::Private {
public:
    Private() : d( 0 ), sidx( 0 ), nidx( 0 ), nota( 0 ) {}
    Private( VerificationResult::Private * priv, unsigned int sindex, unsigned int nindex )
	: d( priv ), sidx( sindex ), nidx( nindex ), nota( 0 )
    {
      if ( d )
        d->ref();
    }
    Private( gpgme_sig_notation_t n )
	: d( 0 ), sidx( 0 ), nidx( 0 ), nota( n ? new _gpgme_sig_notation( *n ) : 0 )
    {
      if ( nota && nota->name )
        nota->name = strdup( nota->name );
      if ( nota && nota->value )
        nota->value = strdup( nota->value );
    }
    Private( const Private & other )
	: d( other.d ), sidx( other.sidx ), nidx( other.nidx ), nota( other.nota )
    {
      if ( d )
        d->ref();
      if ( nota ) {
        nota->name = strdup( nota->name );
        nota->value = strdup( nota->value );
      }
    }
    ~Private() {
      if ( d )
        d->unref();
      if ( nota ) {
        std::free( nota->name );  nota->name = 0;
        std::free( nota->value ); nota->value = 0;
      }
    }

    VerificationResult::Private * d;
    unsigned int sidx, nidx;
    gpgme_sig_notation_t nota;
};

GpgME::Notation::Notation( VerificationResult::Private * parent, unsigned int sindex, unsigned int nindex )
  : d( new Private( parent, sindex, nindex ) )
{

}

GpgME::Notation::Notation( gpgme_sig_notation_t nota )
  : d( new Private( nota ) )
{

}

GpgME::Notation::Notation() : d( 0 ) {}

GpgME::Notation::Notation( const Notation & other )
  : d( other.d ? new Private( *other.d ) : 0 )
{

}

GpgME::Notation::~Notation() {
  delete d; d = 0;
}

bool GpgME::Notation::isNull() const {
    if ( !d )
	return true;
    if ( d->d )
	return d->sidx >= d->d->nota.size() || d->nidx >= d->d->nota[d->sidx].size() ;
    return !d->nota;
}

const char * GpgME::Notation::name() const {
    return
	isNull() ? 0 :
	d->d ? d->d->nota[d->sidx][d->nidx].name :
	d->nota ? d->nota->name : 0 ;
}

const char * GpgME::Notation::value() const {
    return
	isNull() ? 0 :
	d->d ? d->d->nota[d->sidx][d->nidx].value :
	d->nota ? d->nota->value : 0 ;
}

GpgME::Notation::Flags GpgME::Notation::flags() const {
    return
      convert_from_gpgme_sig_notation_flags_t(
#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
        isNull() ? 0 :
        d->d ? d->d->nota[d->sidx][d->nidx].flags :
        d->nota ? d->nota->flags : 0 );
#else
        0 );
#endif
}

bool GpgME::Notation::isHumanReadable() const {
    return flags() & HumanReadable;
}

bool GpgME::Notation::isCritical() const {
    return flags() & Critical;
}
<|endoftext|>


<commit_before>/*  This file is part of the Vc library.

    Copyright (C) 2010 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <Vc/Vc>
#include "unittest.h"

using namespace Vc;

template<typename V> void reads()
{
    typedef typename V::EntryType T;
    typedef typename V::IndexType I;

    V a = V::Zero();
    const T zero = 0;
    for (int i = 0; i < V::Size; ++i) {
        const T x = a[i];
        COMPARE(x, zero);
    }
    a = static_cast<V>(I::IndexesFromZero());
    for (int i = 0; i < V::Size; ++i) {
        const T x = a[i];
        const T y = i;
        COMPARE(x, y);
    }
}

template<typename V> void writes()
{
    typedef typename V::EntryType T;
    typedef typename V::IndexType I;

    V a;
    for (int i = 0; i < V::Size; ++i) {
        a[i] = static_cast<T>(i);
    }
    V b = static_cast<V>(I::IndexesFromZero());
    COMPARE(a, b);

    const T one = 1;
    const T two = 2;

    if (V::Size == 1) {
        a(a == 0) += one;
        a[0] += one;
        a(a == 0) += one;
        COMPARE(a, V(2));
    } else if (V::Size == 4) {
        a(a == 1) += two;
        a[2] += one;
        a(a == 3) += one;
        b(b == 1) += one;
        b(b == 2) += one;
        b(b == 3) += one;
        COMPARE(a, b);
    } else if (V::Size == 8 || V::Size == 16) {
        a(a == 2) += two;
        a[3] += one;
        a(a == 4) += one;
        b(b == 2) += one;
        b(b == 3) += one;
        b(b == 4) += one;
        COMPARE(a, b);
    } else if (V::Size == 2) { // a = [0, 1]; b = [0, 1]
        a(a == 0) += two;      // a = [2, 1]
        a[1] += one;           // a = [2, 2]
        a(a == 2) += one;      // a = [3, 3]
        b(b == 0) += one;      // b = [1, 1]
        b(b == 1) += one;      // b = [2, 2]
        b(b == 2) += one;      // b = [3, 3]
        COMPARE(a, b);
    } else {
        FAIL() << "unsupported Vector::Size";
    }
}

int main(int argc, char **argv)
{
    initTest(argc, argv);

    testAllTypes(reads);
    testAllTypes(writes);

    return 0;
}
<commit_msg>add test to check scalar access with immediate index<commit_after>/*  This file is part of the Vc library.

    Copyright (C) 2010 Matthias Kretz <kretz@kde.org>

    Vc is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Vc is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <Vc/Vc>
#include "unittest.h"

using namespace Vc;

template<typename V> void reads()
{
    typedef typename V::EntryType T;
    typedef typename V::IndexType I;

    V a = V::Zero();
    const T zero = 0;
    for (int i = 0; i < V::Size; ++i) {
        const T x = a[i];
        COMPARE(x, zero);
    }
    a = static_cast<V>(I::IndexesFromZero());
    for (int i = 0; i < V::Size; ++i) {
        const T x = a[i];
        const T y = i;
        COMPARE(x, y);
    }
}

template<typename V, size_t Index>
inline void readsConstantIndexTest(const V a, const V b)
{
    typedef typename V::EntryType T;
    {
        const T x = a[Index];
        const T zero = 0;
        COMPARE(x, zero);
    }{
        const T x = b[Index];
        const T y = Index;
        COMPARE(x, y);
    }
}

template<typename V, size_t Index>
struct ReadsConstantIndex
{
    ReadsConstantIndex(const V a, const V b)
    {
        readsConstantIndexTest<V, Index>(a, b);
        ReadsConstantIndex<V, Index - 1>(a, b);
    }
};

template<typename V>
struct ReadsConstantIndex<V, 0>
{
    ReadsConstantIndex(const V a, const V b)
    {
        readsConstantIndexTest<V, 0>(a, b);
    }
};

template<typename V> void readsConstantIndex()
{
    typedef typename V::IndexType I;

    V a = V::Zero();
    V b = static_cast<V>(I::IndexesFromZero());
    ReadsConstantIndex<V, V::Size - 1>(a, b);
}

template<typename V> void writes()
{
    typedef typename V::EntryType T;
    typedef typename V::IndexType I;

    V a;
    for (int i = 0; i < V::Size; ++i) {
        a[i] = static_cast<T>(i);
    }
    V b = static_cast<V>(I::IndexesFromZero());
    COMPARE(a, b);

    const T one = 1;
    const T two = 2;

    if (V::Size == 1) {
        a(a == 0) += one;
        a[0] += one;
        a(a == 0) += one;
        COMPARE(a, V(2));
    } else if (V::Size == 4) {
        a(a == 1) += two;
        a[2] += one;
        a(a == 3) += one;
        b(b == 1) += one;
        b(b == 2) += one;
        b(b == 3) += one;
        COMPARE(a, b);
    } else if (V::Size == 8 || V::Size == 16) {
        a(a == 2) += two;
        a[3] += one;
        a(a == 4) += one;
        b(b == 2) += one;
        b(b == 3) += one;
        b(b == 4) += one;
        COMPARE(a, b);
    } else if (V::Size == 2) { // a = [0, 1]; b = [0, 1]
        a(a == 0) += two;      // a = [2, 1]
        a[1] += one;           // a = [2, 2]
        a(a == 2) += one;      // a = [3, 3]
        b(b == 0) += one;      // b = [1, 1]
        b(b == 1) += one;      // b = [2, 2]
        b(b == 2) += one;      // b = [3, 3]
        COMPARE(a, b);
    } else {
        FAIL() << "unsupported Vector::Size";
    }
}

int main(int argc, char **argv)
{
    initTest(argc, argv);

    testAllTypes(reads);
    testAllTypes(writes);
    testAllTypes(readsConstantIndex);
    //testAllTypes(writesConstantIndex);

    return 0;
}
<|endoftext|>