<commit_before>#include "gorgone.h"
using namespace cv;
using namespace ofxCv;
int accum = 0;

void gorgone::setup()
{
  masterIp = "Mac-Pro-de-10-52.local";
  appName = "gorgone-1";
  parseCmdLineOptions();
  vidGrabber.setup(filename);
  svgInterp.setup();
  jamoma.setup((void*) this, appName, masterIp);
  motionDetector.setup(&jamoma);
}

void gorgone::exit(){
  setPwm(0);
#ifdef TARGET_RASPBERRY_PI
  vidGrabber.led.switchOffIR();
#endif
}

void gorgone::update()
{
  // cout << ofGetFrameRate() << " fps" << endl;

  vidGrabber.update();

  if ( vidGrabber.isFrameNew() ){
    frame = vidGrabber.getFrame();

    if ( bMotion ){
      motionDetector.update(frame);
    }

    if( bTracking ){

      if ( frame.cols == 0 ) return;

      cv::Mat gray;
      if ( frame.channels() == 1 ){
        gray = frame.clone();
      } else {
        cv::cvtColor(frame, gray, CV_RGB2GRAY);
      }

      cout << "new frame to process : " << gray.cols << "x" << gray.rows << endl;

      irisDetector.update(gray);
    }
  }

  if (bComputeCode) {
    irisDetector.computeCode();
    bComputeCode=false;
    jamoma.mComputeIrisCodeParameter.set("value", bComputeCode);

/*
// desactivated because Max doesn't handle list longer than 256 item, yes this still happens in 2015...
    TTValue v;
    Mat code = irisDetector.getIrisCode();
    v.push_back(code.cols);
    v.push_back(code.rows);
    uchar* p;
    for (int i = 0; i < code.rows; i++ ){
      p=code.ptr<uchar>(i);
      for (int j = 0; j < code.cols; j++ ){
        v.push_back((int) p[j]);
      }
    }
    cout << "v size : " << v.size() << endl;
    jamoma.mTrackingIrisCodeReturn.set("value",v);
*/
  }

  Mat img = irisDetector.getIrisCode();
  if( bDisplaying && irisDetector.newCode && img.total() > 0 ) {

    if ( irisDetector.newCode ){
      svgInterp.coeff.clear();
      cout << "code image resolution : " << img.cols << "x" << img.rows << endl;
      uchar* p;
      for (int i = 0; i < img.rows; i++ ){
        float avg=0;
        p=img.ptr<uchar>(i);
        for (int j = 0; j < img.cols; j++ ){
          avg+=p[j] / 255.;
        }
        avg/=img.cols;
        svgInterp.coeff.push_back(avg);
      }
      irisDetector.newCode = false;
    }

    TTValue v,x,y;
    for (int i = 0; i<svgInterp.coeff.size(); i++){
      v.push_back(svgInterp.coeff[i]);
    }
    jamoma.mDrawingCoeffParameter.set("value", v);
    svgInterp.multiInterpolation();

    vector<ofVec3f> line = svgInterp.interpolatedLine;

    for (int i=0; i<line.size(); i++){
      x.push_back(line[i].x);
      y.push_back(line[i].y);
    }

    jamoma.mDrawingShapeXReturn.set("value", x);
    jamoma.mDrawingShapeYReturn.set("value", y);
  }
}

void gorgone::draw()
{
  // cout << ofGetFrameRate() << " fps" << endl;
  vidGrabber.draw(0,0);
  // drawMat(frame,0,0);
  if ( bTracking )
    irisDetector.drawEyes();
  if ( bDisplaying )
    svgInterp.draw();
}

void gorgone::keyPressed(int key)
{
  switch (key){
    case 's':
      irisDetector.save();
      break;
    case ' ':
      irisDetector.reset();
      break;
    case 'c':
      bComputeCode=true;
      break;
    case 't':
      bTracking = !bTracking;
      if ( bTracking ) irisDetector.reset();
#ifdef TARGET_RASPBERRY_PI
      if ( bTracking ) vidGrabber.led.switchOnIR();
      else vidGrabber.led.switchOffIR();
#endif
      break;
    case 'd':
      bDisplaying = !bDisplaying;
      break;
#ifdef TARGET_RASPBERRY_PI
    case 'i':
      vidGrabber.led.switchOnIR();
      break;
    case 'o':
      vidGrabber.led.switchOffIR();
      break;
    case 'w':
      vidGrabber.led.switchOnWhite();
      break;
    case 'x':
      vidGrabber.led.switchOffWhite();
      break;
#endif
    default :
      break;
  }
}

void gorgone::messageReceived(ofMessage& message)
{
}

void gorgone::parseCmdLineOptions(){
  vector<string> keys = ofxArgParser::allKeys();
  for (int i = 0; i < keys.size(); i++) {
    if ( keys[i] == "f" )   filename   = ofxArgParser::getValue(keys[i]);
    if ( keys[i] == "name" ) appName =  ofxArgParser::getValue(keys[i]);
    if ( keys[i] == "masterIp" ) masterIp =  ofxArgParser::getValue(keys[i]);
    cout << "key: " << keys[i] << ", value: " << ofxArgParser::getValue(keys[i]) << endl;
  }
}

void gorgone::setPwm(float pc){
#ifdef TARGET_RASPBERRY_PI
  ofstream file;
  file.open("/dev/servoblaster", ios::in);
  file << "0=" << pc << "%" << endl;
  file.close();
#endif
}
<commit_msg>restore preview<commit_after>#include "gorgone.h"
using namespace cv;
using namespace ofxCv;
int accum = 0;

void gorgone::setup()
{
  masterIp = "Mac-Pro-de-10-52.local";
  appName = "gorgone-1";
  parseCmdLineOptions();
  vidGrabber.setup(filename);
  svgInterp.setup();
  jamoma.setup((void*) this, appName, masterIp);
  motionDetector.setup(&jamoma);
}

void gorgone::exit(){
  setPwm(0);
#ifdef TARGET_RASPBERRY_PI
  vidGrabber.led.switchOffIR();
#endif
}

void gorgone::update()
{
  // cout << ofGetFrameRate() << " fps" << endl;

  vidGrabber.update();

  if ( vidGrabber.isFrameNew() ){
    frame = vidGrabber.getFrame();

    if ( bMotion ){
      motionDetector.update(frame);
    }

    if( bTracking ){

      if ( frame.cols == 0 ) return;

      cv::Mat gray;
      if ( frame.channels() == 1 ){
        gray = frame.clone();
      } else {
        cv::cvtColor(frame, gray, CV_RGB2GRAY);
      }

      cout << "new frame to process : " << gray.cols << "x" << gray.rows << endl;

      irisDetector.update(gray);
    }
  }

  if (bComputeCode) {
    irisDetector.computeCode();
    bComputeCode=false;
    jamoma.mComputeIrisCodeParameter.set("value", bComputeCode);

/*
// desactivated because Max doesn't handle list longer than 256 item, yes this still happens in 2015...
    TTValue v;
    Mat code = irisDetector.getIrisCode();
    v.push_back(code.cols);
    v.push_back(code.rows);
    uchar* p;
    for (int i = 0; i < code.rows; i++ ){
      p=code.ptr<uchar>(i);
      for (int j = 0; j < code.cols; j++ ){
        v.push_back((int) p[j]);
      }
    }
    cout << "v size : " << v.size() << endl;
    jamoma.mTrackingIrisCodeReturn.set("value",v);
*/
  }

  Mat img = irisDetector.getIrisCode();
  if( bDisplaying && irisDetector.newCode && img.total() > 0 ) {

    if ( irisDetector.newCode ){
      svgInterp.coeff.clear();
      cout << "code image resolution : " << img.cols << "x" << img.rows << endl;
      uchar* p;
      for (int i = 0; i < img.rows; i++ ){
        float avg=0;
        p=img.ptr<uchar>(i);
        for (int j = 0; j < img.cols; j++ ){
          avg+=p[j] / 255.;
        }
        avg/=img.cols;
        svgInterp.coeff.push_back(avg);
      }
      irisDetector.newCode = false;
    }

    TTValue v,x,y;
    for (int i = 0; i<svgInterp.coeff.size(); i++){
      v.push_back(svgInterp.coeff[i]);
    }
    jamoma.mDrawingCoeffParameter.set("value", v);
    svgInterp.multiInterpolation();

    vector<ofVec3f> line = svgInterp.interpolatedLine;

    for (int i=0; i<line.size(); i++){
      x.push_back(line[i].x);
      y.push_back(line[i].y);
    }

    jamoma.mDrawingShapeXReturn.set("value", x);
    jamoma.mDrawingShapeYReturn.set("value", y);
  }
}

void gorgone::draw()
{
  // cout << ofGetFrameRate() << " fps" << endl;
  //vidGrabber.draw(0,0);
  drawMat(frame,0,0);
  if ( bTracking )
    irisDetector.drawEyes();
  if ( bDisplaying )
    svgInterp.draw();
}

void gorgone::keyPressed(int key)
{
  switch (key){
    case 's':
      irisDetector.save();
      break;
    case ' ':
      irisDetector.reset();
      break;
    case 'c':
      bComputeCode=true;
      break;
    case 't':
      bTracking = !bTracking;
      if ( bTracking ) irisDetector.reset();
#ifdef TARGET_RASPBERRY_PI
      if ( bTracking ) vidGrabber.led.switchOnIR();
      else vidGrabber.led.switchOffIR();
#endif
      break;
    case 'd':
      bDisplaying = !bDisplaying;
      break;
#ifdef TARGET_RASPBERRY_PI
    case 'i':
      vidGrabber.led.switchOnIR();
      break;
    case 'o':
      vidGrabber.led.switchOffIR();
      break;
    case 'w':
      vidGrabber.led.switchOnWhite();
      break;
    case 'x':
      vidGrabber.led.switchOffWhite();
      break;
#endif
    default :
      break;
  }
}

void gorgone::messageReceived(ofMessage& message)
{
}

void gorgone::parseCmdLineOptions(){
  vector<string> keys = ofxArgParser::allKeys();
  for (int i = 0; i < keys.size(); i++) {
    if ( keys[i] == "f" )   filename   = ofxArgParser::getValue(keys[i]);
    if ( keys[i] == "name" ) appName =  ofxArgParser::getValue(keys[i]);
    if ( keys[i] == "masterIp" ) masterIp =  ofxArgParser::getValue(keys[i]);
    cout << "key: " << keys[i] << ", value: " << ofxArgParser::getValue(keys[i]) << endl;
  }
}

void gorgone::setPwm(float pc){
#ifdef TARGET_RASPBERRY_PI
  ofstream file;
  file.open("/dev/servoblaster", ios::in);
  file << "0=" << pc << "%" << endl;
  file.close();
#endif
}
<|endoftext|>


<commit_before>#include "gorgone.h"
using namespace cv;
using namespace ofxCv;
int accum = 0;

void gorgone::setup()
{
  ofSetLogLevel(OF_LOG_NOTICE);
  masterIp = "Mac-Pro-de-10-52.local";
  appName = "gorgone-1";
  parseCmdLineOptions();
  vidGrabber.setup(filename);
  svgInterp.setup();
  jamoma.setup((void*) this, appName, masterIp);
  motionDetector.setup(&jamoma);
  irisDetector.setJamomaRef(&jamoma);
  counter = 0;
}

void gorgone::exit(){
  setPwm(0);
#ifdef TARGET_RASPBERRY_PI
  vidGrabber.led.switchOffIR();
#endif
}

void gorgone::update()
{
  ofLogVerbose("gorgone") << ofGetFrameRate() << " fps" << endl;

  vidGrabber.update();

  if ( vidGrabber.isFrameNew() ){
    frame = vidGrabber.getFrame();

    if ( bMotion ){
      motionDetector.update(frame);
    }

    if( bTracking ){

      if ( frame.cols == 0 ) return;

      cv::Mat gray;
      if ( frame.channels() == 1 ){
        gray = frame.clone();
      } else {
        cv::cvtColor(frame, gray, CV_RGB2GRAY);
      }

      ofLogVerbose("gorgone") << "new frame to process : " << gray.cols << "x" << gray.rows << endl;

      irisDetector.updateBool(gray);
    }
  }

  if (bComputeCode) {
    irisDetector.computeCode();
    bComputeCode=false;
    jamoma.mComputeIrisCodeParameter.set("value", bComputeCode);

/*
// desactivated because Max doesn't handle list longer than 256 item, yes this still happens in 2015...
    TTValue v;
    Mat code = irisDetector.getIrisCode();
    v.push_back(code.cols);
    v.push_back(code.rows);
    uchar* p;
    for (int i = 0; i < code.rows; i++ ){
      p=code.ptr<uchar>(i);
      for (int j = 0; j < code.cols; j++ ){
        v.push_back((int) p[j]);
      }
    }
    cout << "v size : " << v.size() << endl;
    jamoma.mTrackingIrisCodeReturn.set("value",v);
*/
  }

  Mat img = irisDetector.getIrisCode();
  if( bDisplaying && irisDetector.newCode && img.total() > 0 ) {

    if ( irisDetector.newCode ){
      svgInterp.coeff.clear();
      ofLogVerbose("gorgone") << "code image resolution : " << img.cols << "x" << img.rows << endl;
      uchar* p;
      for (int i = 0; i < img.rows; i++ ){
        float avg=0;
        p=img.ptr<uchar>(i);
        for (int j = 0; j < img.cols; j++ ){
          avg+=p[j] / 255.;
        }
        avg/=img.cols;
        svgInterp.coeff.push_back(avg);
      }
      irisDetector.newCode = false;

      TTValue v;
      for (int i = 0; i<svgInterp.coeff.size(); i++){
        v.push_back(svgInterp.coeff[i]);
      }
      jamoma.mDrawingCoeffParameter.set("value", v);
      svgInterp.dirtyFlag = true;
    }
  }
}

void gorgone::draw()
{
  //vidGrabber.draw(0,0);
  drawMat(frame,0,0);
  if ( svgInterp.updateBool() ){
    TTValue x,y;
    ofPolyline line = svgInterp.interpolatedLine;
    ofLogNotice("gorgone") << "update drawing with " << line.size() << "points" << endl;
    for (int i=0; i<line.size(); i++){
      x.push_back(line[i].x);
      y.push_back(line[i].y);
    }

    jamoma.mDrawingShapeXReturn.set("value", x);
    jamoma.mDrawingShapeYReturn.set("value", y);
  }
  if ( bTracking )
    irisDetector.drawEyes();
  if ( bDisplaying )
    svgInterp.draw();
}

void gorgone::keyPressed(int key)
{
  ofLogVerbose("gorgone") << "keypressed : " << key << endl;
  switch (key){
    case 's':
      irisDetector.save();
      break;
    case ' ':
      irisDetector.reset();
      break;
    case 'c':
      bComputeCode=true;
      break;
    case 'm':
      bMotion = !bMotion;
      break;
    case 't':
      bTracking = !bTracking;
      if ( bTracking ) irisDetector.reset();
#ifdef TARGET_RASPBERRY_PI
      if ( bTracking ) vidGrabber.led.switchOnIR();
      else vidGrabber.led.switchOffIR();
#endif
      break;
    case 'd':
      bDisplaying = !bDisplaying;
      break;
#ifdef TARGET_RASPBERRY_PI
    case 'i':
      vidGrabber.led.switchOnIR();
      break;
    case 'o':
      vidGrabber.led.switchOffIR();
      break;
    case 'w':
      vidGrabber.led.switchOnWhite();
      break;
    case 'x':
      vidGrabber.led.switchOffWhite();
      break;
#endif
    case 357 : // arrow up
      svgInterp.selectedId = counter++;
      break;
    case 359: // arrow down
      svgInterp.selectedId = counter--;
      break;
    default :
      break;
  }
}

void gorgone::messageReceived(ofMessage& message)
{
}

void gorgone::parseCmdLineOptions(){
  vector<string> keys = ofxArgParser::allKeys();
  for (int i = 0; i < keys.size(); i++) {
    if ( keys[i] == "f" )   filename   = ofxArgParser::getValue(keys[i]);
    else if ( keys[i] == "name" ) appName =  ofxArgParser::getValue(keys[i]);
    else if ( keys[i] == "masterIp" ) masterIp =  ofxArgParser::getValue(keys[i]);
    else if ( keys[i] == "verbose" ) { // vebose level, value : 0..5, default 1 (OF_LOG_NOTICE)
      int logLevel;
      istringstream( ofxArgParser::getValue(keys[i]) ) >> logLevel;
      ofSetLogLevel((ofLogLevel) logLevel);
    }

    ofLogNotice("gorgone") << "key: " << keys[i] << ", value: " << ofxArgParser::getValue(keys[i]) << endl;
  }
}

void gorgone::setPwm(float pc){
#ifdef TARGET_RASPBERRY_PI
  ofstream file;
  file.open("/dev/servoblaster", ios::in);
  file << "0=" << pc << "%" << endl;
  file.close();
#endif
}
<commit_msg>use /tracking/iriscode to return computed coefficient from iriscode<commit_after>#include "gorgone.h"
using namespace cv;
using namespace ofxCv;
int accum = 0;

void gorgone::setup()
{
  ofSetLogLevel(OF_LOG_NOTICE);
  masterIp = "Mac-Pro-de-10-52.local";
  appName = "gorgone-1";
  parseCmdLineOptions();
  vidGrabber.setup(filename);
  svgInterp.setup();
  jamoma.setup((void*) this, appName, masterIp);
  motionDetector.setup(&jamoma);
  irisDetector.setJamomaRef(&jamoma);
  counter = 0;
}

void gorgone::exit(){
  setPwm(0);
#ifdef TARGET_RASPBERRY_PI
  vidGrabber.led.switchOffIR();
#endif
}

void gorgone::update()
{
  ofLogVerbose("gorgone") << ofGetFrameRate() << " fps" << endl;

  vidGrabber.update();

  if ( vidGrabber.isFrameNew() ){
    frame = vidGrabber.getFrame();

    if ( bMotion ){
      motionDetector.update(frame);
    }

    if( bTracking ){

      if ( frame.cols == 0 ) return;

      cv::Mat gray;
      if ( frame.channels() == 1 ){
        gray = frame.clone();
      } else {
        cv::cvtColor(frame, gray, CV_RGB2GRAY);
      }

      ofLogVerbose("gorgone") << "new frame to process : " << gray.cols << "x" << gray.rows << endl;

      irisDetector.updateBool(gray);
    }
  }

  if (bComputeCode) {
    irisDetector.computeCode();
    bComputeCode=false;
    jamoma.mComputeIrisCodeParameter.set("value", bComputeCode);

/*
// desactivated because Max doesn't handle list longer than 256 item, yes this still happens in 2015...
    TTValue v;
    Mat code = irisDetector.getIrisCode();
    v.push_back(code.cols);
    v.push_back(code.rows);
    uchar* p;
    for (int i = 0; i < code.rows; i++ ){
      p=code.ptr<uchar>(i);
      for (int j = 0; j < code.cols; j++ ){
        v.push_back((int) p[j]);
      }
    }
    cout << "v size : " << v.size() << endl;
    jamoma.mTrackingIrisCodeReturn.set("value",v);
*/
  }

  Mat img = irisDetector.getIrisCode();
  if( bDisplaying && irisDetector.newCode && img.total() > 0 ) {

    if ( irisDetector.newCode ){
      svgInterp.coeff.clear();
      ofLogVerbose("gorgone") << "code image resolution : " << img.cols << "x" << img.rows << endl;
      uchar* p;
      for (int i = 0; i < img.rows; i++ ){
        float avg=0;
        p=img.ptr<uchar>(i);
        for (int j = 0; j < img.cols; j++ ){
          avg+=p[j] / 255.;
        }
        avg/=img.cols;
        svgInterp.coeff.push_back(avg);
      }
      irisDetector.newCode = false;

      TTValue v;
      for (int i = 0; i<svgInterp.coeff.size(); i++){
        v.push_back(svgInterp.coeff[i]);
      }
      jamoma.mTrackingIrisCodeReturn.set("value", v);
    }
  }
}

void gorgone::draw()
{
  //vidGrabber.draw(0,0);
  drawMat(frame,0,0);
  if ( svgInterp.updateBool() ){
    TTValue x,y;
    ofPolyline line = svgInterp.interpolatedLine;
    ofLogNotice("gorgone") << "update drawing with " << line.size() << "points" << endl;
    for (int i=0; i<line.size(); i++){
      x.push_back(line[i].x);
      y.push_back(line[i].y);
    }

    jamoma.mDrawingShapeXReturn.set("value", x);
    jamoma.mDrawingShapeYReturn.set("value", y);
  }
  if ( bTracking )
    irisDetector.drawEyes();
  if ( bDisplaying )
    svgInterp.draw();
}

void gorgone::keyPressed(int key)
{
  ofLogVerbose("gorgone") << "keypressed : " << key << endl;
  switch (key){
    case 's':
      irisDetector.save();
      break;
    case ' ':
      irisDetector.reset();
      break;
    case 'c':
      bComputeCode=true;
      break;
    case 'm':
      bMotion = !bMotion;
      break;
    case 't':
      bTracking = !bTracking;
      if ( bTracking ) irisDetector.reset();
#ifdef TARGET_RASPBERRY_PI
      if ( bTracking ) vidGrabber.led.switchOnIR();
      else vidGrabber.led.switchOffIR();
#endif
      break;
    case 'd':
      bDisplaying = !bDisplaying;
      break;
#ifdef TARGET_RASPBERRY_PI
    case 'i':
      vidGrabber.led.switchOnIR();
      break;
    case 'o':
      vidGrabber.led.switchOffIR();
      break;
    case 'w':
      vidGrabber.led.switchOnWhite();
      break;
    case 'x':
      vidGrabber.led.switchOffWhite();
      break;
#endif
    case 357 : // arrow up
      svgInterp.selectedId = counter++;
      break;
    case 359: // arrow down
      svgInterp.selectedId = counter--;
      break;
    default :
      break;
  }
}

void gorgone::messageReceived(ofMessage& message)
{
}

void gorgone::parseCmdLineOptions(){
  vector<string> keys = ofxArgParser::allKeys();
  for (int i = 0; i < keys.size(); i++) {
    if ( keys[i] == "f" )   filename   = ofxArgParser::getValue(keys[i]);
    else if ( keys[i] == "name" ) appName =  ofxArgParser::getValue(keys[i]);
    else if ( keys[i] == "masterIp" ) masterIp =  ofxArgParser::getValue(keys[i]);
    else if ( keys[i] == "verbose" ) { // vebose level, value : 0..5, default 1 (OF_LOG_NOTICE)
      int logLevel;
      istringstream( ofxArgParser::getValue(keys[i]) ) >> logLevel;
      ofSetLogLevel((ofLogLevel) logLevel);
    }

    ofLogNotice("gorgone") << "key: " << keys[i] << ", value: " << ofxArgParser::getValue(keys[i]) << endl;
  }
}

void gorgone::setPwm(float pc){
#ifdef TARGET_RASPBERRY_PI
  ofstream file;
  file.open("/dev/servoblaster", ios::in);
  file << "0=" << pc << "%" << endl;
  file.close();
#endif
}
<|endoftext|>


<commit_before>#include "redis_cli.h"

#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdarg.h>

#include "pink_define.h"
#include "pink_cli_socket.h"
#include "xdebug.h"

namespace pink {

enum REDIS_STATUS {
  REDIS_ERR = -1,
  REDIS_OK = 0,
  REDIS_HALF,
  REDIS_REPLY_STRING,
  REDIS_REPLY_ARRAY,
  REDIS_REPLY_INTEGER,
  REDIS_REPLY_NIL,
  REDIS_REPLY_STATUS,
  REDIS_REPLY_ERROR
};

RedisCli::RedisCli()
  : rbuf_size_(REDIS_MAX_MESSAGE),
    rbuf_pos_(0),
    rbuf_offset_(0),
    err_(REDIS_OK) {
      rbuf_ = (char *)malloc(sizeof(char) * rbuf_size_);
    }

RedisCli::~RedisCli() {
  free(rbuf_);
}

#if 0
void RedisCli::Init(int send_timeout, int recv_timeout, int connect_timeout) {
  if (send_timeout > 0) {
    cli_socket_->set_send_timeout(send_timeout);
  }
  if (recv_timeout > 0) {
    cli_socket_->set_recv_timeout(recv_timeout);
  }
  if (connect_timeout > 0) {
    cli_socket_->set_connect_timeout(connect_timeout);
  }
}
#endif

// We use passed-in send buffer here
Status RedisCli::Send(void *msg) {
  log_info("The Send function");
  Status s;

  std::string* storage = reinterpret_cast<std::string *>(msg);
  const char *wbuf = storage->data();
  size_t nleft = storage->size();
  int wbuf_pos = 0;

  ssize_t nwritten;

  while (nleft > 0) {
    if ((nwritten = write(fd(), wbuf + wbuf_pos, nleft)) <= 0) {
      if (errno == EINTR) {
        nwritten = 0;
        continue;
        // block will EAGAIN ?
      } else {
        s = Status::IOError(wbuf, "write context error");
        return s;
      }
    }

    nleft -= nwritten;
    wbuf_pos += nwritten;
  }

  return s;
}

// The result is useless
Status RedisCli::Recv(void *result) {
  log_info("The Recv function");

  if (GetReply() == REDIS_ERR) {
    return Status::IOError(std::string(strerror(errno)));
  }

  return Status::OK();
}

ssize_t RedisCli::BufferRead() {
  // memmove the remain chars to rbuf begin
  if (rbuf_pos_ > 0) {
    memmove(rbuf_, rbuf_ + rbuf_pos_, rbuf_offset_);
    rbuf_pos_ = 0;
  }

  ssize_t nread;

  while (true) {
    nread = read(fd(), rbuf_ + rbuf_offset_, rbuf_size_ - rbuf_offset_);

    if (nread == -1) {
      if (errno == EINTR) {
        continue;
      } else {
        log_info("read error, %s", strerror(errno));
        return -1;
      }
    } else if (nread == 0) {    // we consider read null an error
      err = REDIS_ERR;
      return -1;
    }

    rbuf_offset_ += nread;
    return nread;
  }
}

/* Find pointer to \r\n. */
static char *seekNewline(char *s, size_t len) {
  int pos = 0;
  int _len = len-1;

  /* Position should be < len-1 because the character at "pos" should be
   * followed by a \n. Note that strchr cannot be used because it doesn't
   * allow to search a limited length and the buffer that is being searched
   * might not have a trailing NULL character. */
  while (pos < _len) {
    while (pos < _len && s[pos] != '\r') pos++;
    if (s[pos] != '\r') {
      /* Not found. */
      return NULL;
    } else {
      if (s[pos+1] == '\n') {
        /* Found. */
        return s+pos;
      } else {
        /* Continue searching. */
        pos++;
      }
    }
  }
  return NULL;
}

int RedisCli::ProcessLineItem() {
  char *p;
  int len;

  if ((p = ReadLine(&len)) == NULL) {
    return REDIS_HALF;
  }

  std::string arg(p, len);
  argv_.push_back(arg);

  return REDIS_OK;
}

int RedisCli::GetReply() {
  int result = REDIS_OK;

  while (true) {
    // Should read again
    if (rbuf_offset_ == 0 || result == REDIS_HALF) {
      if ((result = BufferRead()) < 0) {
        return REDIS_ERR;
      }
    }

    // REDIS_HALF will read and parse again
    if ((result = GetReplyFromReader()) != REDIS_HALF)
      return result;
  }
}

char* RedisCli::ReadBytes(unsigned int bytes) {
  char *p = NULL;
  if (rbuf_offset_ >= bytes) {
    p = rbuf_ + rbuf_pos_;
    rbuf_pos_ += bytes;
    rbuf_offset_ -= bytes;
  }
  return p;
}

char *RedisCli::ReadLine(int *_len) {
  char *p, *s;
  int len;

  p = rbuf_ + rbuf_pos_;
  s = seekNewline(rbuf_ + rbuf_pos_, rbuf_offset_);
  if (s != NULL) {
    len = s - (rbuf_ + rbuf_pos_);
    rbuf_pos_ += len + 2; /* skip \r\n */
    rbuf_offset_ -= len + 2;
    if (_len) *_len = len;
    return p;
  }
  return NULL;
}

int RedisCli::GetReplyFromReader() {
  if (err_) {
    return REDIS_ERR;
  }

  if (rbuf_offset_ == 0) {
    return REDIS_HALF;
  }

  char *p;
  if ((p = ReadBytes(1)) == NULL) {
    return REDIS_HALF;
  }

  int type;
  // Check reply type
  switch (*p) {
    case '-':
      type = REDIS_REPLY_ERROR;
      break;
    case '+':
      type = REDIS_REPLY_STATUS;
      break;
    case ':':
      type = REDIS_REPLY_INTEGER;
      break;
    case '$':
      type = REDIS_REPLY_STRING;
      break;
    case '*':
      type = REDIS_REPLY_ARRAY;
      break;
    default:
      return REDIS_ERR;
  }

  switch(type) {
    case REDIS_REPLY_ERROR:
    case REDIS_REPLY_STATUS:
    case REDIS_REPLY_INTEGER:
      return ProcessLineItem();
    case REDIS_REPLY_STRING:
      // need processBulkItem();
    case REDIS_REPLY_ARRAY:
      // need processMultiBulkItem();
    default:
      return REDIS_ERR; // Avoid warning.
  }
}

// Calculate the number of bytes needed to represent an integer as string.
static int intlen(int i) {
  int len = 0;
  if (i < 0) {
    len++;
    i = -i;
  }
  do {
    len++;
    i /= 10;
  } while(i);
  return len;
}

// Helper that calculates the bulk length given a certain string length.
static size_t bulklen(size_t len) {
  return 1 + intlen(len) + 2 + len + 2;
}

int redisvFormatCommand(std::string *cmd, const char *format, va_list ap) {
  const char *c = format;
  std::string curarg;
  char buf[REDIS_MAX_MESSAGE];
  std::vector<std::string> args;
  int touched = 0; /* was the current argument touched? */
  size_t totlen = 0;

  while (*c != '\0') {
    if (*c != '%' || c[1] == '\0') {
      if (*c == ' ') {
        if (touched) {
          args.push_back(curarg);
          totlen += bulklen(curarg.size());
          curarg.clear();
          touched = 0;
        }
      } else {
        curarg.append(c, 1);
        touched = 1;
      }
    } else {
      char *arg;
      size_t size;

      switch (c[1]) {
        case 's':
          arg = va_arg(ap, char*);
          size = strlen(arg);
          if (size > 0) {
            curarg.append(arg, size);
          }
          break;
        case 'b':
          arg = va_arg(ap, char*);
          size = va_arg(ap, size_t);
          if (size > 0) {
            curarg.append(arg, size);
          }
          break;
        case '%':
          curarg.append(arg, size);
          break;
        default:
          /* Try to detect printf format */
          {
            static const char intfmts[] = "diouxX";
            char _format[16];
            const char *_p = c+1;
            size_t _l = 0;
            va_list _cpy;
            bool fmt_valid = false;

            /* Flags */
            if (*_p != '\0' && *_p == '#') _p++;
            if (*_p != '\0' && *_p == '0') _p++;
            if (*_p != '\0' && *_p == '-') _p++;
            if (*_p != '\0' && *_p == ' ') _p++;
            if (*_p != '\0' && *_p == '+') _p++;

            /* Field width */
            while (*_p != '\0' && isdigit(*_p)) _p++;

            /* Precision */
            if (*_p == '.') {
              _p++;
              while (*_p != '\0' && isdigit(*_p)) _p++;
            }

            /* Copy va_list before consuming with va_arg */
            va_copy(_cpy, ap);

            if (strchr(intfmts, *_p) != NULL) {       /* Integer conversion (without modifiers) */
              va_arg(ap,int);
              fmt_valid = true;
            } else if (strchr("eEfFgGaA",*_p) != NULL) { /* Double conversion (without modifiers) */
              va_arg(ap, double);
              fmt_valid = true;
            } else if (_p[0] == 'h' && _p[1] == 'h') {    /* Size: char */
              _p += 2;
              if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                va_arg(ap,int); /* char gets promoted to int */
                fmt_valid = true;
              }
            } else if (_p[0] == 'h') {                /* Size: short */
              _p += 1;
              if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                va_arg(ap,int); /* short gets promoted to int */
                fmt_valid = true;
              }
            } else if (_p[0] == 'l' && _p[1] == 'l') { /* Size: long long */
              _p += 2;
              if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                va_arg(ap, long long);
                fmt_valid = true;
              }
            } else if (_p[0] == 'l') {           /* Size: long */
              _p += 1;
              if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                va_arg(ap,long);
                fmt_valid = true;
              }
            }

            if (!fmt_valid) {
              va_end(_cpy);
              return REDIS_ERR;
            }

            _l = (_p + 1) - c;
            if (_l < sizeof(_format) - 2) {
              memcpy(_format, c, _l);
              _format[_l] = '\0';

              int n = vsnprintf (buf, REDIS_MAX_MESSAGE, _format, _cpy);
              curarg.append(buf, n);

              /* Update current position (note: outer blocks
               * increment c twice so compensate here) */
              c = _p - 1;
            }

            va_end(_cpy);
            break;
          }
      }

      if (curarg.empty()) {
        return REDIS_ERR;
      }

      touched = 1;
      c++;
    }
    c++;
  }

  /* Add the last argument if needed */
  if (touched) {
    args.push_back(curarg);
    totlen += bulklen(curarg.size());
  }

  /* Add bytes needed to hold multi bulk count */
  totlen += 1 + intlen(args.size()) + 2;

  /* Build the command at protocol level */
  cmd->clear();
  cmd->reserve(totlen);

  cmd->append(1, '*');
  cmd->append(std::to_string(args.size()));
  cmd->append("\r\n");
  for (size_t i = 0; i < args.size(); i++) {
    cmd->append(1, '$');
    cmd->append(std::to_string(args[i].size()));
    cmd->append("\r\n");
    cmd->append(args[i]);
    cmd->append("\r\n");
  }
  assert(cmd->size() == totlen);

  return totlen;
}

int redisvAppendCommand(std::string *cmd, const char *format, va_list ap) {
  int len = redisvFormatCommand(cmd, format, ap);
  if (len == -1) {
    return REDIS_ERR;
  }

  return REDIS_OK;
}

int RedisCli::SerializeCommand(std::string *cmd, const char *format, ...) {
  va_list ap;
  va_start(ap, format);
  int result = redisvAppendCommand(cmd, format, ap);
  va_end(ap);
  return result;
}

};  // namespace pink
<commit_msg>fix wrong commit<commit_after>#include "redis_cli.h"

#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdarg.h>

#include "pink_define.h"
#include "pink_cli_socket.h"
#include "xdebug.h"

namespace pink {

enum REDIS_STATUS {
  REDIS_ERR = -1,
  REDIS_OK = 0,
  REDIS_HALF,
  REDIS_REPLY_STRING,
  REDIS_REPLY_ARRAY,
  REDIS_REPLY_INTEGER,
  REDIS_REPLY_NIL,
  REDIS_REPLY_STATUS,
  REDIS_REPLY_ERROR
};

RedisCli::RedisCli()
  : rbuf_size_(REDIS_MAX_MESSAGE),
    rbuf_pos_(0),
    rbuf_offset_(0),
    err_(REDIS_OK) {
      rbuf_ = (char *)malloc(sizeof(char) * rbuf_size_);
    }

RedisCli::~RedisCli() {
  free(rbuf_);
}

#if 0
void RedisCli::Init(int send_timeout, int recv_timeout, int connect_timeout) {
  if (send_timeout > 0) {
    cli_socket_->set_send_timeout(send_timeout);
  }
  if (recv_timeout > 0) {
    cli_socket_->set_recv_timeout(recv_timeout);
  }
  if (connect_timeout > 0) {
    cli_socket_->set_connect_timeout(connect_timeout);
  }
}
#endif

// We use passed-in send buffer here
Status RedisCli::Send(void *msg) {
  log_info("The Send function");
  Status s;

  std::string* storage = reinterpret_cast<std::string *>(msg);
  const char *wbuf = storage->data();
  size_t nleft = storage->size();
  int wbuf_pos = 0;

  ssize_t nwritten;

  while (nleft > 0) {
    if ((nwritten = write(fd(), wbuf + wbuf_pos, nleft)) <= 0) {
      if (errno == EINTR) {
        nwritten = 0;
        continue;
        // block will EAGAIN ?
      } else {
        s = Status::IOError(wbuf, "write context error");
        return s;
      }
    }

    nleft -= nwritten;
    wbuf_pos += nwritten;
  }

  return s;
}

// The result is useless
Status RedisCli::Recv(void *result) {
  log_info("The Recv function");

  if (GetReply() == REDIS_ERR) {
    return Status::IOError(std::string(strerror(errno)));
  }

  return Status::OK();
}

ssize_t RedisCli::BufferRead() {
  // memmove the remain chars to rbuf begin
  if (rbuf_pos_ > 0) {
    memmove(rbuf_, rbuf_ + rbuf_pos_, rbuf_offset_);
    rbuf_pos_ = 0;
  }

  ssize_t nread;

  while (true) {
    nread = read(fd(), rbuf_ + rbuf_offset_, rbuf_size_ - rbuf_offset_);

    if (nread == -1) {
      if (errno == EINTR) {
        continue;
      } else {
        log_info("read error, %s", strerror(errno));
        return -1;
      }
    } else if (nread == 0) {    // we consider read null an error
      err_ = REDIS_ERR;
      return -1;
    }

    rbuf_offset_ += nread;
    return nread;
  }
}

/* Find pointer to \r\n. */
static char *seekNewline(char *s, size_t len) {
  int pos = 0;
  int _len = len-1;

  /* Position should be < len-1 because the character at "pos" should be
   * followed by a \n. Note that strchr cannot be used because it doesn't
   * allow to search a limited length and the buffer that is being searched
   * might not have a trailing NULL character. */
  while (pos < _len) {
    while (pos < _len && s[pos] != '\r') pos++;
    if (s[pos] != '\r') {
      /* Not found. */
      return NULL;
    } else {
      if (s[pos+1] == '\n') {
        /* Found. */
        return s+pos;
      } else {
        /* Continue searching. */
        pos++;
      }
    }
  }
  return NULL;
}

int RedisCli::ProcessLineItem() {
  char *p;
  int len;

  if ((p = ReadLine(&len)) == NULL) {
    return REDIS_HALF;
  }

  std::string arg(p, len);
  argv_.push_back(arg);

  return REDIS_OK;
}

int RedisCli::GetReply() {
  int result = REDIS_OK;

  while (true) {
    // Should read again
    if (rbuf_offset_ == 0 || result == REDIS_HALF) {
      if ((result = BufferRead()) < 0) {
        return REDIS_ERR;
      }
    }

    // REDIS_HALF will read and parse again
    if ((result = GetReplyFromReader()) != REDIS_HALF)
      return result;
  }
}

char* RedisCli::ReadBytes(unsigned int bytes) {
  char *p = NULL;
  if (rbuf_offset_ >= bytes) {
    p = rbuf_ + rbuf_pos_;
    rbuf_pos_ += bytes;
    rbuf_offset_ -= bytes;
  }
  return p;
}

char *RedisCli::ReadLine(int *_len) {
  char *p, *s;
  int len;

  p = rbuf_ + rbuf_pos_;
  s = seekNewline(rbuf_ + rbuf_pos_, rbuf_offset_);
  if (s != NULL) {
    len = s - (rbuf_ + rbuf_pos_);
    rbuf_pos_ += len + 2; /* skip \r\n */
    rbuf_offset_ -= len + 2;
    if (_len) *_len = len;
    return p;
  }
  return NULL;
}

int RedisCli::GetReplyFromReader() {
  if (err_) {
    return REDIS_ERR;
  }

  if (rbuf_offset_ == 0) {
    return REDIS_HALF;
  }

  char *p;
  if ((p = ReadBytes(1)) == NULL) {
    return REDIS_HALF;
  }

  int type;
  // Check reply type
  switch (*p) {
    case '-':
      type = REDIS_REPLY_ERROR;
      break;
    case '+':
      type = REDIS_REPLY_STATUS;
      break;
    case ':':
      type = REDIS_REPLY_INTEGER;
      break;
    case '$':
      type = REDIS_REPLY_STRING;
      break;
    case '*':
      type = REDIS_REPLY_ARRAY;
      break;
    default:
      return REDIS_ERR;
  }

  switch(type) {
    case REDIS_REPLY_ERROR:
    case REDIS_REPLY_STATUS:
    case REDIS_REPLY_INTEGER:
      return ProcessLineItem();
    case REDIS_REPLY_STRING:
      // need processBulkItem();
    case REDIS_REPLY_ARRAY:
      // need processMultiBulkItem();
    default:
      return REDIS_ERR; // Avoid warning.
  }
}

// Calculate the number of bytes needed to represent an integer as string.
static int intlen(int i) {
  int len = 0;
  if (i < 0) {
    len++;
    i = -i;
  }
  do {
    len++;
    i /= 10;
  } while(i);
  return len;
}

// Helper that calculates the bulk length given a certain string length.
static size_t bulklen(size_t len) {
  return 1 + intlen(len) + 2 + len + 2;
}

int redisvFormatCommand(std::string *cmd, const char *format, va_list ap) {
  const char *c = format;
  std::string curarg;
  char buf[REDIS_MAX_MESSAGE];
  std::vector<std::string> args;
  int touched = 0; /* was the current argument touched? */
  size_t totlen = 0;

  while (*c != '\0') {
    if (*c != '%' || c[1] == '\0') {
      if (*c == ' ') {
        if (touched) {
          args.push_back(curarg);
          totlen += bulklen(curarg.size());
          curarg.clear();
          touched = 0;
        }
      } else {
        curarg.append(c, 1);
        touched = 1;
      }
    } else {
      char *arg;
      size_t size;

      switch (c[1]) {
        case 's':
          arg = va_arg(ap, char*);
          size = strlen(arg);
          if (size > 0) {
            curarg.append(arg, size);
          }
          break;
        case 'b':
          arg = va_arg(ap, char*);
          size = va_arg(ap, size_t);
          if (size > 0) {
            curarg.append(arg, size);
          }
          break;
        case '%':
          curarg.append(arg, size);
          break;
        default:
          /* Try to detect printf format */
          {
            static const char intfmts[] = "diouxX";
            char _format[16];
            const char *_p = c+1;
            size_t _l = 0;
            va_list _cpy;
            bool fmt_valid = false;

            /* Flags */
            if (*_p != '\0' && *_p == '#') _p++;
            if (*_p != '\0' && *_p == '0') _p++;
            if (*_p != '\0' && *_p == '-') _p++;
            if (*_p != '\0' && *_p == ' ') _p++;
            if (*_p != '\0' && *_p == '+') _p++;

            /* Field width */
            while (*_p != '\0' && isdigit(*_p)) _p++;

            /* Precision */
            if (*_p == '.') {
              _p++;
              while (*_p != '\0' && isdigit(*_p)) _p++;
            }

            /* Copy va_list before consuming with va_arg */
            va_copy(_cpy, ap);

            if (strchr(intfmts, *_p) != NULL) {       /* Integer conversion (without modifiers) */
              va_arg(ap,int);
              fmt_valid = true;
            } else if (strchr("eEfFgGaA",*_p) != NULL) { /* Double conversion (without modifiers) */
              va_arg(ap, double);
              fmt_valid = true;
            } else if (_p[0] == 'h' && _p[1] == 'h') {    /* Size: char */
              _p += 2;
              if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                va_arg(ap,int); /* char gets promoted to int */
                fmt_valid = true;
              }
            } else if (_p[0] == 'h') {                /* Size: short */
              _p += 1;
              if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                va_arg(ap,int); /* short gets promoted to int */
                fmt_valid = true;
              }
            } else if (_p[0] == 'l' && _p[1] == 'l') { /* Size: long long */
              _p += 2;
              if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                va_arg(ap, long long);
                fmt_valid = true;
              }
            } else if (_p[0] == 'l') {           /* Size: long */
              _p += 1;
              if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                va_arg(ap,long);
                fmt_valid = true;
              }
            }

            if (!fmt_valid) {
              va_end(_cpy);
              return REDIS_ERR;
            }

            _l = (_p + 1) - c;
            if (_l < sizeof(_format) - 2) {
              memcpy(_format, c, _l);
              _format[_l] = '\0';

              int n = vsnprintf (buf, REDIS_MAX_MESSAGE, _format, _cpy);
              curarg.append(buf, n);

              /* Update current position (note: outer blocks
               * increment c twice so compensate here) */
              c = _p - 1;
            }

            va_end(_cpy);
            break;
          }
      }

      if (curarg.empty()) {
        return REDIS_ERR;
      }

      touched = 1;
      c++;
    }
    c++;
  }

  /* Add the last argument if needed */
  if (touched) {
    args.push_back(curarg);
    totlen += bulklen(curarg.size());
  }

  /* Add bytes needed to hold multi bulk count */
  totlen += 1 + intlen(args.size()) + 2;

  /* Build the command at protocol level */
  cmd->clear();
  cmd->reserve(totlen);

  cmd->append(1, '*');
  cmd->append(std::to_string(args.size()));
  cmd->append("\r\n");
  for (size_t i = 0; i < args.size(); i++) {
    cmd->append(1, '$');
    cmd->append(std::to_string(args[i].size()));
    cmd->append("\r\n");
    cmd->append(args[i]);
    cmd->append("\r\n");
  }
  assert(cmd->size() == totlen);

  return totlen;
}

int redisvAppendCommand(std::string *cmd, const char *format, va_list ap) {
  int len = redisvFormatCommand(cmd, format, ap);
  if (len == -1) {
    return REDIS_ERR;
  }

  return REDIS_OK;
}

int RedisCli::SerializeCommand(std::string *cmd, const char *format, ...) {
  va_list ap;
  va_start(ap, format);
  int result = redisvAppendCommand(cmd, format, ap);
  va_end(ap);
  return result;
}

};  // namespace pink
<|endoftext|>


<commit_before>#include "grammar.h"

#include "ast.h"
#include "token.h"
#include "parser.h"
#include "grammar.h"
#include "exceptions.h"

#include <map>
#include <boost/regex.hpp>
#include <iostream>

namespace sota {

    // scanners
    size_t RegexScanner(Symbol *symbol, const std::string &source, size_t index) {
        auto pattern = symbol->pattern;
        boost::smatch matches;
        boost::regex re("^" + pattern);
        if (boost::regex_search(source, matches, re)) {
            auto match = matches[0];
            //std::cout << "re pattern: " << pattern << " matched: " << match << std::endl;
            return index + match.length();
        }
        return index;
    }

    size_t LiteralScanner(Symbol *symbol, const std::string &source, size_t index) {
        auto pattern = symbol->pattern;
        auto patternSize = pattern.size();
        if (source.size() >= patternSize && source.compare(0, patternSize, pattern) == 0) {
            //std::cout << "lit pattern: " << pattern << " matched: " << pattern << std::endl;
            return index + patternSize;
        }
        return index;
    }

    // nud parsing functions
    Ast * NotImplementedNud(Parser *parser, Token *token) {
        throw SotaNotImplemented("nud: NotImplemented; this shouldn't be called!");
    }
    Ast * EndOfFileNud(Parser *parser, Token *token) {
        std::cout << "EndOfFileNud" << std::endl;
        return nullptr;
    }
    Ast * WhiteSpaceNud(Parser *parser, Token *token) {
        std::cout << "WhiteSpaceNud" << std::endl;
        return nullptr;
    }
    Ast * NumberNud(Parser *parser, Token *token) {
        std::cout << "NumberNud" << std::endl;
        return nullptr;
    }
    Ast * IdentifierNud(Parser *parser, Token *token) {
        std::cout << "IdentifierNud" << std::endl;
        Ast *ast = new IdentifierAst(token->Value());
        return ast;
    }
    Ast * PrefixOperatorNud(Parser *parser, Token *token) {
        std::cout << "PrefixOperatorNud" << std::endl;
        return nullptr;
    }

    // led parsing functions
    Ast * NotImplementedLed(Parser *parser, Ast *left, Token *token) {
        throw SotaNotImplemented("led: NotImplemented; this shouldn't be called!");
    }
    Ast * InfixOperatorLed(Parser *parser, Ast *left, Token *token) {
        std::cout << "InfixOperatorLed" << std::endl;
        Ast *right = parser->Parse(token->symbol.lbp);
        return new InfixOperatorAst(token, left, right);
    }
    Ast * PostfixOperatorNud(Parser *parser, Ast *left, Token *token) {
        std::cout << "PostfixOperatorLed" << std::endl;
        return nullptr;
    }

    #define T(k,p,s,n,l,b) std::make_pair(SymbolType::k, new Symbol(SymbolType::k,p,s,n,l,b) ),
    std::map<size_t, Symbol *> Type2Symbol {
        SYMBOLS
    };
    #undef T

    #define T(k,p,s,n,l,b) std::make_pair(#k, Type2Symbol[SymbolType::k]),
    std::map<std::string, Symbol *> Name2Symbol {
        SYMBOLS
    };
    #undef T

    #define T(k,p,s,n,l,b) std::make_pair(SymbolType::k, #k),
    std::map<size_t, std::string> Type2Name {
        SYMBOLS
    };
    #undef T

    #define T(k,p,s,n,l,b) std::make_pair(#k, SymbolType::k),
    std::map<std::string, size_t> Name2Type {
        SYMBOLS
    };
    #undef T

}
<commit_msg>Added identifier and number ast implementations... -sai<commit_after>#include "grammar.h"

#include "ast.h"
#include "token.h"
#include "parser.h"
#include "grammar.h"
#include "exceptions.h"

#include <map>
#include <boost/regex.hpp>
#include <iostream>

namespace sota {

    // scanners
    size_t RegexScanner(Symbol *symbol, const std::string &source, size_t index) {
        auto pattern = symbol->pattern;
        boost::smatch matches;
        boost::regex re("^" + pattern);
        if (boost::regex_search(source, matches, re)) {
            auto match = matches[0];
            //std::cout << "re pattern: " << pattern << " matched: " << match << std::endl;
            return index + match.length();
        }
        return index;
    }

    size_t LiteralScanner(Symbol *symbol, const std::string &source, size_t index) {
        auto pattern = symbol->pattern;
        auto patternSize = pattern.size();
        if (source.size() >= patternSize && source.compare(0, patternSize, pattern) == 0) {
            //std::cout << "lit pattern: " << pattern << " matched: " << pattern << std::endl;
            return index + patternSize;
        }
        return index;
    }

    // nud parsing functions
    Ast * NotImplementedNud(Parser *parser, Token *token) {
        throw SotaNotImplemented("nud: NotImplemented; this shouldn't be called!");
    }
    Ast * EndOfFileNud(Parser *parser, Token *token) {
        std::cout << "EndOfFileNud" << std::endl;
        return nullptr;
    }
    Ast * WhiteSpaceNud(Parser *parser, Token *token) {
        std::cout << "WhiteSpaceNud" << std::endl;
        return nullptr;
    }
    Ast * NumberNud(Parser *parser, Token *token) {
        std::cout << "NumberNud" << std::endl;
        return new NumberAst(token->Value());
    }
    Ast * IdentifierNud(Parser *parser, Token *token) {
        std::cout << "IdentifierNud" << std::endl;
        return new IdentifierAst(token->Value());
    }
    Ast * PrefixOperatorNud(Parser *parser, Token *token) {
        std::cout << "PrefixOperatorNud" << std::endl;
        return nullptr;
    }

    // led parsing functions
    Ast * NotImplementedLed(Parser *parser, Ast *left, Token *token) {
        throw SotaNotImplemented("led: NotImplemented; this shouldn't be called!");
    }
    Ast * InfixOperatorLed(Parser *parser, Ast *left, Token *token) {
        std::cout << "InfixOperatorLed" << std::endl;
        Ast *right = parser->Parse(token->symbol.lbp);
        return new InfixOperatorAst(token, left, right);
    }
    Ast * PostfixOperatorNud(Parser *parser, Ast *left, Token *token) {
        std::cout << "PostfixOperatorLed" << std::endl;
        return nullptr;
    }

    #define T(k,p,s,n,l,b) std::make_pair(SymbolType::k, new Symbol(SymbolType::k,p,s,n,l,b) ),
    std::map<size_t, Symbol *> Type2Symbol {
        SYMBOLS
    };
    #undef T

    #define T(k,p,s,n,l,b) std::make_pair(#k, Type2Symbol[SymbolType::k]),
    std::map<std::string, Symbol *> Name2Symbol {
        SYMBOLS
    };
    #undef T

    #define T(k,p,s,n,l,b) std::make_pair(SymbolType::k, #k),
    std::map<size_t, std::string> Type2Name {
        SYMBOLS
    };
    #undef T

    #define T(k,p,s,n,l,b) std::make_pair(#k, SymbolType::k),
    std::map<std::string, size_t> Name2Type {
        SYMBOLS
    };
    #undef T

}
<|endoftext|>


<commit_before>#include "renderer.h"

Renderer::Renderer() {
    // Set color and depth clear value
    glClearDepth(1.f);
    glClearColor(0.f, 0.f, 0.f, 0.f);

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

    // Setup a perspective projection
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90.f, 1.f, 1.f, 500.f);

    // Lighting test junk
    GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; 				// Ambient Light Values ( NEW )
    GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };				 // Diffuse Light Values ( NEW )
    GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };				 // Light Position ( NEW )
    glShadeModel(GL_SMOOTH);						// Enable Smooth Shading
    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
    glEnable(GL_LIGHTING);
}

void drawCube() {
    glBegin(GL_QUADS);

		// Front Face
		glNormal3f( 0.0f, 0.0f, 1.0f);					// Normal Pointing Towards Viewer
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);	// Point 1 (Front)
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);	// Point 2 (Front)
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);	// Point 3 (Front)
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);	// Point 4 (Front)
		// Back Face
		glNormal3f( 0.0f, 0.0f,-1.0f);					// Normal Pointing Away From Viewer
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);	// Point 1 (Back)
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);	// Point 2 (Back)
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);	// Point 3 (Back)
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);	// Point 4 (Back)
		// Top Face
		glNormal3f( 0.0f, 1.0f, 0.0f);					// Normal Pointing Up
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);	// Point 1 (Top)
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);	// Point 2 (Top)
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);	// Point 3 (Top)
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);	// Point 4 (Top)
		// Bottom Face
		glNormal3f( 0.0f,-1.0f, 0.0f);					// Normal Pointing Down
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);	// Point 1 (Bottom)
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);	// Point 2 (Bottom)
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);	// Point 3 (Bottom)
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);	// Point 4 (Bottom)
		// Right face
		glNormal3f( 1.0f, 0.0f, 0.0f);					// Normal Pointing Right
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);	// Point 1 (Right)
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);	// Point 2 (Right)
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);	// Point 3 (Right)
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);	// Point 4 (Right)
		// Left Face
		glNormal3f(-1.0f, 0.0f, 0.0f);					// Normal Pointing Left
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);	// Point 1 (Left)
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);	// Point 2 (Left)
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);	// Point 3 (Left)
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);	// Point 4 (Left)
	glEnd();								// Done Drawing Quads
}

void Renderer::render(float Left, float Top, float Up) {

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

    glMatrixMode(GL_MODELVIEW);

    // Apply some transformations
    glLoadIdentity();
	  glTranslatef(-Left, -Up, -Top);				// Translate The Scene Based On Player Position
    glTranslatef(0.f, 0.f, -5.f);

    drawCube();

    // Apply some transformations
    glLoadIdentity();
	  glTranslatef(-Left, -Up, -Top);				// Translate The Scene Based On Player Position
    glTranslatef(2.f, 0.f, -5.f);

    drawCube();
}
<commit_msg>Render four test cubes<commit_after>#include "renderer.h"

Renderer::Renderer() {
    // Set color and depth clear value
    glClearDepth(1.f);
    glClearColor(0.f, 0.f, 0.f, 0.f);

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

    // Setup a perspective projection
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90.f, 1.f, 1.f, 500.f);

    // Lighting test junk
    GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; 				// Ambient Light Values ( NEW )
    GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };				 // Diffuse Light Values ( NEW )
    GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };				 // Light Position ( NEW )
    glShadeModel(GL_SMOOTH);						// Enable Smooth Shading
    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
    glEnable(GL_LIGHTING);
}

void drawCube(float x, float y, float z, float length) {

    // Apply some transformations
	  glPushMatrix();
    glTranslatef(x, y, z);
    glScalef(length, length, length);

    glBegin(GL_QUADS);

		// Front Face
		glNormal3f( 0.0f, 0.0f, 1.0f);					// Normal Pointing Towards Viewer
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);	// Point 1 (Front)
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);	// Point 2 (Front)
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);	// Point 3 (Front)
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);	// Point 4 (Front)
		// Back Face
		glNormal3f( 0.0f, 0.0f,-1.0f);					// Normal Pointing Away From Viewer
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);	// Point 1 (Back)
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);	// Point 2 (Back)
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);	// Point 3 (Back)
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);	// Point 4 (Back)
		// Top Face
		glNormal3f( 0.0f, 1.0f, 0.0f);					// Normal Pointing Up
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);	// Point 1 (Top)
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);	// Point 2 (Top)
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);	// Point 3 (Top)
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);	// Point 4 (Top)
		// Bottom Face
		glNormal3f( 0.0f,-1.0f, 0.0f);					// Normal Pointing Down
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);	// Point 1 (Bottom)
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);	// Point 2 (Bottom)
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);	// Point 3 (Bottom)
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);	// Point 4 (Bottom)
		// Right face
		glNormal3f( 1.0f, 0.0f, 0.0f);					// Normal Pointing Right
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);	// Point 1 (Right)
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);	// Point 2 (Right)
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);	// Point 3 (Right)
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);	// Point 4 (Right)
		// Left Face
		glNormal3f(-1.0f, 0.0f, 0.0f);					// Normal Pointing Left
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);	// Point 1 (Left)
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);	// Point 2 (Left)
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);	// Point 3 (Left)
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);	// Point 4 (Left)
	glEnd();								// Done Drawing Quads

	  glPopMatrix();
}

void Renderer::render(float Left, float Top, float Up) {

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

    glMatrixMode(GL_MODELVIEW);

    // Apply some transformations
    glLoadIdentity();
	  glTranslatef(-Left, -Up, -Top);				// Translate The Scene Based On Player Position

    drawCube(0.f, 0.f, -5.f, 1.f);
    drawCube(3.f, 0.f, -5.f, 1.f);
    drawCube(-2.f, 1.f, -4.f, 0.5f);
    drawCube(10.f, -10.f, -10.f, 5.f);
}
<|endoftext|>


<commit_before>// $Id: TGHtmlImage.cxx,v 1.2 2007/05/07 15:28:48 brun Exp $
// Author:  Valeriy Onuchin   03/05/2007

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/**************************************************************************

    HTML widget for xclass. Based on tkhtml 1.28
    Copyright (C) 1997-2000 D. Richard Hipp <drh@acm.org>
    Copyright (C) 2002-2003 Hector Peraza.

    This library 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.

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

**************************************************************************/

// Routines used for processing <IMG> markup

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

#include "TGHtml.h"
//#include <TGHtmlUri.h>
#include "TImage.h"
#include "TUrl.h"
#include "TSocket.h"
#include "TSystem.h"

//______________________________________________________________________________
TGHtmlImage::TGHtmlImage(TGHtml *htm, const char *url, const char *width,
                       const char *height)
{
   // ctor.

   fHtml = htm;
   fZUrl = StrDup(url);
   fZWidth = StrDup(width);
   fZHeight = StrDup(height);
   fImage = NULL;
   fPNext = NULL;
   fPList = NULL;
   fW = 0;
   fH = 0;
   fTimer = NULL;
}

//______________________________________________________________________________
TGHtmlImage::~TGHtmlImage()
{
   //  dtor.

   delete [] fZUrl;
   delete [] fZWidth;
   delete [] fZHeight;

   if (fImage) delete fImage;
   if (fTimer) delete fTimer;
}

//______________________________________________________________________________
int TGHtml::GetImageAlignment(TGHtmlElement *p)
{
   // Find the alignment for an image

   const char *z;
   int i;
   int result;

   static struct {
      const char *zName;
      int iValue;
   } aligns[] = {
      { "bottom",    IMAGE_ALIGN_Bottom    },
      { "baseline",  IMAGE_ALIGN_Bottom    },
      { "middle",    IMAGE_ALIGN_Middle    },
      { "top",       IMAGE_ALIGN_Top       },
      { "absbottom", IMAGE_ALIGN_AbsBottom },
      { "absmiddle", IMAGE_ALIGN_AbsMiddle },
      { "texttop",   IMAGE_ALIGN_TextTop   },
      { "left",      IMAGE_ALIGN_Left      },
      { "right",     IMAGE_ALIGN_Right     },
   };

   z = p->MarkupArg("align", 0);
   result = IMAGE_ALIGN_Bottom;
   if (z) {
      for (i = 0; i < int(sizeof(aligns) / sizeof(aligns[0])); i++) {
         if (strcasecmp(aligns[i].zName, z) == 0) {
            result = aligns[i].iValue;
            break;
         }
      }
   }
   return result;
}

//______________________________________________________________________________
void TGHtml::ImageChanged(TGHtmlImage *pImage, int newWidth, int newHeight)
{
   // This routine is called when an image changes. If the size of the
   // images changes, then we need to completely redo the layout. If
   // only the appearance changes, then this works like an expose event.
   //
   // pImage    - Pointer to an TGHtmlImage object
   // newWidth  - New width of the image
   // newHeight - New height of the image

   TGHtmlImageMarkup *pElem;

   if (pImage->fW != newWidth || pImage->fH != newHeight) {
      // We have to completely redo the layout after adjusting the size
      // of the images
      for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
         pElem->fW = newWidth;
         pElem->fH = newHeight;
      }
      fFlags |= RELAYOUT;
      pImage->fW = newWidth;
      pImage->fH = newHeight;
      RedrawEverything();
   } else {
#if 0
      for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
         pElem->fRedrawNeeded = 1;
      }
      fFlags |= REDRAW_IMAGES;
      ScheduleRedraw();
#else
      for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
         pElem->fRedrawNeeded = 1;
         DrawRegion(pElem->fX, pElem->fY - pElem->fAscent, pElem->fW, pElem->fH);
      }
#endif
   }
}

//______________________________________________________________________________
TGHtmlImage *TGHtml::GetImage(TGHtmlImageMarkup *p)
{
   // Given an <IMG> markup, find or create an appropriate TGHtmlImage
   // object and return a pointer to that object. NULL might be returned.

   const char *zWidth;
   const char *zHeight;
   const char *zSrc;
   TGHtmlImage *pImage;

   if (p->fType != Html_IMG) { CANT_HAPPEN; return 0; }

   zSrc = p->MarkupArg("src", 0);
   if (zSrc == 0) return 0;

   zSrc = ResolveUri(zSrc);
   if (zSrc == 0) return 0;

   zWidth = p->MarkupArg("width", "");
   zHeight = p->MarkupArg("height", "");

   //p->w = atoi(fZWidth);
   //p->h = atoi(zHeight);

   for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
      if (strcmp(pImage->fZUrl, zSrc) == 0
          &&  strcmp(pImage->fZWidth, zWidth) == 0
          &&  strcmp(pImage->fZHeight, zHeight) == 0) {
         delete [] zSrc;
         return pImage;
      }
   }

   TImage *img = LoadImage(zSrc, atoi(zWidth), atoi(zHeight));

   if (img) {
      pImage = new TGHtmlImage(this, zSrc, zWidth, zHeight);
      pImage->fImage = img;
    //if (img->IsAnimated()) {
    //  pImage->timer = new TTimer(this, img->GetAnimDelay());
    //}
      ImageChanged(pImage, img->GetWidth(), img->GetHeight());
      pImage->fPNext = fImageList;
      fImageList = pImage;
   } else {
      pImage = 0;
   }

   delete [] zSrc;

   return pImage;
}

//______________________________________________________________________________
static TImage *ReadRemoteImage(const char *url)
{
   // Temporary function to read remote pictures

   TImage *image = 0;
   FILE *tmp;
   char *buf;
   TUrl fUrl(url);

   TString msg = "GET ";
   msg += fUrl.GetProtocol();
   msg += "://";
   msg += fUrl.GetHost();
   msg += ":";
   msg += fUrl.GetPort();
   msg += "/";
   msg += fUrl.GetFile();
   msg += "\r\n";

   TString uri(url);
   if (!uri.BeginsWith("http://") || uri.EndsWith(".html"))
      return 0;
   TSocket s(fUrl.GetHost(), fUrl.GetPort());
   if (!s.IsValid())
      return 0;
   if (s.SendRaw(msg.Data(), msg.Length()) == -1)
      return 0;
   Int_t size = 1024*1024;
   buf = (char *)calloc(size, sizeof(char));
   if (!buf) return 0;
   if (s.RecvRaw(buf, size) == -1) {
      free(buf);
      return 0;
   }
   TString pathtmp = TString::Format("%s/%s", gSystem->TempDirectory(),
                                     gSystem->BaseName(url));
   tmp = fopen(pathtmp.Data(), "wb");
   if (!tmp) {
      free(buf);
      return 0;
   }
   fwrite(buf, sizeof(char), size, tmp);
   fclose(tmp);
   free(buf);
   image = TImage::Open(pathtmp.Data());
   if (image && !image->IsValid()) {
      delete image;
      image = 0;
   }
   gSystem->Unlink(pathtmp.Data());
   return image;
}

//______________________________________________________________________________
TImage *TGHtml::LoadImage(const char *url, int w, int h)
{
   // This is the default LoadImage() procedure. It just tries to load the
   // image from a file in the local filesystem.

   TImage *image = 0;

   //TGHtmlUri uri(url);

   TString uri(url);
   if (uri.BeginsWith("http://") && !uri.EndsWith(".html"))
      image = ReadRemoteImage(url);
   else
      image = TImage::Open(url);
   if (image) {
      if (!image->IsValid()) {
         delete image;
         image = 0;
         return 0;
      }
      if ((w > 0 && h > 0) && ((w != (int)image->GetWidth()) ||
          (h != (int)image->GetHeight()))) {
         image->Scale(w, h);
      }
   }
   return image;
}

//______________________________________________________________________________
const char *TGHtml::GetPctWidth(TGHtmlElement *p, char *opt, char *ret)
{
   // Return the height and width, converting to percent if required
   // ret must be at least 16 characters long

   int n, m, val;
   const char *tz, *z;
   TGHtmlElement *pElem = p;

   z = pElem->MarkupArg(opt, "");
   if (!strchr(z, '%')) return z;
   // coverity[secure_coding]
   if (!sscanf(z, "%d", &n)) return z;
   if (n < 0 || n > 100) return z;
   if (opt[0] == 'h') {
      val = fCanvas->GetHeight() * 100;
   } else {
      val = fCanvas->GetWidth() * 100;
   }
   if (!fInTd) {
      snprintf(ret, 15, "%d", val / n);
   } else {
      while (pElem && pElem->fType != Html_TD) pElem = pElem->fPPrev;
      if (!pElem) return z;
      tz = pElem->MarkupArg(opt, 0);
      // coverity[secure_coding]
      if (tz && !strchr(tz, '%') && sscanf(tz, "%d", &m)) {
         snprintf(ret, 15, "%d", m * 100 / n);
         return ret;
      }
      pElem = ((TGHtmlCell *)pElem)->fPTable;
      if (!pElem) return z;
      tz = pElem->MarkupArg(opt, 0);
      // coverity[secure_coding]
      if (tz && !strchr(tz, '%') && sscanf(tz, "%d", &m)) {
         snprintf(ret, 15, "%d", m * 100 / n);
         return ret;
      }
      return z;
   }
   return ret;
}

//______________________________________________________________________________
int TGHtml::GetImageAt(int x, int y)
{
   // This routine searchs for an image beneath the coordinates x,y
   // and returns the token number of the the image, or -1 if no
   // image found.

   TGHtmlBlock *pBlock;
   TGHtmlElement *pElem;
   //int n;

   for (pBlock = fFirstBlock; pBlock; pBlock = pBlock->fBNext) {
      if (pBlock->fTop > y || pBlock->fBottom < y ||
          pBlock->fLeft > x || pBlock->fRight < x) {
         continue;
      }
      for (pElem = pBlock->fPNext; pElem; pElem = pElem->fPNext) {
         if (pBlock->fBNext && pElem == pBlock->fBNext->fPNext) break;
         if (pElem->fType == Html_IMG) {
            return TokenNumber(pElem);
         }
      }
   }

   return -1;
}
<commit_msg>Fix coverity #36020 Dereference null return<commit_after>// $Id: TGHtmlImage.cxx,v 1.2 2007/05/07 15:28:48 brun Exp $
// Author:  Valeriy Onuchin   03/05/2007

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

/**************************************************************************

    HTML widget for xclass. Based on tkhtml 1.28
    Copyright (C) 1997-2000 D. Richard Hipp <drh@acm.org>
    Copyright (C) 2002-2003 Hector Peraza.

    This library 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.

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

**************************************************************************/

// Routines used for processing <IMG> markup

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

#include "TGHtml.h"
//#include <TGHtmlUri.h>
#include "TImage.h"
#include "TUrl.h"
#include "TSocket.h"
#include "TSystem.h"

//______________________________________________________________________________
TGHtmlImage::TGHtmlImage(TGHtml *htm, const char *url, const char *width,
                       const char *height)
{
   // ctor.

   fHtml = htm;
   fZUrl = StrDup(url);
   fZWidth = StrDup(width);
   fZHeight = StrDup(height);
   fImage = NULL;
   fPNext = NULL;
   fPList = NULL;
   fW = 0;
   fH = 0;
   fTimer = NULL;
}

//______________________________________________________________________________
TGHtmlImage::~TGHtmlImage()
{
   //  dtor.

   delete [] fZUrl;
   delete [] fZWidth;
   delete [] fZHeight;

   if (fImage) delete fImage;
   if (fTimer) delete fTimer;
}

//______________________________________________________________________________
int TGHtml::GetImageAlignment(TGHtmlElement *p)
{
   // Find the alignment for an image

   const char *z;
   int i;
   int result;

   static struct {
      const char *zName;
      int iValue;
   } aligns[] = {
      { "bottom",    IMAGE_ALIGN_Bottom    },
      { "baseline",  IMAGE_ALIGN_Bottom    },
      { "middle",    IMAGE_ALIGN_Middle    },
      { "top",       IMAGE_ALIGN_Top       },
      { "absbottom", IMAGE_ALIGN_AbsBottom },
      { "absmiddle", IMAGE_ALIGN_AbsMiddle },
      { "texttop",   IMAGE_ALIGN_TextTop   },
      { "left",      IMAGE_ALIGN_Left      },
      { "right",     IMAGE_ALIGN_Right     },
   };

   z = p->MarkupArg("align", 0);
   result = IMAGE_ALIGN_Bottom;
   if (z) {
      for (i = 0; i < int(sizeof(aligns) / sizeof(aligns[0])); i++) {
         if (strcasecmp(aligns[i].zName, z) == 0) {
            result = aligns[i].iValue;
            break;
         }
      }
   }
   return result;
}

//______________________________________________________________________________
void TGHtml::ImageChanged(TGHtmlImage *pImage, int newWidth, int newHeight)
{
   // This routine is called when an image changes. If the size of the
   // images changes, then we need to completely redo the layout. If
   // only the appearance changes, then this works like an expose event.
   //
   // pImage    - Pointer to an TGHtmlImage object
   // newWidth  - New width of the image
   // newHeight - New height of the image

   TGHtmlImageMarkup *pElem;

   if (pImage->fW != newWidth || pImage->fH != newHeight) {
      // We have to completely redo the layout after adjusting the size
      // of the images
      for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
         pElem->fW = newWidth;
         pElem->fH = newHeight;
      }
      fFlags |= RELAYOUT;
      pImage->fW = newWidth;
      pImage->fH = newHeight;
      RedrawEverything();
   } else {
#if 0
      for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
         pElem->fRedrawNeeded = 1;
      }
      fFlags |= REDRAW_IMAGES;
      ScheduleRedraw();
#else
      for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
         pElem->fRedrawNeeded = 1;
         DrawRegion(pElem->fX, pElem->fY - pElem->fAscent, pElem->fW, pElem->fH);
      }
#endif
   }
}

//______________________________________________________________________________
TGHtmlImage *TGHtml::GetImage(TGHtmlImageMarkup *p)
{
   // Given an <IMG> markup, find or create an appropriate TGHtmlImage
   // object and return a pointer to that object. NULL might be returned.

   const char *zWidth;
   const char *zHeight;
   const char *zSrc;
   TGHtmlImage *pImage;

   if (p->fType != Html_IMG) { CANT_HAPPEN; return 0; }

   zSrc = p->MarkupArg("src", 0);
   if (zSrc == 0) return 0;

   zSrc = ResolveUri(zSrc);
   if (zSrc == 0) return 0;

   zWidth = p->MarkupArg("width", "");
   zHeight = p->MarkupArg("height", "");

   //p->w = atoi(fZWidth);
   //p->h = atoi(zHeight);

   for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
      if (strcmp(pImage->fZUrl, zSrc) == 0
          &&  strcmp(pImage->fZWidth, zWidth) == 0
          &&  strcmp(pImage->fZHeight, zHeight) == 0) {
         delete [] zSrc;
         return pImage;
      }
   }

   TImage *img = LoadImage(zSrc, atoi(zWidth), atoi(zHeight));

   if (img) {
      pImage = new TGHtmlImage(this, zSrc, zWidth, zHeight);
      pImage->fImage = img;
    //if (img->IsAnimated()) {
    //  pImage->timer = new TTimer(this, img->GetAnimDelay());
    //}
      ImageChanged(pImage, img->GetWidth(), img->GetHeight());
      pImage->fPNext = fImageList;
      fImageList = pImage;
   } else {
      pImage = 0;
   }

   delete [] zSrc;

   return pImage;
}

//______________________________________________________________________________
static TImage *ReadRemoteImage(const char *url)
{
   // Temporary function to read remote pictures

   TImage *image = 0;
   FILE *tmp;
   char *buf;
   TUrl fUrl(url);

   TString msg = "GET ";
   msg += fUrl.GetProtocol();
   msg += "://";
   msg += fUrl.GetHost();
   msg += ":";
   msg += fUrl.GetPort();
   msg += "/";
   msg += fUrl.GetFile();
   msg += "\r\n";

   TString uri(url);
   if (!uri.BeginsWith("http://") || uri.EndsWith(".html"))
      return 0;
   TSocket s(fUrl.GetHost(), fUrl.GetPort());
   if (!s.IsValid())
      return 0;
   if (s.SendRaw(msg.Data(), msg.Length()) == -1)
      return 0;
   Int_t size = 1024*1024;
   buf = (char *)calloc(size, sizeof(char));
   if (!buf) return 0;
   if (s.RecvRaw(buf, size) == -1) {
      free(buf);
      return 0;
   }
   TString pathtmp = TString::Format("%s/%s", gSystem->TempDirectory(),
                                     gSystem->BaseName(url));
   tmp = fopen(pathtmp.Data(), "wb");
   if (!tmp) {
      free(buf);
      return 0;
   }
   fwrite(buf, sizeof(char), size, tmp);
   fclose(tmp);
   free(buf);
   image = TImage::Open(pathtmp.Data());
   if (image && !image->IsValid()) {
      delete image;
      image = 0;
   }
   gSystem->Unlink(pathtmp.Data());
   return image;
}

//______________________________________________________________________________
TImage *TGHtml::LoadImage(const char *url, int w, int h)
{
   // This is the default LoadImage() procedure. It just tries to load the
   // image from a file in the local filesystem.

   TImage *image = 0;

   //TGHtmlUri uri(url);

   TString uri(url);
   if (uri.BeginsWith("http://") && !uri.EndsWith(".html"))
      image = ReadRemoteImage(url);
   else
      image = TImage::Open(url);
   if (image) {
      if (!image->IsValid()) {
         delete image;
         image = 0;
         return 0;
      }
      if ((w > 0 && h > 0) && ((w != (int)image->GetWidth()) ||
          (h != (int)image->GetHeight()))) {
         image->Scale(w, h);
      }
   }
   return image;
}

//______________________________________________________________________________
const char *TGHtml::GetPctWidth(TGHtmlElement *p, char *opt, char *ret)
{
   // Return the height and width, converting to percent if required
   // ret must be at least 16 characters long

   int n, m, val;
   const char *tz, *z;
   TGHtmlElement *pElem = p;

   z = pElem->MarkupArg(opt, "");
   if (!z) return z;
   if (!strchr(z, '%')) return z;
   // coverity[secure_coding]
   if (!sscanf(z, "%d", &n)) return z;
   if (n < 0 || n > 100) return z;
   if (opt[0] == 'h') {
      val = fCanvas->GetHeight() * 100;
   } else {
      val = fCanvas->GetWidth() * 100;
   }
   if (!fInTd) {
      snprintf(ret, 15, "%d", val / n);
   } else {
      while (pElem && pElem->fType != Html_TD) pElem = pElem->fPPrev;
      if (!pElem) return z;
      tz = pElem->MarkupArg(opt, 0);
      // coverity[secure_coding]
      if (tz && !strchr(tz, '%') && sscanf(tz, "%d", &m)) {
         snprintf(ret, 15, "%d", m * 100 / n);
         return ret;
      }
      pElem = ((TGHtmlCell *)pElem)->fPTable;
      if (!pElem) return z;
      tz = pElem->MarkupArg(opt, 0);
      // coverity[secure_coding]
      if (tz && !strchr(tz, '%') && sscanf(tz, "%d", &m)) {
         snprintf(ret, 15, "%d", m * 100 / n);
         return ret;
      }
      return z;
   }
   return ret;
}

//______________________________________________________________________________
int TGHtml::GetImageAt(int x, int y)
{
   // This routine searchs for an image beneath the coordinates x,y
   // and returns the token number of the the image, or -1 if no
   // image found.

   TGHtmlBlock *pBlock;
   TGHtmlElement *pElem;
   //int n;

   for (pBlock = fFirstBlock; pBlock; pBlock = pBlock->fBNext) {
      if (pBlock->fTop > y || pBlock->fBottom < y ||
          pBlock->fLeft > x || pBlock->fRight < x) {
         continue;
      }
      for (pElem = pBlock->fPNext; pElem; pElem = pElem->fPNext) {
         if (pBlock->fBNext && pElem == pBlock->fBNext->fPNext) break;
         if (pElem->fType == Html_IMG) {
            return TokenNumber(pElem);
         }
      }
   }

   return -1;
}
<|endoftext|>


<commit_before>#include "selection.hh"

#include "utf8.hh"

namespace Kakoune
{

void Range::merge_with(const Range& range)
{
    m_last = range.m_last;
    if (m_first < m_last)
        m_first = std::min(m_first, range.m_first);
    if (m_first > m_last)
        m_first = std::max(m_first, range.m_first);
}

namespace
{

template<template <bool, bool> class UpdateFunc>
void on_buffer_change(const Buffer& buffer, SelectionList& sels,
                      BufferCoord begin, BufferCoord end, LineCount end_line)
{
    auto update_beg = std::lower_bound(sels.begin(), sels.end(), begin,
                                       [](const Selection& s, BufferCoord c) { return std::max(s.first(), s.last()) < c; });
    auto update_only_line_beg = std::upper_bound(sels.begin(), sels.end(), end_line,
                                                 [](LineCount l, const Selection& s) { return l < std::min(s.first(), s.last()).line; });

    if (update_beg != update_only_line_beg)
    {
        // for the first one, we are not sure if min < begin
        UpdateFunc<false, false>{}(buffer, update_beg->first(), begin, end);
        UpdateFunc<false, false>{}(buffer, update_beg->last(), begin, end);
    }
    for (auto it = update_beg+1; it < update_only_line_beg; ++it)
    {
        UpdateFunc<false, true>{}(buffer, it->first(), begin, end);
        UpdateFunc<false, true>{}(buffer, it->last(), begin, end);
    }
    if (end.line > begin.line)
    {
        for (auto it = update_only_line_beg; it != sels.end(); ++it)
        {
            UpdateFunc<true, true>{}(buffer, it->first(), begin, end);
            UpdateFunc<true, true>{}(buffer, it->last(), begin, end);
        }
    }
}

template<bool assume_different_line, bool assume_greater_than_begin>
struct UpdateInsert
{
    void operator()(const Buffer& buffer, BufferCoord& coord,
                    BufferCoord begin, BufferCoord end) const
    {
        if (assume_different_line)
            kak_assert(begin.line < coord.line);
        if (not assume_greater_than_begin and coord < begin)
            return;
        if (not assume_different_line and begin.line == coord.line)
            coord.column = end.column + coord.column - begin.column;

        coord.line += end.line - begin.line;
    }
};

template<bool assume_different_line, bool assume_greater_than_begin>
struct UpdateErase
{
    void operator()(const Buffer& buffer, BufferCoord& coord,
                    BufferCoord begin, BufferCoord end) const
    {
        if (not assume_greater_than_begin and coord < begin)
            return;
        if (assume_different_line)
            kak_assert(end.line < coord.line);
        if (not assume_different_line and coord <= end)
            coord = buffer.clamp(begin);
        else
        {
            if (not assume_different_line and end.line == coord.line)
            {
                coord.line = begin.line;
                coord.column = begin.column + coord.column - end.column;
            }
            else
                coord.line -= end.line - begin.line;
        }
    }
};

}

void SelectionList::update_insert(const Buffer& buffer, BufferCoord begin, BufferCoord end)
{
    on_buffer_change<UpdateInsert>(buffer, *this, begin, end, begin.line);
}

void SelectionList::update_erase(const Buffer& buffer, BufferCoord begin, BufferCoord end)
{
    on_buffer_change<UpdateErase>(buffer, *this, begin, end, end.line);
}

void SelectionList::check_invariant() const
{
    kak_assert(m_main < size());
    for (size_t i = 0; i+1 < size(); ++ i)
        kak_assert((*this)[i].min() <= (*this)[i+1].min());
}

}
<commit_msg>SelectionList should never be empty<commit_after>#include "selection.hh"

#include "utf8.hh"

namespace Kakoune
{

void Range::merge_with(const Range& range)
{
    m_last = range.m_last;
    if (m_first < m_last)
        m_first = std::min(m_first, range.m_first);
    if (m_first > m_last)
        m_first = std::max(m_first, range.m_first);
}

namespace
{

template<template <bool, bool> class UpdateFunc>
void on_buffer_change(const Buffer& buffer, SelectionList& sels,
                      BufferCoord begin, BufferCoord end, LineCount end_line)
{
    auto update_beg = std::lower_bound(sels.begin(), sels.end(), begin,
                                       [](const Selection& s, BufferCoord c) { return std::max(s.first(), s.last()) < c; });
    auto update_only_line_beg = std::upper_bound(sels.begin(), sels.end(), end_line,
                                                 [](LineCount l, const Selection& s) { return l < std::min(s.first(), s.last()).line; });

    if (update_beg != update_only_line_beg)
    {
        // for the first one, we are not sure if min < begin
        UpdateFunc<false, false>{}(buffer, update_beg->first(), begin, end);
        UpdateFunc<false, false>{}(buffer, update_beg->last(), begin, end);
    }
    for (auto it = update_beg+1; it < update_only_line_beg; ++it)
    {
        UpdateFunc<false, true>{}(buffer, it->first(), begin, end);
        UpdateFunc<false, true>{}(buffer, it->last(), begin, end);
    }
    if (end.line > begin.line)
    {
        for (auto it = update_only_line_beg; it != sels.end(); ++it)
        {
            UpdateFunc<true, true>{}(buffer, it->first(), begin, end);
            UpdateFunc<true, true>{}(buffer, it->last(), begin, end);
        }
    }
}

template<bool assume_different_line, bool assume_greater_than_begin>
struct UpdateInsert
{
    void operator()(const Buffer& buffer, BufferCoord& coord,
                    BufferCoord begin, BufferCoord end) const
    {
        if (assume_different_line)
            kak_assert(begin.line < coord.line);
        if (not assume_greater_than_begin and coord < begin)
            return;
        if (not assume_different_line and begin.line == coord.line)
            coord.column = end.column + coord.column - begin.column;

        coord.line += end.line - begin.line;
    }
};

template<bool assume_different_line, bool assume_greater_than_begin>
struct UpdateErase
{
    void operator()(const Buffer& buffer, BufferCoord& coord,
                    BufferCoord begin, BufferCoord end) const
    {
        if (not assume_greater_than_begin and coord < begin)
            return;
        if (assume_different_line)
            kak_assert(end.line < coord.line);
        if (not assume_different_line and coord <= end)
            coord = buffer.clamp(begin);
        else
        {
            if (not assume_different_line and end.line == coord.line)
            {
                coord.line = begin.line;
                coord.column = begin.column + coord.column - end.column;
            }
            else
                coord.line -= end.line - begin.line;
        }
    }
};

}

void SelectionList::update_insert(const Buffer& buffer, BufferCoord begin, BufferCoord end)
{
    on_buffer_change<UpdateInsert>(buffer, *this, begin, end, begin.line);
}

void SelectionList::update_erase(const Buffer& buffer, BufferCoord begin, BufferCoord end)
{
    on_buffer_change<UpdateErase>(buffer, *this, begin, end, end.line);
}

void SelectionList::check_invariant() const
{
    kak_assert(size() > 0);
    kak_assert(m_main < size());
    for (size_t i = 0; i+1 < size(); ++ i)
        kak_assert((*this)[i].min() <= (*this)[i+1].min());
}

}
<|endoftext|>


<commit_before>#include <QDebug>
#include <QFile>
#include <QImage>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QToolButton>
#include <QStackedLayout>
#include <QWidget>

#include "app.h"
#include "settings.h"
#include "ui_settings.h"

Settings::Settings(App* app, QWidget* parent = NULL) :
	QWidget(parent),
	app(app) {
	this->ui.setupUi(this);

	this->initValues();

	QLineEdit* platform = this->ui.platform;
	QLineEdit* command = this->ui.command;
	QLineEdit* icon = this->ui.icon;
	QLineEdit* background = this->ui.background;
	connect(platform, SIGNAL(textEdited(const QString&)), this, SLOT(onChange()));
	connect(command, SIGNAL(textEdited(const QString&)), this, SLOT(onChange()));
	connect(icon, SIGNAL(textEdited(const QString&)), this, SLOT(onChange()));
	connect(background, SIGNAL(textEdited(const QString&)), this, SLOT(onChange()));

	QPushButton* save = this->ui.save;
	connect(save, SIGNAL(clicked()), this, SLOT(onSave()));
	save->setEnabled(false);

	QToolButton* iconButton = this->ui.iconButton;
	connect(iconButton, SIGNAL(clicked()), this, SLOT(onIconButton()));

	connect(this->ui.backgroundButton, SIGNAL(clicked()), this, SLOT(onBackgroundButton()));
	connect(this->ui.commandButton, SIGNAL(clicked(bool)), this, SLOT(onCommandButton()));
	connect(this->ui.completeView, SIGNAL(clicked()), this, SLOT(onViewSelected()));
	connect(this->ui.coverView, SIGNAL(clicked()), this, SLOT(onViewSelected()));
}

Settings::~Settings() {
}

void Settings::initValues() {
	if (this->app == NULL) {
		return;
	}

	this->ui.platform->setText(this->app->getSelectedPlatform().name);
	this->ui.command->setText(this->app->getSelectedPlatform().command);
	this->ui.icon->setText(this->app->getSelectedPlatform().icon);
	this->ui.background->setText(this->app->getSelectedPlatform().background);

	QLabel* iconImage = this->ui.iconImage;
	QLabel* backgroundImage = this->ui.backgroundImage;

	QImage image(this->ui.icon->text());
	QPixmap pixmap;
	pixmap.convertFromImage(image);
	if (!image.isNull()) {
		iconImage->setPixmap(pixmap.scaled(iconImage->width(),iconImage->height(),Qt::KeepAspectRatio));
		iconImage->setScaledContents(true);
	}

	image = QImage(this->ui.background->text());
	pixmap.convertFromImage(image);
	if (!image.isNull()) {
		backgroundImage->setPixmap(pixmap);
		backgroundImage->setScaledContents(true);
	}

	if (this->app->getSelectedPlatform().view == "complete") {
		this->ui.completeView->setChecked(true);
		this->ui.coverView->setChecked(false);
	} else {
		this->ui.coverView->setChecked(true);
		this->ui.completeView->setChecked(false);
	}
}

void Settings::onViewSelected() {
	this->enableSave();
}

void Settings::onCommandButton() {
	QFileDialog fileDialog(this);
	fileDialog.setOption(QFileDialog::DontUseNativeDialog, true);
	connect(&fileDialog, SIGNAL(fileSelected(const QString&)), this, SLOT(onCommandSelected(const QString&)));
	fileDialog.exec();
}

void Settings::onCommandSelected(const QString& command) {
	this->ui.command->setText(command);
	this->enableSave();
}

void Settings::onIconButton() {
	QFileDialog fileDialog(this);
	fileDialog.setOption(QFileDialog::DontUseNativeDialog, true);
	connect(&fileDialog, SIGNAL(fileSelected(const QString&)), this, SLOT(onIconSelected(const QString&)));
	fileDialog.exec();
}

void Settings::onIconSelected(const QString& filepath) {
	QLineEdit* icon = this->ui.icon;
	icon->setText(filepath);
	this->enableSave();

	// refresh the image
	QLabel* iconImage = this->ui.iconImage;
	QImage image(icon->text());
	QPixmap pixmap;
	pixmap.convertFromImage(image);
	if (!image.isNull()) {
		iconImage->setPixmap(pixmap);
	}
}

void Settings::onBackgroundButton() {
	QFileDialog fileDialog(this);
	fileDialog.setOption(QFileDialog::DontUseNativeDialog, true);
	connect(&fileDialog, SIGNAL(fileSelected(const QString&)), this, SLOT(onBackgroundSelected(const QString&)));
	fileDialog.exec();
}

void Settings::onBackgroundSelected(const QString& filepath) {
	QLineEdit* background = this->ui.background;
	background->setText(filepath);
	this->enableSave();

	// refresh the image
	QLabel* backgroundImage = this->ui.backgroundImage;
	QImage image(background->text());
	QPixmap pixmap;
	pixmap.convertFromImage(image);
	if (!image.isNull()) {
		backgroundImage->setPixmap(pixmap);
	}
}

void Settings::onChange() {
	this->enableSave();
}

void Settings::enableSave() {
	QPushButton* save = this->ui.save;
	save->setEnabled(true);
}

void Settings::onSave() {
	QLineEdit* platform = this->ui.platform;
	QLineEdit* command = this->ui.command;
	QLineEdit* icon = this->ui.icon;
	QLineEdit* background = this->ui.background;
	Platform& selectedPlatform= this->app->getSelectedPlatform();
	selectedPlatform.name = platform->text();
	selectedPlatform.command = command->text();
	selectedPlatform.icon = icon->text();
	selectedPlatform.background = background->text();

	if (this->ui.completeView->isChecked()) {
		selectedPlatform.view = "complete";
	} else {
		selectedPlatform.view = "cover";
	}

	// replace the platform in the list of platform of the app
	this->app->updateInternalPlatform(selectedPlatform);

	// update the db
	this->app->getDb()->update(selectedPlatform);

	this->app->updatePlatformList();

	QPushButton* save = this->ui.save;
	save->setEnabled(false);
}
<commit_msg>When creating a new platform, default on complete mode.<commit_after>#include <QDebug>
#include <QFile>
#include <QImage>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QToolButton>
#include <QStackedLayout>
#include <QWidget>

#include "app.h"
#include "settings.h"
#include "ui_settings.h"

Settings::Settings(App* app, QWidget* parent = NULL) :
	QWidget(parent),
	app(app) {
	this->ui.setupUi(this);

	this->initValues();

	QLineEdit* platform = this->ui.platform;
	QLineEdit* command = this->ui.command;
	QLineEdit* icon = this->ui.icon;
	QLineEdit* background = this->ui.background;
	connect(platform, SIGNAL(textEdited(const QString&)), this, SLOT(onChange()));
	connect(command, SIGNAL(textEdited(const QString&)), this, SLOT(onChange()));
	connect(icon, SIGNAL(textEdited(const QString&)), this, SLOT(onChange()));
	connect(background, SIGNAL(textEdited(const QString&)), this, SLOT(onChange()));

	QPushButton* save = this->ui.save;
	connect(save, SIGNAL(clicked()), this, SLOT(onSave()));
	save->setEnabled(false);

	QToolButton* iconButton = this->ui.iconButton;
	connect(iconButton, SIGNAL(clicked()), this, SLOT(onIconButton()));

	connect(this->ui.backgroundButton, SIGNAL(clicked()), this, SLOT(onBackgroundButton()));
	connect(this->ui.commandButton, SIGNAL(clicked(bool)), this, SLOT(onCommandButton()));
	connect(this->ui.completeView, SIGNAL(clicked()), this, SLOT(onViewSelected()));
	connect(this->ui.coverView, SIGNAL(clicked()), this, SLOT(onViewSelected()));
}

Settings::~Settings() {
}

void Settings::initValues() {
	if (this->app == NULL) {
		return;
	}

	this->ui.platform->setText(this->app->getSelectedPlatform().name);
	this->ui.command->setText(this->app->getSelectedPlatform().command);
	this->ui.icon->setText(this->app->getSelectedPlatform().icon);
	this->ui.background->setText(this->app->getSelectedPlatform().background);

	QLabel* iconImage = this->ui.iconImage;
	QLabel* backgroundImage = this->ui.backgroundImage;

	QImage image(this->ui.icon->text());
	QPixmap pixmap;
	pixmap.convertFromImage(image);
	if (!image.isNull()) {
		iconImage->setPixmap(pixmap.scaled(iconImage->width(),iconImage->height(),Qt::KeepAspectRatio));
		iconImage->setScaledContents(true);
	}

	image = QImage(this->ui.background->text());
	pixmap.convertFromImage(image);
	if (!image.isNull()) {
		backgroundImage->setPixmap(pixmap);
		backgroundImage->setScaledContents(true);
	}

	if (this->app->getSelectedPlatform().view == "cover") {
		this->ui.coverView->setChecked(true);
		this->ui.completeView->setChecked(false);
	} else {
		this->ui.completeView->setChecked(true);
		this->ui.coverView->setChecked(false);
	}
}

void Settings::onViewSelected() {
	this->enableSave();
}

void Settings::onCommandButton() {
	QFileDialog fileDialog(this);
	fileDialog.setOption(QFileDialog::DontUseNativeDialog, true);
	connect(&fileDialog, SIGNAL(fileSelected(const QString&)), this, SLOT(onCommandSelected(const QString&)));
	fileDialog.exec();
}

void Settings::onCommandSelected(const QString& command) {
	this->ui.command->setText(command);
	this->enableSave();
}

void Settings::onIconButton() {
	QFileDialog fileDialog(this);
	fileDialog.setOption(QFileDialog::DontUseNativeDialog, true);
	connect(&fileDialog, SIGNAL(fileSelected(const QString&)), this, SLOT(onIconSelected(const QString&)));
	fileDialog.exec();
}

void Settings::onIconSelected(const QString& filepath) {
	QLineEdit* icon = this->ui.icon;
	icon->setText(filepath);
	this->enableSave();

	// refresh the image
	QLabel* iconImage = this->ui.iconImage;
	QImage image(icon->text());
	QPixmap pixmap;
	pixmap.convertFromImage(image);
	if (!image.isNull()) {
		iconImage->setPixmap(pixmap);
	}
}

void Settings::onBackgroundButton() {
	QFileDialog fileDialog(this);
	fileDialog.setOption(QFileDialog::DontUseNativeDialog, true);
	connect(&fileDialog, SIGNAL(fileSelected(const QString&)), this, SLOT(onBackgroundSelected(const QString&)));
	fileDialog.exec();
}

void Settings::onBackgroundSelected(const QString& filepath) {
	QLineEdit* background = this->ui.background;
	background->setText(filepath);
	this->enableSave();

	// refresh the image
	QLabel* backgroundImage = this->ui.backgroundImage;
	QImage image(background->text());
	QPixmap pixmap;
	pixmap.convertFromImage(image);
	if (!image.isNull()) {
		backgroundImage->setPixmap(pixmap);
	}
}

void Settings::onChange() {
	this->enableSave();
}

void Settings::enableSave() {
	QPushButton* save = this->ui.save;
	save->setEnabled(true);
}

void Settings::onSave() {
	QLineEdit* platform = this->ui.platform;
	QLineEdit* command = this->ui.command;
	QLineEdit* icon = this->ui.icon;
	QLineEdit* background = this->ui.background;
	Platform& selectedPlatform= this->app->getSelectedPlatform();
	selectedPlatform.name = platform->text();
	selectedPlatform.command = command->text();
	selectedPlatform.icon = icon->text();
	selectedPlatform.background = background->text();

	if (this->ui.completeView->isChecked()) {
		selectedPlatform.view = "complete";
	} else {
		selectedPlatform.view = "cover";
	}

	// replace the platform in the list of platform of the app
	this->app->updateInternalPlatform(selectedPlatform);

	// update the db
	this->app->getDb()->update(selectedPlatform);

	this->app->updatePlatformList();

	QPushButton* save = this->ui.save;
	save->setEnabled(false);
}
<|endoftext|>