<commit_before>#include "road.h"

//Beállítja a változókat
Road::Road(QGraphicsWidget* parent) : QGraphicsWidget(parent),
    life(Settings::STARTLIFE),isDisplay(false),distance(0),speed(Settings::STEP_SIZE),
    accel(0),moving(0)
{
    setPos(0,Settings::SCREEN_HEIGHT-Settings::ROAD_HEIGHT);
    myCar = new Car(this);
    myCar->setPos(Settings::SCREEN_WIDTH/2-Settings::FIELD_WIDTH/2,
                  Settings::ROAD_HEIGHT-(Settings::FIELD_HEIGHT*3));
    myCar->setZValue(2);
    generateRoad(0);
    roadPict.load("debug/images/road.png");
    roadGenerator = new RoadGenerator();
}

//Megadja a tartalmazó négyzet méretét
QRectF Road::boundingRect() const{
    return QRectF(0,-Settings::SCREEN_HEIGHT,Settings::SCREEN_WIDTH,Settings::SCREEN_HEIGHT*2.5);
}

//Felrajzol két utat egymás után.
void Road::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
    painter->drawPixmap(0,-Settings::ROAD_HEIGHT,Settings::SCREEN_WIDTH,Settings::ROAD_HEIGHT,roadPict);
    painter->drawPixmap(0,0,Settings::SCREEN_WIDTH,Settings::ROAD_HEIGHT,roadPict);
}

//Animációért felelős
void Road::advance(int step){
    if(!step) return;   //ha step 0, akkor nem csinál semmit
    moveBy(0,speed);          //lépteti az utat és a kocsit
    myCar->moveBy(0,-speed);
    if(moving>0){
        moving-=speed;
        myCar->moveBy(speed,0);
    }
    if(moving<0){
        moving+=speed;
        myCar->moveBy(-speed,0);
    }
    accel++;
    //sendDistanceNumber(accel);
    distance+=speed/5;
    if(accel>100){
        accel=0;
        speed=speed*1.3;
        std::cout<<"TÁVOLSÁG: "<<distance<<std::endl;
    }
    if(pos().y()>Settings::SCREEN_HEIGHT){  //ha az út kiment a képernyőről újra beállítja a koordinátákat
        moveBy(0,-Settings::ROAD_HEIGHT);
        myCar->moveBy(0,Settings::ROAD_HEIGHT);
        movePotholes();
        generateRoad(1);                    //generál egy új kátyúsort
    }
                                            //ha az autó ütközik egy kátyúval csökkenti az életét.
    for(unsigned int i=0;i<potholes.size();i++){
        if(myCar->collidesWithItem(potholes[i])){
            int depth=potholes[i]->conflict();
            if(depth>0){
                speed=Settings::STEP_SIZE;
                accel=0;
                life-=depth;
                emit sendLifeNumber(life);
                isDisplay=false;
                if(life<0){
                    std::cout<<"HALÁL!"<<std::endl;
                    //exit(0);
                }
            }
            if(!isDisplay){
                std::cout<<"ELET: "<<life<<std::endl;
                isDisplay=true;
            }
        }
    }
}

//Lépteti az autót oldalra, úgy, hogy ne lépjen le az útrlól
///TODO: még jobbra le tud lépni a tesztelés érdekében!
void Road::moveCar(const short& direction){ //direction -1: bal, 1:jobb
    if(direction==-1){
        if(myCar->pos().x()+moving>Settings::SCREEN_WIDTH/2-Settings::FIELD_WIDTH*0.5){
            moving+=-Settings::FIELD_WIDTH;
            //myCar->moveBy(-Settings::FIELD_WIDTH,0);
        }
    }else if(direction==1){
        if(myCar->pos().x()+moving<Settings::SCREEN_WIDTH/2+Settings::FIELD_WIDTH*1.5){
            moving+=Settings::FIELD_WIDTH;
            //myCar->moveBy(Settings::FIELD_WIDTH,0);
        }
    }
}

//Véletlen számokkal generál ROAD_SIZE-méretű utat
void Road::generateRoad(const unsigned short& difficulty){
    if(difficulty==0)return;
    std::vector<std::vector<bool> > idRoad = roadGenerator->getRoad(difficulty);
    for(unsigned int i=0;i<idRoad.size();i++){
        for(unsigned int j=0;j<idRoad[i].size();j++){
            if(idRoad[i][j] == true){
                Pothole *idPot = new Pothole(this);
                idPot->setPos(Settings::SCREEN_WIDTH/2-Settings::FIELD_WIDTH*1.5+j*Settings::FIELD_WIDTH,-(int)(i+1)*Settings::FIELD_HEIGHT);
                idPot->setZValue(1);
                potholes.push_back(idPot);
            }
        }
    }
    //std::cout <<"Road generated with difficulty: " << difficulty <<std::endl;
}

Road::~Road(){
    delete myCar;
    for(unsigned int i(0);i<potholes.size();i++){
        delete potholes[i];
    }
}

//A már nem kellő kátyúkat törli, a még kellőket pedig áthelyezi, hogy a képernyőn maradjon törlésnél.
void Road::movePotholes(){
    auto i = std::begin(potholes);
    while (i != std::end(potholes)) {
        if((*i)->pos().y()>0){  //Törlés
            (*i)->hide();
            i = potholes.erase(i);
        }else{                  //Léptetés
            (*i)->moveBy(0,Settings::ROAD_HEIGHT);
            i++;
        }
    }
}
<commit_msg>Distance send by signal<commit_after>#include "road.h"

//Beállítja a változókat
Road::Road(QGraphicsWidget* parent) : QGraphicsWidget(parent),
    life(Settings::STARTLIFE),isDisplay(false),distance(0),speed(Settings::STEP_SIZE),
    accel(0),moving(0)
{
    setPos(0,Settings::SCREEN_HEIGHT-Settings::ROAD_HEIGHT);
    myCar = new Car(this);
    myCar->setPos(Settings::SCREEN_WIDTH/2-Settings::FIELD_WIDTH/2,
                  Settings::ROAD_HEIGHT-(Settings::FIELD_HEIGHT*3));
    myCar->setZValue(2);
    generateRoad(0);
    roadPict.load("debug/images/road.png");
    roadGenerator = new RoadGenerator();
}

//Megadja a tartalmazó négyzet méretét
QRectF Road::boundingRect() const{
    return QRectF(0,-Settings::SCREEN_HEIGHT,Settings::SCREEN_WIDTH,Settings::SCREEN_HEIGHT*2.5);
}

//Felrajzol két utat egymás után.
void Road::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
    painter->drawPixmap(0,-Settings::ROAD_HEIGHT,Settings::SCREEN_WIDTH,Settings::ROAD_HEIGHT,roadPict);
    painter->drawPixmap(0,0,Settings::SCREEN_WIDTH,Settings::ROAD_HEIGHT,roadPict);
}

//Animációért felelős
void Road::advance(int step){
    if(!step) return;   //ha step 0, akkor nem csinál semmit
    moveBy(0,speed);          //lépteti az utat és a kocsit
    myCar->moveBy(0,-speed);
    if(moving>0){
        moving-=speed;
        myCar->moveBy(speed,0);
    }
    if(moving<0){
        moving+=speed;
        myCar->moveBy(-speed,0);
    }
    accel++;
    emit sendDistanceNumber(accel);
    distance+=speed/5;
    if(accel>100){
        accel=0;
        speed=speed*1.3;
        std::cout<<"TÁVOLSÁG: "<<distance<<std::endl;
    }
    if(pos().y()>Settings::SCREEN_HEIGHT){  //ha az út kiment a képernyőről újra beállítja a koordinátákat
        moveBy(0,-Settings::ROAD_HEIGHT);
        myCar->moveBy(0,Settings::ROAD_HEIGHT);
        movePotholes();
        generateRoad(1);                    //generál egy új kátyúsort
    }
                                            //ha az autó ütközik egy kátyúval csökkenti az életét.
    for(unsigned int i=0;i<potholes.size();i++){
        if(myCar->collidesWithItem(potholes[i])){
            int depth=potholes[i]->conflict();
            if(depth>0){
                speed=Settings::STEP_SIZE;
                accel=0;
                life-=depth;
                emit sendLifeNumber(life);
                isDisplay=false;
                if(life<0){
                    std::cout<<"HALÁL!"<<std::endl;
                    //exit(0);
                }
            }
            if(!isDisplay){
                std::cout<<"ELET: "<<life<<std::endl;
                isDisplay=true;
            }
        }
    }
}

//Lépteti az autót oldalra, úgy, hogy ne lépjen le az útrlól
///TODO: még jobbra le tud lépni a tesztelés érdekében!
void Road::moveCar(const short& direction){ //direction -1: bal, 1:jobb
    if(direction==-1){
        if(myCar->pos().x()+moving>Settings::SCREEN_WIDTH/2-Settings::FIELD_WIDTH*0.5){
            moving+=-Settings::FIELD_WIDTH;
            //myCar->moveBy(-Settings::FIELD_WIDTH,0);
        }
    }else if(direction==1){
        if(myCar->pos().x()+moving<Settings::SCREEN_WIDTH/2+Settings::FIELD_WIDTH*1.5){
            moving+=Settings::FIELD_WIDTH;
            //myCar->moveBy(Settings::FIELD_WIDTH,0);
        }
    }
}

//Véletlen számokkal generál ROAD_SIZE-méretű utat
void Road::generateRoad(const unsigned short& difficulty){
    if(difficulty==0)return;
    std::vector<std::vector<bool> > idRoad = roadGenerator->getRoad(difficulty);
    for(unsigned int i=0;i<idRoad.size();i++){
        for(unsigned int j=0;j<idRoad[i].size();j++){
            if(idRoad[i][j] == true){
                Pothole *idPot = new Pothole(this);
                idPot->setPos(Settings::SCREEN_WIDTH/2-Settings::FIELD_WIDTH*1.5+j*Settings::FIELD_WIDTH,-(int)(i+1)*Settings::FIELD_HEIGHT);
                idPot->setZValue(1);
                potholes.push_back(idPot);
            }
        }
    }
    //std::cout <<"Road generated with difficulty: " << difficulty <<std::endl;
}

Road::~Road(){
    delete myCar;
    for(unsigned int i(0);i<potholes.size();i++){
        delete potholes[i];
    }
}

//A már nem kellő kátyúkat törli, a még kellőket pedig áthelyezi, hogy a képernyőn maradjon törlésnél.
void Road::movePotholes(){
    auto i = std::begin(potholes);
    while (i != std::end(potholes)) {
        if((*i)->pos().y()>0){  //Törlés
            (*i)->hide();
            i = potholes.erase(i);
        }else{                  //Léptetés
            (*i)->moveBy(0,Settings::ROAD_HEIGHT);
            i++;
        }
    }
}
<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Justin Madsen
// =============================================================================
//
// A Simple Idler system that keeps track chain tension by pre-loading a
//  spring/damper elemnt
//
// =============================================================================

#include <cstdio>

#include "IdlerSimple.h"

#include "assets/ChAsset.h"
#include "assets/ChCylinderShape.h"
#include "assets/ChTriangleMeshShape.h"
#include "assets/ChColorAsset.h"
// collision mesh
#include "geometry/ChCTriangleMeshSoup.h"

#include "utils/ChUtilsInputOutput.h"
#include "utils/ChUtilsData.h"

namespace chrono {

// Static variables
const double IdlerSimple::m_mass = 429.6;
const ChVector<> IdlerSimple::m_inertia = ChVector<>(14.7, 12.55, 12.55);

const std::string IdlerSimple::m_meshName = "idler_mesh";
const std::string IdlerSimple::m_meshFile = utils::GetModelDataFile("M113/Idler_XforwardYup.obj");

// guessing at these values
const double IdlerSimple::m_radius = 0.255;
const double IdlerSimple::m_width = 0.166;
const double IdlerSimple::m_widthGap = 0.092;
const double IdlerSimple::m_springK = 100000;
const double IdlerSimple::m_springC = 1000;
const double IdlerSimple::m_springRestLength = 1.0;

/*
// -----------------------------------------------------------------------------
// Default shock and spring functors (used for linear elements)
// -----------------------------------------------------------------------------
class LinearSpringForce : public ChSpringForceCallback
{
public:
  LinearSpringForce(double k) : m_k(k) {}

  virtual double operator()(double time,         // current time
                            double rest_length,  // undeformed length
                            double length,       // current length
                            double vel)          // current velocity (positive when extending)
  {
    return -m_k * (length - rest_length);
  }

private:
  double  m_k;
};

class LinearShockForce : public ChSpringForceCallback
{
public:
  LinearShockForce(double c) : m_c(c) {}

  virtual double operator()(double time,         // current time
                            double rest_length,  // undeformed length
                            double length,       // current length
                            double vel)          // current velocity (positive when extending)
  {
    return -m_c * vel;
  }

private:
  double  m_c;
};
*/

IdlerSimple::IdlerSimple(const std::string& name,
                         VisualizationType vis,
                         CollisionType collide)
  : m_vis(vis), m_collide(collide)
//  , m_shockCB(NULL), m_springCB(NULL)
{
  // create the body, set the basic info
  m_idler = ChSharedPtr<ChBody>(new ChBody);
  m_idler->SetNameString(name + "_body");
  m_idler->SetMass(m_mass);
  m_idler->SetInertiaXX(m_inertia);

  // create the idler joint
  m_idler_joint = ChSharedPtr<ChLinkLockRevolutePrismatic>(new ChLinkLockRevolutePrismatic);
  m_idler_joint->SetNameString(name + "_idler_joint");

  // create the tensioning linear spring-shock
  m_shock = ChSharedPtr<ChLinkSpring>(new ChLinkSpring);
  m_shock->SetNameString(name + "_shock");
  m_shock->Set_SpringK(m_springK);
  m_shock->Set_SpringR(m_springC);
  m_shock->Set_SpringRestLength(m_springRestLength);

  AddVisualization();

}

IdlerSimple::~IdlerSimple()
{
  // delete m_springCB;
  // delete m_shockCB;
}

void IdlerSimple::Initialize(ChSharedPtr<ChBodyAuxRef> chassis,
                             const ChCoordsys<>& local_Csys)
{
  // add collision geometry
  AddCollisionGeometry();

  // Express the steering reference frame in the absolute coordinate system.
  ChFrame<> idler_to_abs(local_Csys);
  idler_to_abs.ConcatenatePreTransformation(chassis->GetFrame_REF_to_abs());

  // transform the idler body, add to system
  m_idler->SetPos(idler_to_abs.GetPos());
  m_idler->SetRot(idler_to_abs.GetRot());
  chassis->GetSystem()->Add(m_idler);

  // init joint, add to system
  // body 1 should rotate about z-axis, translate about x-axis of body2
  // TODO: (check) idler joint translates, rotates in correct direction.
  // NOTE: I created the idler to translate x-dir, rotate about z-dir, according
  //      to how the chassis is rotated by default.
  m_idler_joint->Initialize(m_idler, chassis, m_idler->GetCoord() );
  chassis->GetSystem()->AddLink(m_idler_joint);

  // init shock, add to system
  // put the second marker some length in front of marker1, based on desired preload
  double preLoad = 20000; // [N]
  // chassis spring attachment point is towards the center of the vehicle
  ChVector<> pos_chassis_abs = local_Csys.pos;
  if(local_Csys.pos.x < 0 )
    pos_chassis_abs.x += m_springRestLength - (preLoad / m_springK);
  else
    pos_chassis_abs.x -= m_springRestLength - (preLoad / m_springK);

  // transform 2nd attachment point to abs coords
  pos_chassis_abs = chassis->GetCoord().TransformPointLocalToParent(pos_chassis_abs);

  // init. points based on desired preload and free lengths
  m_shock->Initialize(m_idler, chassis, false, m_idler->GetPos(), pos_chassis_abs );
  // setting rest length should yield desired preload at time = 0
  m_shock->Set_SpringRestLength(m_springRestLength);

  chassis->GetSystem()->AddLink(m_shock);
}

void IdlerSimple::AddVisualization()
{
  // add visualization asset
  switch (m_vis) {
  case VisualizationType::PRIMITIVES:
  {
    ChSharedPtr<ChCylinderShape> cylA(new ChCylinderShape);
    // define the shape with two concentric cyclinders, with a gap.
    cylA->GetCylinderGeometry().p1 = ChVector<>(0, 0, m_width/2.0);
    cylA->GetCylinderGeometry().p2 = ChVector<>(0, 0, m_widthGap/2.0);
    cylA->GetCylinderGeometry().rad = m_radius;
    m_idler->AddAsset(cylA);

    // second cylinder is a mirror of the first
    ChSharedPtr<ChCylinderShape> cylB(new ChCylinderShape( *cylA.get_ptr() ));
    cylB->GetCylinderGeometry().p1.z = -m_width/2.0;
    cylB->GetCylinderGeometry().p2.z = -m_widthGap/2.0;
    m_idler->AddAsset(cylB);

    // add a color asset
    ChSharedPtr<ChColorAsset> mcolor(new ChColorAsset(0.5f, 0.1f, 0.4f));
    m_idler->AddAsset(mcolor);

    break;
  }
   case VisualizationType::MESH:
  {
    geometry::ChTriangleMeshConnected trimesh;
    trimesh.LoadWavefrontMesh(getMeshFile(), false, false);

    ChSharedPtr<ChTriangleMeshShape> trimesh_shape(new ChTriangleMeshShape);
    trimesh_shape->SetMesh(trimesh);
    trimesh_shape->SetName(getMeshName());
    m_idler->AddAsset(trimesh_shape);

    // add a color asset
    ChSharedPtr<ChColorAsset> mcolor(new ChColorAsset(0.5f, 0.1f, 0.4f));
    m_idler->AddAsset(mcolor);

    break;
  }
  default:
  {
    GetLog() << "Didn't recognize VisualizationType for IdlerSimple \n";
  }
  } // end switch
}

void IdlerSimple::AddCollisionGeometry()
{
  // add collision geometrey to the chassis, if enabled
  if(m_collide == CollisionType::NONE)
  {
      m_idler->SetCollide(false);
      GetLog() << " !!! Idler " << m_idler->GetName() << " collision deactivated !!! \n\n";
      return;
  }

  m_idler->SetCollide(true);
  m_idler->GetCollisionModel()->ClearModel();

  // 1 cm outwards, 0.5 inwards for envelope and margin, respectfully.
  m_idler->GetCollisionModel()->SetSafeMargin(0.005);	// inward safe margin
	m_idler->GetCollisionModel()->SetEnvelope(0.010);		// distance of the outward "collision envelope"

  switch (m_collide) {
  case CollisionType::PRIMITIVES:
  {
    double half_cyl_width =  (m_width - m_widthGap)/2.0;
    ChVector<> shape_offset =  ChVector<>(0, 0, half_cyl_width + m_widthGap/2.0);
    // use two cylinders.
    m_idler->GetCollisionModel()->AddCylinder(m_radius, m_radius, half_cyl_width,
      shape_offset,Q_from_AngAxis(CH_C_PI_2,VECT_X));

    // mirror first cylinder about the x-y plane
    shape_offset.z *= -1;
    m_idler->GetCollisionModel()->AddCylinder(m_radius, m_radius, half_cyl_width,
      shape_offset,Q_from_AngAxis(CH_C_PI_2,VECT_X));

    break;
  }
  case CollisionType::MESH:
  {
    // use a triangle mesh

		geometry::ChTriangleMeshSoup temp_trianglemesh;

    // TODO: fill the triangleMesh here with some track shoe geometry

    // is there an offset??
    double shoelength = 0.2;
    ChVector<> mesh_displacement(shoelength*0.5,0,0);  // since mesh origin is not in body center of mass
    m_idler->GetCollisionModel()->AddTriangleMesh(temp_trianglemesh, false, false, mesh_displacement);

    break;
  }
  case CollisionType::CONVEXHULL:
  {
    // use convex hulls, loaded from file
    ChStreamInAsciiFile chull_file(GetChronoDataFile("idler.chulls").c_str());
    // transform the collision geometry as needed
    double mangle = 45.0; // guess
    ChQuaternion<>rot;
    rot.Q_from_AngAxis(mangle*(CH_C_PI/180.),VECT_X);
    ChMatrix33<> rot_offset(rot);
    ChVector<> disp_offset(0,0,0);  // no displacement offset
    m_idler->GetCollisionModel()->AddConvexHullsFromFile(chull_file, disp_offset, rot_offset);
    break;
  }
  default:
    // no collision geometry
    GetLog() << "not recognized CollisionType: " << (int)m_collide <<" for idler wheel \n";
    m_idler->SetCollide(false);
    return;
  } // end switch

  // setup collision family, idler is a rolling element
  m_idler->GetCollisionModel()->SetFamily( (int)CollisionFam::WHEELS );

  // don't collide with the other wheels, nor ground
  m_idler->GetCollisionModel()->SetFamilyMaskNoCollisionWithFamily( (int)CollisionFam::WHEELS );

  m_idler->GetCollisionModel()->BuildModel();
}

} // end namespace chrono
<commit_msg>idler tensioner preload should be larger<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Justin Madsen
// =============================================================================
//
// A Simple Idler system that keeps track chain tension by pre-loading a
//  spring/damper elemnt
//
// =============================================================================

#include <cstdio>

#include "IdlerSimple.h"

#include "assets/ChAsset.h"
#include "assets/ChCylinderShape.h"
#include "assets/ChTriangleMeshShape.h"
#include "assets/ChColorAsset.h"
// collision mesh
#include "geometry/ChCTriangleMeshSoup.h"

#include "utils/ChUtilsInputOutput.h"
#include "utils/ChUtilsData.h"

namespace chrono {

// Static variables
const double IdlerSimple::m_mass = 429.6;
const ChVector<> IdlerSimple::m_inertia = ChVector<>(14.7, 12.55, 12.55);

const std::string IdlerSimple::m_meshName = "idler_mesh";
const std::string IdlerSimple::m_meshFile = utils::GetModelDataFile("M113/Idler_XforwardYup.obj");

// guessing at these values
const double IdlerSimple::m_radius = 0.255;
const double IdlerSimple::m_width = 0.166;
const double IdlerSimple::m_widthGap = 0.092;
const double IdlerSimple::m_springK = 150000;
const double IdlerSimple::m_springC = 1500;
const double IdlerSimple::m_springRestLength = 1.0;

/*
// -----------------------------------------------------------------------------
// Default shock and spring functors (used for linear elements)
// -----------------------------------------------------------------------------
class LinearSpringForce : public ChSpringForceCallback
{
public:
  LinearSpringForce(double k) : m_k(k) {}

  virtual double operator()(double time,         // current time
                            double rest_length,  // undeformed length
                            double length,       // current length
                            double vel)          // current velocity (positive when extending)
  {
    return -m_k * (length - rest_length);
  }

private:
  double  m_k;
};

class LinearShockForce : public ChSpringForceCallback
{
public:
  LinearShockForce(double c) : m_c(c) {}

  virtual double operator()(double time,         // current time
                            double rest_length,  // undeformed length
                            double length,       // current length
                            double vel)          // current velocity (positive when extending)
  {
    return -m_c * vel;
  }

private:
  double  m_c;
};
*/

IdlerSimple::IdlerSimple(const std::string& name,
                         VisualizationType vis,
                         CollisionType collide)
  : m_vis(vis), m_collide(collide)
//  , m_shockCB(NULL), m_springCB(NULL)
{
  // create the body, set the basic info
  m_idler = ChSharedPtr<ChBody>(new ChBody);
  m_idler->SetNameString(name + "_body");
  m_idler->SetMass(m_mass);
  m_idler->SetInertiaXX(m_inertia);

  // create the idler joint
  m_idler_joint = ChSharedPtr<ChLinkLockRevolutePrismatic>(new ChLinkLockRevolutePrismatic);
  m_idler_joint->SetNameString(name + "_idler_joint");

  // create the tensioning linear spring-shock
  m_shock = ChSharedPtr<ChLinkSpring>(new ChLinkSpring);
  m_shock->SetNameString(name + "_shock");
  m_shock->Set_SpringK(m_springK);
  m_shock->Set_SpringR(m_springC);
  m_shock->Set_SpringRestLength(m_springRestLength);

  AddVisualization();

}

IdlerSimple::~IdlerSimple()
{
  // delete m_springCB;
  // delete m_shockCB;
}

void IdlerSimple::Initialize(ChSharedPtr<ChBodyAuxRef> chassis,
                             const ChCoordsys<>& local_Csys)
{
  // add collision geometry
  AddCollisionGeometry();

  // Express the steering reference frame in the absolute coordinate system.
  ChFrame<> idler_to_abs(local_Csys);
  idler_to_abs.ConcatenatePreTransformation(chassis->GetFrame_REF_to_abs());

  // transform the idler body, add to system
  m_idler->SetPos(idler_to_abs.GetPos());
  m_idler->SetRot(idler_to_abs.GetRot());
  chassis->GetSystem()->Add(m_idler);

  // init joint, add to system
  // body 1 should rotate about z-axis, translate about x-axis of body2
  // TODO: (check) idler joint translates, rotates in correct direction.
  // NOTE: I created the idler to translate x-dir, rotate about z-dir, according
  //      to how the chassis is rotated by default.
  m_idler_joint->Initialize(m_idler, chassis, m_idler->GetCoord() );
  chassis->GetSystem()->AddLink(m_idler_joint);

  // init shock, add to system
  // put the second marker some length in front of marker1, based on desired preload
  double preLoad = 30000; // [N]
  // chassis spring attachment point is towards the center of the vehicle
  ChVector<> pos_chassis_abs = local_Csys.pos;
  if(local_Csys.pos.x < 0 )
    pos_chassis_abs.x += m_springRestLength - (preLoad / m_springK);
  else
    pos_chassis_abs.x -= m_springRestLength - (preLoad / m_springK);

  // transform 2nd attachment point to abs coords
  pos_chassis_abs = chassis->GetCoord().TransformPointLocalToParent(pos_chassis_abs);

  // init. points based on desired preload and free lengths
  m_shock->Initialize(m_idler, chassis, false, m_idler->GetPos(), pos_chassis_abs );
  // setting rest length should yield desired preload at time = 0
  m_shock->Set_SpringRestLength(m_springRestLength);

  chassis->GetSystem()->AddLink(m_shock);
}

void IdlerSimple::AddVisualization()
{
  // add visualization asset
  switch (m_vis) {
  case VisualizationType::PRIMITIVES:
  {
    ChSharedPtr<ChCylinderShape> cylA(new ChCylinderShape);
    // define the shape with two concentric cyclinders, with a gap.
    cylA->GetCylinderGeometry().p1 = ChVector<>(0, 0, m_width/2.0);
    cylA->GetCylinderGeometry().p2 = ChVector<>(0, 0, m_widthGap/2.0);
    cylA->GetCylinderGeometry().rad = m_radius;
    m_idler->AddAsset(cylA);

    // second cylinder is a mirror of the first
    ChSharedPtr<ChCylinderShape> cylB(new ChCylinderShape( *cylA.get_ptr() ));
    cylB->GetCylinderGeometry().p1.z = -m_width/2.0;
    cylB->GetCylinderGeometry().p2.z = -m_widthGap/2.0;
    m_idler->AddAsset(cylB);

    // add a color asset
    ChSharedPtr<ChColorAsset> mcolor(new ChColorAsset(0.5f, 0.1f, 0.4f));
    m_idler->AddAsset(mcolor);

    break;
  }
   case VisualizationType::MESH:
  {
    geometry::ChTriangleMeshConnected trimesh;
    trimesh.LoadWavefrontMesh(getMeshFile(), false, false);

    ChSharedPtr<ChTriangleMeshShape> trimesh_shape(new ChTriangleMeshShape);
    trimesh_shape->SetMesh(trimesh);
    trimesh_shape->SetName(getMeshName());
    m_idler->AddAsset(trimesh_shape);

    // add a color asset
    ChSharedPtr<ChColorAsset> mcolor(new ChColorAsset(0.5f, 0.1f, 0.4f));
    m_idler->AddAsset(mcolor);

    break;
  }
  default:
  {
    GetLog() << "Didn't recognize VisualizationType for IdlerSimple \n";
  }
  } // end switch
}

void IdlerSimple::AddCollisionGeometry()
{
  // add collision geometrey to the chassis, if enabled
  if(m_collide == CollisionType::NONE)
  {
      m_idler->SetCollide(false);
      GetLog() << " !!! Idler " << m_idler->GetName() << " collision deactivated !!! \n\n";
      return;
  }

  m_idler->SetCollide(true);
  m_idler->GetCollisionModel()->ClearModel();

  // 1 cm outwards, 0.5 inwards for envelope and margin, respectfully.
  m_idler->GetCollisionModel()->SetSafeMargin(0.005);	// inward safe margin
	m_idler->GetCollisionModel()->SetEnvelope(0.010);		// distance of the outward "collision envelope"

  switch (m_collide) {
  case CollisionType::PRIMITIVES:
  {
    double half_cyl_width =  (m_width - m_widthGap)/2.0;
    ChVector<> shape_offset =  ChVector<>(0, 0, half_cyl_width + m_widthGap/2.0);
    // use two cylinders.
    m_idler->GetCollisionModel()->AddCylinder(m_radius, m_radius, half_cyl_width,
      shape_offset,Q_from_AngAxis(CH_C_PI_2,VECT_X));

    // mirror first cylinder about the x-y plane
    shape_offset.z *= -1;
    m_idler->GetCollisionModel()->AddCylinder(m_radius, m_radius, half_cyl_width,
      shape_offset,Q_from_AngAxis(CH_C_PI_2,VECT_X));

    break;
  }
  case CollisionType::MESH:
  {
    // use a triangle mesh

		geometry::ChTriangleMeshSoup temp_trianglemesh;

    // TODO: fill the triangleMesh here with some track shoe geometry

    // is there an offset??
    double shoelength = 0.2;
    ChVector<> mesh_displacement(shoelength*0.5,0,0);  // since mesh origin is not in body center of mass
    m_idler->GetCollisionModel()->AddTriangleMesh(temp_trianglemesh, false, false, mesh_displacement);

    break;
  }
  case CollisionType::CONVEXHULL:
  {
    // use convex hulls, loaded from file
    ChStreamInAsciiFile chull_file(GetChronoDataFile("idler.chulls").c_str());
    // transform the collision geometry as needed
    double mangle = 45.0; // guess
    ChQuaternion<>rot;
    rot.Q_from_AngAxis(mangle*(CH_C_PI/180.),VECT_X);
    ChMatrix33<> rot_offset(rot);
    ChVector<> disp_offset(0,0,0);  // no displacement offset
    m_idler->GetCollisionModel()->AddConvexHullsFromFile(chull_file, disp_offset, rot_offset);
    break;
  }
  default:
    // no collision geometry
    GetLog() << "not recognized CollisionType: " << (int)m_collide <<" for idler wheel \n";
    m_idler->SetCollide(false);
    return;
  } // end switch

  // setup collision family, idler is a rolling element
  m_idler->GetCollisionModel()->SetFamily( (int)CollisionFam::WHEELS );

  // don't collide with the other wheels, nor ground
  m_idler->GetCollisionModel()->SetFamilyMaskNoCollisionWithFamily( (int)CollisionFam::WHEELS );

  m_idler->GetCollisionModel()->BuildModel();
}

} // end namespace chrono
<|endoftext|>


<commit_before>/*
  ==============================================================================

    OSCMessenger.cpp
    Created: 17 Feb 2017 11:19:57pm
    Author:  Oli

  ==============================================================================
*/

// see Poco::Contidion section of http://openframeworks.cc/ofBook/chapters/threads.html
// and replace Poco stuff with Juce Thread class functionality

#include "OSCMessenger.h"

OSCMessenger::OSCMessenger(String targetHost, int targetPort) :
   Thread("Message Dispatcher (OSC)"),  host(targetHost), port(targetPort)
{
    if (sender.connect (host, port)) {
        startThread(); // something going wrong here
    }
    else {
        showConnectionErrorMessage ("Error: could not connect to UDP port");
    }
}

void OSCMessenger::pushVideoFile(const String& name) {

    const ScopedLock mutex(videoSelectionMutex);
    videoSelections.push_back(name);
    notify();

}

void OSCMessenger::run()
{
    while (! threadShouldExit())
    {

        videoSelectionMutex.enter();

        if(!videoSelections.empty()) {
            String videoSelection = videoSelections.front();
            videoSelections.pop_front();

            videoSelectionMutex.exit();

            sendVideoSelection(videoSelection);
        } else {
            wait(-1);
        }

    }
}

bool OSCMessenger::sendVideoSelection(const String& name) {
    if(!sender.send("/video/playfile", name)) {
        showConnectionErrorMessage("Error: could not send Video Selection");
        return false;
    }
    return true;
}<commit_msg>make sure the mutex unlocks<commit_after>/*
  ==============================================================================

    OSCMessenger.cpp
    Created: 17 Feb 2017 11:19:57pm
    Author:  Oli

  ==============================================================================
*/

// see Poco::Contidion section of http://openframeworks.cc/ofBook/chapters/threads.html
// and replace Poco stuff with Juce Thread class functionality

#include "OSCMessenger.h"

OSCMessenger::OSCMessenger(String targetHost, int targetPort) :
   Thread("Message Dispatcher (OSC)"),  host(targetHost), port(targetPort)
{
    if (sender.connect (host, port)) {
        startThread(); // something going wrong here
    }
    else {
        showConnectionErrorMessage ("Error: could not connect to UDP port");
    }
}

void OSCMessenger::pushVideoFile(const String& name) {

    const ScopedLock mutex(videoSelectionMutex);
    videoSelections.push_back(name);
    notify();

}

void OSCMessenger::run()
{
    while (! threadShouldExit())
    {

        videoSelectionMutex.enter();

        if(!videoSelections.empty()) {
            String videoSelection = videoSelections.front();
            videoSelections.pop_front();

            videoSelectionMutex.exit();

            sendVideoSelection(videoSelection);
        } else {
            videoSelectionMutex.exit();
            wait(-1);
        }

    }
}

bool OSCMessenger::sendVideoSelection(const String& name) {
    if(!sender.send("/video/playfile", name)) {
        showConnectionErrorMessage("Error: could not send Video Selection");
        return false;
    }
    return true;
}<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtp_format_vp8.h"

#include <cassert>  // assert
#include <math.h>   // ceil
#include <string.h> // memcpy

namespace webrtc {

// Define how the VP8PacketizerModes are implemented.
// Modes are: kStrict, kAggregate, kSloppy.
const RtpFormatVp8::AggregationMode RtpFormatVp8::aggr_modes_[kNumModes] =
    { kAggrNone, kAggrPartitions, kAggrFragments };
const bool RtpFormatVp8::bal_modes_[kNumModes] =
    { true, false, false };
const bool RtpFormatVp8::sep_first_modes_[kNumModes] =
    { true, false, false };

RtpFormatVp8::RtpFormatVp8(const WebRtc_UWord8* payload_data,
                           WebRtc_UWord32 payload_size,
                           const RTPFragmentationHeader& fragmentation,
                           VP8PacketizerMode mode)
    : payload_data_(payload_data),
      payload_size_(static_cast<int>(payload_size)),
      payload_bytes_sent_(0),
      part_ix_(0),
      beginning_(true),
      first_fragment_(true),
      vp8_header_bytes_(1),
      aggr_mode_(aggr_modes_[mode]),
      balance_(bal_modes_[mode]),
      separate_first_(sep_first_modes_[mode])
{
    part_info_ = fragmentation;
}

RtpFormatVp8::RtpFormatVp8(const WebRtc_UWord8* payload_data,
                           WebRtc_UWord32 payload_size)
    : payload_data_(payload_data),
      payload_size_(static_cast<int>(payload_size)),
      part_info_(),
      payload_bytes_sent_(0),
      part_ix_(0),
      beginning_(true),
      first_fragment_(true),
      vp8_header_bytes_(1),
      aggr_mode_(aggr_modes_[kSloppy]),
      balance_(bal_modes_[kSloppy]),
      separate_first_(sep_first_modes_[kSloppy])
{
    part_info_.VerifyAndAllocateFragmentationHeader(1);
    part_info_.fragmentationLength[0] = payload_size;
    part_info_.fragmentationOffset[0] = 0;
}

int RtpFormatVp8::CalcNextSize(int max_payload_len, int remaining_bytes,
                               bool split_payload) const
{
    if (max_payload_len == 0 || remaining_bytes == 0)
    {
        return 0;
    }
    if (!split_payload)
    {
        return max_payload_len >= remaining_bytes ? remaining_bytes : 0;
    }

    if (balance_)
    {
        // Balance payload sizes to produce (almost) equal size
        // fragments.
        // Number of fragments for remaining_bytes:
        int num_frags = ceil(
            static_cast<double>(remaining_bytes) / max_payload_len);
        // Number of bytes in this fragment:
        return static_cast<int>(static_cast<double>(remaining_bytes)
            / num_frags + 0.5);
    }
    else
    {
        return max_payload_len >= remaining_bytes ? remaining_bytes
            : max_payload_len;
    }
}

int RtpFormatVp8::NextPacket(int max_payload_len, WebRtc_UWord8* buffer,
                             int* bytes_to_send, bool* last_packet)
{
    const int num_partitions = part_info_.fragmentationVectorSize;
    int send_bytes = 0; // How much data to send in this packet.
    bool split_payload = true; // Splitting of partitions is initially allowed.
    int remaining_in_partition = part_info_.fragmentationOffset[part_ix_]
        - payload_bytes_sent_ + part_info_.fragmentationLength[part_ix_];
    int rem_payload_len = max_payload_len - vp8_header_bytes_;

    while (int next_size = CalcNextSize(rem_payload_len, remaining_in_partition,
        split_payload))
    {
        send_bytes += next_size;
        rem_payload_len -= next_size;
        remaining_in_partition -= next_size;

        if (remaining_in_partition == 0 && !(beginning_ && separate_first_))
        {
            // Advance to next partition?
            // Check that there are more partitions; verify that we are either
            // allowed to aggregate fragments, or that we are allowed to
            // aggregate intact partitions and that we started this packet
            // with an intact partition (indicated by first_fragment_ == true).
            if (part_ix_ + 1 < num_partitions &&
                ((aggr_mode_ == kAggrFragments) ||
                 (aggr_mode_ == kAggrPartitions && first_fragment_)))
            {
                remaining_in_partition
                    = part_info_.fragmentationLength[++part_ix_];
                // Disallow splitting unless kAggrFragments. In kAggrPartitions,
                // we can only aggregate intact partitions.
                split_payload = (aggr_mode_ == kAggrFragments);
            }
        }
        else if (balance_ && remaining_in_partition > 0)
        {
            break;
        }
    }
    if (remaining_in_partition == 0)
    {
        ++part_ix_; // Advance to next partition.
    }

    const bool end_of_fragment = (remaining_in_partition == 0);
    // Write the payload header and the payload to buffer.
    *bytes_to_send = WriteHeaderAndPayload(send_bytes, end_of_fragment, buffer);
    if (*bytes_to_send < 0)
    {
        return -1;
    }

    *last_packet = (payload_bytes_sent_ >= payload_size_);
    assert(!*last_packet || (payload_bytes_sent_ == payload_size_));
    return 0;
}

int RtpFormatVp8::WriteHeaderAndPayload(int send_bytes,
                                        bool end_of_fragment,
                                        WebRtc_UWord8* buffer)
{
    // Write the VP8 payload header.
    //  0 1 2 3 4 5 6 7
    // +-+-+-+-+-+-+-+-+
    // | RSV |I|N|FI |B|
    // +-+-+-+-+-+-+-+-+

    if (send_bytes < 0)
    {
        return -1;
    }
    if (payload_bytes_sent_ + send_bytes > payload_size_)
    {
        return -1;
    }

    // PictureID always present in first packet
    const int picture_id_present = beginning_;
    // TODO(hlundin): must pipe this info from VP8 encoder
    const int kNonrefFrame = 0;

    buffer[0] = 0;
    if (picture_id_present) buffer[0] |= (0x01 << 4); // I
    if (kNonrefFrame)       buffer[0] |= (0x01 << 3); // N
    if (!first_fragment_)   buffer[0] |= (0x01 << 2); // FI
    if (!end_of_fragment)   buffer[0] |= (0x01 << 1); // FI
    if (beginning_)         buffer[0] |= 0x01; // B

    memcpy(&buffer[vp8_header_bytes_], &payload_data_[payload_bytes_sent_],
           send_bytes);

    beginning_ = false; // next packet cannot be first packet in frame
    // next packet starts new fragment if this ended one
    first_fragment_ = end_of_fragment;
    payload_bytes_sent_ += send_bytes;

    // Return total length of written data.
    return send_bytes + vp8_header_bytes_;
}
} // namespace webrtc
<commit_msg><commit_after>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtp_format_vp8.h"

#include <cassert>  // assert
#include <string.h> // memcpy

namespace webrtc {

// Define how the VP8PacketizerModes are implemented.
// Modes are: kStrict, kAggregate, kSloppy.
const RtpFormatVp8::AggregationMode RtpFormatVp8::aggr_modes_[kNumModes] =
    { kAggrNone, kAggrPartitions, kAggrFragments };
const bool RtpFormatVp8::balance_modes_[kNumModes] =
    { true, false, false };
const bool RtpFormatVp8::separate_first_modes_[kNumModes] =
    { true, false, false };

RtpFormatVp8::RtpFormatVp8(const WebRtc_UWord8* payload_data,
                           WebRtc_UWord32 payload_size,
                           const RTPVideoHeaderVP8& hdr_info,
                           const RTPFragmentationHeader& fragmentation,
                           VP8PacketizerMode mode)
    : payload_data_(payload_data),
      payload_size_(static_cast<int>(payload_size)),
      payload_bytes_sent_(0),
      part_ix_(0),
      beginning_(true),
      first_fragment_(true),
      vp8_header_bytes_(1),
      aggr_mode_(aggr_modes_[mode]),
      balance_(balance_modes_[mode]),
      separate_first_(separate_first_modes_[mode]),
      hdr_info_(hdr_info)
{
    part_info_ = fragmentation;
}

RtpFormatVp8::RtpFormatVp8(const WebRtc_UWord8* payload_data,
                           WebRtc_UWord32 payload_size,
                           const RTPVideoHeaderVP8& hdr_info)
    : payload_data_(payload_data),
      payload_size_(static_cast<int>(payload_size)),
      part_info_(),
      payload_bytes_sent_(0),
      part_ix_(0),
      beginning_(true),
      first_fragment_(true),
      vp8_header_bytes_(1),
      aggr_mode_(aggr_modes_[kSloppy]),
      balance_(balance_modes_[kSloppy]),
      separate_first_(separate_first_modes_[kSloppy]),
      hdr_info_(hdr_info)
{
    part_info_.VerifyAndAllocateFragmentationHeader(1);
    part_info_.fragmentationLength[0] = payload_size;
    part_info_.fragmentationOffset[0] = 0;
}

int RtpFormatVp8::CalcNextSize(int max_payload_len, int remaining_bytes,
                               bool split_payload) const
{
    if (max_payload_len == 0 || remaining_bytes == 0)
    {
        return 0;
    }
    if (!split_payload)
    {
        return max_payload_len >= remaining_bytes ? remaining_bytes : 0;
    }

    if (balance_)
    {
        // Balance payload sizes to produce (almost) equal size
        // fragments.
        // Number of fragments for remaining_bytes:
        int num_frags = remaining_bytes / max_payload_len + 1;
        // Number of bytes in this fragment:
        return static_cast<int>(static_cast<double>(remaining_bytes)
            / num_frags + 0.5);
    }
    else
    {
        return max_payload_len >= remaining_bytes ? remaining_bytes
            : max_payload_len;
    }
}

int RtpFormatVp8::NextPacket(int max_payload_len, WebRtc_UWord8* buffer,
                             int* bytes_to_send, bool* last_packet)
{
    const int num_partitions = part_info_.fragmentationVectorSize;
    int send_bytes = 0; // How much data to send in this packet.
    bool split_payload = true; // Splitting of partitions is initially allowed.
    int remaining_in_partition = part_info_.fragmentationOffset[part_ix_] -
        payload_bytes_sent_ + part_info_.fragmentationLength[part_ix_] +
        FirstHeaderExtraLength(); // Add header extra length to payload length.
    int rem_payload_len = max_payload_len - vp8_header_bytes_;

    while (int next_size = CalcNextSize(rem_payload_len, remaining_in_partition,
        split_payload))
    {
        send_bytes += next_size;
        rem_payload_len -= next_size;
        remaining_in_partition -= next_size;

        if (remaining_in_partition == 0 && !(beginning_ && separate_first_))
        {
            // Advance to next partition?
            // Check that there are more partitions; verify that we are either
            // allowed to aggregate fragments, or that we are allowed to
            // aggregate intact partitions and that we started this packet
            // with an intact partition (indicated by first_fragment_ == true).
            if (part_ix_ + 1 < num_partitions &&
                ((aggr_mode_ == kAggrFragments) ||
                 (aggr_mode_ == kAggrPartitions && first_fragment_)))
            {
                remaining_in_partition
                    = part_info_.fragmentationLength[++part_ix_];
                // Disallow splitting unless kAggrFragments. In kAggrPartitions,
                // we can only aggregate intact partitions.
                split_payload = (aggr_mode_ == kAggrFragments);
            }
        }
        else if (balance_ && remaining_in_partition > 0)
        {
            break;
        }
    }
    if (remaining_in_partition == 0)
    {
        ++part_ix_; // Advance to next partition.
    }

    send_bytes -= FirstHeaderExtraLength(); // Remove the extra length again.
    assert(send_bytes > 0);
    const bool end_of_fragment = (remaining_in_partition == 0);
    // Write the payload header and the payload to buffer.
    *bytes_to_send = WriteHeaderAndPayload(send_bytes, end_of_fragment, buffer,
        max_payload_len);
    if (*bytes_to_send < 0)
    {
        return -1;
    }

    *last_packet = (payload_bytes_sent_ >= payload_size_);
    assert(!*last_packet || (payload_bytes_sent_ == payload_size_));
    return 0;
}

int RtpFormatVp8::WriteHeaderAndPayload(int payload_bytes,
                                        bool end_of_fragment,
                                        WebRtc_UWord8* buffer,
                                        int buffer_length)
{
    // Write the VP8 payload header.
    //  0                   1                   2
    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    // | RSV |I|N|FI |B|   PictureID (1 or 2 octets)   |
    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    if (payload_bytes < 0)
    {
        return -1;
    }
    if (payload_bytes_sent_ + payload_bytes > payload_size_)
    {
        return -1;
    }

    buffer[0] = 0;
    if (hdr_info_.nonReference) buffer[0] |= (0x01 << 3); // N
    if (!first_fragment_)       buffer[0] |= (0x01 << 2); // FI
    if (!end_of_fragment)       buffer[0] |= (0x01 << 1); // FI
    if (beginning_)             buffer[0] |= 0x01; // B

    int pic_id_len = WritePictureID(&buffer[vp8_header_bytes_],
        buffer_length - vp8_header_bytes_);
    if (pic_id_len < 0) return pic_id_len; // error
    if (pic_id_len > 0) buffer[0] |= (0x01 << 4); // I

    if (vp8_header_bytes_ + pic_id_len + payload_bytes > buffer_length)
    {
        return -1;
    }
    memcpy(&buffer[vp8_header_bytes_ + pic_id_len],
        &payload_data_[payload_bytes_sent_], payload_bytes);

    beginning_ = false; // next packet cannot be first packet in frame
    // next packet starts new fragment if this ended one
    first_fragment_ = end_of_fragment;
    payload_bytes_sent_ += payload_bytes;

    // Return total length of written data.
    return payload_bytes + vp8_header_bytes_ + pic_id_len;
}

int RtpFormatVp8::WritePictureID(WebRtc_UWord8* buffer, int buffer_length) const
{
    const WebRtc_UWord16 pic_id =
        static_cast<WebRtc_UWord16> (hdr_info_.pictureId);
    int picture_id_len = PictureIdLength();
    if (picture_id_len > buffer_length) return -1; // error
    if (picture_id_len == 2)
    {
        buffer[0] = 0x80 | ((pic_id >> 8) & 0x7F);
        buffer[1] = pic_id & 0xFF;
    }
    else if (picture_id_len == 1)
    {
        buffer[0] = pic_id & 0x7F;
    }
    return picture_id_len;
}

int RtpFormatVp8::FirstHeaderExtraLength() const
{
    if (!beginning_)
    {
        return 0;
    }
    int length = 0;

    length += PictureIdLength();

    return length;
}

int RtpFormatVp8::PictureIdLength() const
{
    if (!beginning_ || hdr_info_.pictureId == kNoPictureId)
    {
        return 0;
    }
    if (hdr_info_.pictureId <= 0x7F)
    {
        return 1;
    }
    else
    {
        return 2;
    }
}

} // namespace webrtc
<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <boost/concept_check.hpp>
#include <opencv2/core.hpp>
#include <opencv2/core/affine.hpp>

namespace cv
{
    typedef std::string String;

    namespace viz
    {
        class CV_EXPORTS Color : public Scalar
        {
        public:
            Color();
            Color(double gray);
            Color(double blue, double green, double red);

            Color(const Scalar& color);

            static Color black();
            static Color blue();
            static Color green();
            static Color cyan();

            static Color red();
            static Color magenta();
            static Color yellow();
            static Color white();

            static Color gray();
        };

        class CV_EXPORTS Mesh3d
        {
        public:

            Mat cloud, colors;
            Mat polygons;

            static cv::viz::Mesh3d loadMesh(const String& file);

        private:
            struct loadMeshImpl;
        };

        class CV_EXPORTS KeyboardEvent
        {
        public:
            static const unsigned int Alt   = 1;
            static const unsigned int Ctrl  = 2;
            static const unsigned int Shift = 4;

            /** \brief Constructor
              * \param[in] action    true for key was pressed, false for released
              * \param[in] key_sym   the key-name that caused the action
              * \param[in] key       the key code that caused the action
              * \param[in] alt       whether the alt key was pressed at the time where this event was triggered
              * \param[in] ctrl      whether the ctrl was pressed at the time where this event was triggered
              * \param[in] shift     whether the shift was pressed at the time where this event was triggered
              */
            KeyboardEvent (bool action, const std::string& key_sym, unsigned char key, bool alt, bool ctrl, bool shift);

            bool isAltPressed () const;
            bool isCtrlPressed () const;
            bool isShiftPressed () const;

            unsigned char getKeyCode () const;

            const String& getKeySym () const;
            bool keyDown () const;
            bool keyUp () const;

        protected:

            bool action_;
            unsigned int modifiers_;
            unsigned char key_code_;
            String key_sym_;
        };

        class CV_EXPORTS MouseEvent
        {
        public:
            enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ;
            enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ;

            MouseEvent (const Type& type, const MouseButton& button, const Point& p, bool alt, bool ctrl, bool shift);

            Type type;
            MouseButton button;
            Point pointer;
            unsigned int key_state;
        };

        class CV_EXPORTS Camera2
        {
        public:
            Camera2(float f_x, float f_y, float c_x, float c_y, const Size &window_size);
            Camera2(const Vec2f &fov, const Size &window_size);
            Camera2(const cv::Mat &K, const Size &window_size);

            inline const Vec2d & getClip() const { return clip_; }
            inline void setClip(const Vec2d &clip) { clip_ = clip; }

            inline const Size & getWindowSize() const { return window_size_; }
            void setWindowSize(const Size &window_size);

            inline const Vec2f & getFov() const { return fov_; }
            inline void setFov(const Vec2f & fov) { fov_ = fov; }

        private:
            Vec2d clip_;
            Vec2f fov_;
            Size window_size_;
            Vec2f principal_point_;
            Vec2f focal_;
        };

    } /* namespace viz */
} /* namespace cv */
<commit_msg>remove boost include (caused by Kdevelop autocomplete)<commit_after>#pragma once

#include <string>
#include <opencv2/core.hpp>
#include <opencv2/core/affine.hpp>

namespace cv
{
    typedef std::string String;

    namespace viz
    {
        class CV_EXPORTS Color : public Scalar
        {
        public:
            Color();
            Color(double gray);
            Color(double blue, double green, double red);

            Color(const Scalar& color);

            static Color black();
            static Color blue();
            static Color green();
            static Color cyan();

            static Color red();
            static Color magenta();
            static Color yellow();
            static Color white();

            static Color gray();
        };

        class CV_EXPORTS Mesh3d
        {
        public:

            Mat cloud, colors;
            Mat polygons;

            static cv::viz::Mesh3d loadMesh(const String& file);

        private:
            struct loadMeshImpl;
        };

        class CV_EXPORTS KeyboardEvent
        {
        public:
            static const unsigned int Alt   = 1;
            static const unsigned int Ctrl  = 2;
            static const unsigned int Shift = 4;

            /** \brief Constructor
              * \param[in] action    true for key was pressed, false for released
              * \param[in] key_sym   the key-name that caused the action
              * \param[in] key       the key code that caused the action
              * \param[in] alt       whether the alt key was pressed at the time where this event was triggered
              * \param[in] ctrl      whether the ctrl was pressed at the time where this event was triggered
              * \param[in] shift     whether the shift was pressed at the time where this event was triggered
              */
            KeyboardEvent (bool action, const std::string& key_sym, unsigned char key, bool alt, bool ctrl, bool shift);

            bool isAltPressed () const;
            bool isCtrlPressed () const;
            bool isShiftPressed () const;

            unsigned char getKeyCode () const;

            const String& getKeySym () const;
            bool keyDown () const;
            bool keyUp () const;

        protected:

            bool action_;
            unsigned int modifiers_;
            unsigned char key_code_;
            String key_sym_;
        };

        class CV_EXPORTS MouseEvent
        {
        public:
            enum Type { MouseMove = 1, MouseButtonPress, MouseButtonRelease, MouseScrollDown, MouseScrollUp, MouseDblClick } ;
            enum MouseButton { NoButton = 0, LeftButton, MiddleButton, RightButton, VScroll } ;

            MouseEvent (const Type& type, const MouseButton& button, const Point& p, bool alt, bool ctrl, bool shift);

            Type type;
            MouseButton button;
            Point pointer;
            unsigned int key_state;
        };

        class CV_EXPORTS Camera2
        {
        public:
            Camera2(float f_x, float f_y, float c_x, float c_y, const Size &window_size);
            Camera2(const Vec2f &fov, const Size &window_size);
            Camera2(const cv::Mat &K, const Size &window_size);

            inline const Vec2d & getClip() const { return clip_; }
            inline void setClip(const Vec2d &clip) { clip_ = clip; }

            inline const Size & getWindowSize() const { return window_size_; }
            void setWindowSize(const Size &window_size);

            inline const Vec2f & getFov() const { return fov_; }
            inline void setFov(const Vec2f & fov) { fov_ = fov; }

        private:
            Vec2d clip_;
            Vec2f fov_;
            Size window_size_;
            Vec2f principal_point_;
            Vec2f focal_;
        };

    } /* namespace viz */
} /* namespace cv */
<|endoftext|>


<commit_before>// SciTE - Scintilla based Text Editor
// LexCPP.cxx - lexer for C++, C, Java, and Javascript
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static bool classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
	char s[100];
	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
	}
	bool wordIsUUID = false;
	char chAttr = SCE_C_IDENTIFIER;
	if (isdigit(s[0]) || (s[0] == '.'))
		chAttr = SCE_C_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_C_WORD;
			wordIsUUID = strcmp(s, "uuid") == 0;
		}
	}
	styler.ColourTo(end, chAttr);
	return wordIsUUID;
}

static bool isOKBeforeRE(char ch) {
	return (ch == '(') || (ch == '=') || (ch == ',');
}

static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);

	bool fold = styler.GetPropertyInt("fold");
	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor");
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;

	int state = initStyle;
	if (state == SCE_C_STRINGEOL)	// Does not leak onto next line
		state = SCE_C_DEFAULT;
	char chPrev = ' ';
	char chNext = styler[startPos];
	char chPrevNonWhite = ' ';
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	styler.StartSegment(startPos);
	bool lastWordWasUUID = false;
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
			// Avoid triggering two times on Dos/Win
			// End of line
			if (state == SCE_C_STRINGEOL) {
				styler.ColourTo(i, state);
				state = SCE_C_DEFAULT;
			}
			if (fold) {
				int lev = levelPrev;
				if (visibleChars == 0)
					lev |= SC_FOLDLEVELWHITEFLAG;
				if ((levelCurrent > levelPrev) && (visibleChars > 0))
					lev |= SC_FOLDLEVELHEADERFLAG;
				styler.SetLevel(lineCurrent, lev);
				lineCurrent++;
				levelPrev = levelCurrent;
			}
			visibleChars = 0;
		}
		if (!isspace(ch))
			visibleChars++;

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_C_DEFAULT) {
			if (ch == '@' && chNext == '\"') {
				styler.ColourTo(i-1, state);
				state = SCE_C_VERBATIM;
				i++;
				ch = chNext;
				chNext = styler.SafeGetCharAt(i + 1);
			} else if (iswordstart(ch) || (ch == '@')) {
				styler.ColourTo(i-1, state);
				if (lastWordWasUUID) {
					state = SCE_C_UUID;
					lastWordWasUUID = false;
				} else {
					state = SCE_C_IDENTIFIER;
				}
			} else if (ch == '/' && chNext == '*') {
				styler.ColourTo(i-1, state);
				if (styler.SafeGetCharAt(i + 2) == '*')
					state = SCE_C_COMMENTDOC;
				else
					state = SCE_C_COMMENT;
			} else if (ch == '/' && chNext == '/') {
				styler.ColourTo(i-1, state);
				state = SCE_C_COMMENTLINE;
			} else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) {
				styler.ColourTo(i-1, state);
				state = SCE_C_REGEX;
			} else if (ch == '\"') {
				styler.ColourTo(i-1, state);
				state = SCE_C_STRING;
			} else if (ch == '\'') {
				styler.ColourTo(i-1, state);
				state = SCE_C_CHARACTER;
			} else if (ch == '#' && visibleChars == 1) {
				// Preprocessor commands are alone on their line
				styler.ColourTo(i-1, state);
				state = SCE_C_PREPROCESSOR;
				// Skip whitespace between # and preprocessor word
				do {
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				} while (isspace(ch) && (i < lengthDoc));
			} else if (isoperator(ch)) {
				styler.ColourTo(i-1, state);
				styler.ColourTo(i, SCE_C_OPERATOR);
				if ((ch == '{') || (ch == '}')) {
					levelCurrent += (ch == '{') ? 1 : -1;
				}
			}
		} else if (state == SCE_C_IDENTIFIER) {
			if (!iswordchar(ch)) {
				lastWordWasUUID = classifyWordCpp(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_C_DEFAULT;
				if (ch == '/' && chNext == '*') {
					if (styler.SafeGetCharAt(i + 2) == '*')
						state = SCE_C_COMMENTDOC;
					else
						state = SCE_C_COMMENT;
				} else if (ch == '/' && chNext == '/') {
					state = SCE_C_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_C_STRING;
				} else if (ch == '\'') {
					state = SCE_C_CHARACTER;
				} else if (isoperator(ch)) {
					styler.ColourTo(i, SCE_C_OPERATOR);
					if ((ch == '{') || (ch == '}')) {
						levelCurrent += (ch == '{') ? 1 : -1;
					}
				}
			}
		} else {
			if (state == SCE_C_PREPROCESSOR) {
				if (stylingWithinPreprocessor) {
					if (isspace(ch)) {
						styler.ColourTo(i-1, state);
						state = SCE_C_DEFAULT;
					}
				} else {
					if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
						styler.ColourTo(i-1, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENT) {
				if (ch == '/' && chPrev == '*') {
					if (((i > styler.GetStartSegment() + 2) || (
						(initStyle == SCE_C_COMMENT) &&
						(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTDOC) {
				if (ch == '/' && chPrev == '*') {
					if (((i > styler.GetStartSegment() + 2) || (
						(initStyle == SCE_C_COMMENTDOC) &&
						(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTLINE) {
				if (ch == '\r' || ch == '\n') {
					styler.ColourTo(i-1, state);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_STRING) {
				if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				} else if ((chNext == '\r' || chNext == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i-1, SCE_C_STRINGEOL);
					state = SCE_C_STRINGEOL;
				}
			} else if (state == SCE_C_CHARACTER) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i-1, SCE_C_STRINGEOL);
					state = SCE_C_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\'') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_REGEX) {
				if (ch == '\r' || ch == '\n' || ch == '/') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				} else if (ch == '\\') {
					// Gobble up the quoted character
					if (chNext == '\\' || chNext == '/') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				}
			} else if (state == SCE_C_VERBATIM) {
				if (ch == '\"') {
					if (chNext == '\"') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					} else {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_UUID) {
				if (ch == '\r' || ch == '\n' || ch == ')') {
					styler.ColourTo(i-1, state);
					if (ch == ')')
						styler.ColourTo(i, SCE_C_OPERATOR);
					state = SCE_C_DEFAULT;
				}
			}
		}
		chPrev = ch;
		if (ch != ' ' && ch != '\t')
			chPrevNonWhite = ch;
	}
	styler.ColourTo(lengthDoc - 1, state);

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	if (fold) {
		int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
		//styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
		styler.SetLevel(lineCurrent, levelPrev | flagsNext);

	}
}

LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc);
<commit_msg>Addition of SCE_C_COMMENTLINEDOC by Philippe.<commit_after>// SciTE - Scintilla based Text Editor
// LexCPP.cxx - lexer for C++, C, Java, and Javascript
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static bool classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
	char s[100];
	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
	}
	bool wordIsUUID = false;
	char chAttr = SCE_C_IDENTIFIER;
	if (isdigit(s[0]) || (s[0] == '.'))
		chAttr = SCE_C_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_C_WORD;
			wordIsUUID = strcmp(s, "uuid") == 0;
		}
	}
	styler.ColourTo(end, chAttr);
	return wordIsUUID;
}

static bool isOKBeforeRE(char ch) {
	return (ch == '(') || (ch == '=') || (ch == ',');
}

static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);

	bool fold = styler.GetPropertyInt("fold");
	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor");
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;

	int state = initStyle;
	if (state == SCE_C_STRINGEOL)	// Does not leak onto next line
		state = SCE_C_DEFAULT;
	char chPrev = ' ';
	char chNext = styler[startPos];
	char chPrevNonWhite = ' ';
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	styler.StartSegment(startPos);
	bool lastWordWasUUID = false;
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
			// Avoid triggering two times on Dos/Win
			// End of line
			if (state == SCE_C_STRINGEOL) {
				styler.ColourTo(i, state);
				state = SCE_C_DEFAULT;
			}
			if (fold) {
				int lev = levelPrev;
				if (visibleChars == 0)
					lev |= SC_FOLDLEVELWHITEFLAG;
				if ((levelCurrent > levelPrev) && (visibleChars > 0))
					lev |= SC_FOLDLEVELHEADERFLAG;
				styler.SetLevel(lineCurrent, lev);
				lineCurrent++;
				levelPrev = levelCurrent;
			}
			visibleChars = 0;
		}
		if (!isspace(ch))
			visibleChars++;

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_C_DEFAULT) {
			if (ch == '@' && chNext == '\"') {
				styler.ColourTo(i-1, state);
				state = SCE_C_VERBATIM;
				i++;
				ch = chNext;
				chNext = styler.SafeGetCharAt(i + 1);
			} else if (iswordstart(ch) || (ch == '@')) {
				styler.ColourTo(i-1, state);
				if (lastWordWasUUID) {
					state = SCE_C_UUID;
					lastWordWasUUID = false;
				} else {
					state = SCE_C_IDENTIFIER;
				}
			} else if (ch == '/' && chNext == '*') {
				styler.ColourTo(i-1, state);
				if (styler.SafeGetCharAt(i + 2) == '*' ||
					styler.SafeGetCharAt(i + 2) == '!')	// Support of Qt/Doxygen doc. style
					state = SCE_C_COMMENTDOC;
				else
					state = SCE_C_COMMENT;
			} else if (ch == '/' && chNext == '/') {
				styler.ColourTo(i-1, state);
				if (styler.SafeGetCharAt(i + 2) == '/' ||
					styler.SafeGetCharAt(i + 2) == '!')	// Support of Qt/Doxygen doc. style
					state = SCE_C_COMMENTLINEDOC;
				else
				state = SCE_C_COMMENTLINE;
			} else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) {
				styler.ColourTo(i-1, state);
				state = SCE_C_REGEX;
			} else if (ch == '\"') {
				styler.ColourTo(i-1, state);
				state = SCE_C_STRING;
			} else if (ch == '\'') {
				styler.ColourTo(i-1, state);
				state = SCE_C_CHARACTER;
			} else if (ch == '#' && visibleChars == 1) {
				// Preprocessor commands are alone on their line
				styler.ColourTo(i-1, state);
				state = SCE_C_PREPROCESSOR;
				// Skip whitespace between # and preprocessor word
				do {
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				} while (isspace(ch) && (i < lengthDoc));
			} else if (isoperator(ch)) {
				styler.ColourTo(i-1, state);
				styler.ColourTo(i, SCE_C_OPERATOR);
				if ((ch == '{') || (ch == '}')) {
					levelCurrent += (ch == '{') ? 1 : -1;
				}
			}
		} else if (state == SCE_C_IDENTIFIER) {
			if (!iswordchar(ch)) {
				lastWordWasUUID = classifyWordCpp(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_C_DEFAULT;
				if (ch == '/' && chNext == '*') {
					if (styler.SafeGetCharAt(i + 2) == '*')
						state = SCE_C_COMMENTDOC;
					else
						state = SCE_C_COMMENT;
				} else if (ch == '/' && chNext == '/') {
					state = SCE_C_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_C_STRING;
				} else if (ch == '\'') {
					state = SCE_C_CHARACTER;
				} else if (isoperator(ch)) {
					styler.ColourTo(i, SCE_C_OPERATOR);
					if ((ch == '{') || (ch == '}')) {
						levelCurrent += (ch == '{') ? 1 : -1;
					}
				}
			}
		} else {
			if (state == SCE_C_PREPROCESSOR) {
				if (stylingWithinPreprocessor) {
					if (isspace(ch)) {
						styler.ColourTo(i-1, state);
						state = SCE_C_DEFAULT;
					}
				} else {
					if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
						styler.ColourTo(i-1, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENT) {
				if (ch == '/' && chPrev == '*') {
					if (((i > styler.GetStartSegment() + 2) || (
						(initStyle == SCE_C_COMMENT) &&
						(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTDOC) {
				if (ch == '/' && chPrev == '*') {
					if (((i > styler.GetStartSegment() + 2) || (
						(initStyle == SCE_C_COMMENTDOC) &&
						(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTLINE || state == SCE_C_COMMENTLINEDOC) {
				if (ch == '\r' || ch == '\n') {
					styler.ColourTo(i-1, state);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_STRING) {
				if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				} else if ((chNext == '\r' || chNext == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i-1, SCE_C_STRINGEOL);
					state = SCE_C_STRINGEOL;
				}
			} else if (state == SCE_C_CHARACTER) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i-1, SCE_C_STRINGEOL);
					state = SCE_C_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\'') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_REGEX) {
				if (ch == '\r' || ch == '\n' || ch == '/') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				} else if (ch == '\\') {
					// Gobble up the quoted character
					if (chNext == '\\' || chNext == '/') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				}
			} else if (state == SCE_C_VERBATIM) {
				if (ch == '\"') {
					if (chNext == '\"') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					} else {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_UUID) {
				if (ch == '\r' || ch == '\n' || ch == ')') {
					styler.ColourTo(i-1, state);
					if (ch == ')')
						styler.ColourTo(i, SCE_C_OPERATOR);
					state = SCE_C_DEFAULT;
				}
			}
		}
		chPrev = ch;
		if (ch != ' ' && ch != '\t')
			chPrevNonWhite = ch;
	}
	styler.ColourTo(lengthDoc - 1, state);

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	if (fold) {
		int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
		//styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
		styler.SetLevel(lineCurrent, levelPrev | flagsNext);

	}
}

LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc);
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexSML.cxx
 ** Lexer for SML.
 **/
// Copyright 2009 by James Moffatt and Yuzhou Xin
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

inline int  issml(int c) {return isalnum(c) || c == '_';}
inline int issmlf(int c) {return isalpha(c) || c == '_';}
inline int issmld(int c) {return isdigit(c) || c == '_';}

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

void ColouriseSMLDoc(
	unsigned int startPos, int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler)
{
	StyleContext sc(startPos, length, initStyle, styler);
	int nesting = 0;
	if (sc.state < SCE_SML_STRING)
		sc.state = SCE_SML_DEFAULT;
	if (sc.state >= SCE_SML_COMMENT)
		nesting = (sc.state & 0x0f) - SCE_SML_COMMENT;

	int chBase = 0, chToken = 0, chLit = 0;
	WordList& keywords  = *keywordlists[0];
	WordList& keywords2 = *keywordlists[1];
	WordList& keywords3 = *keywordlists[2];
	const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0);

	while (sc.More()) {
		int state2 = -1;
		int chColor = sc.currentPos - 1;
		bool advance = true;

		switch (sc.state & 0x0f) {
		case SCE_SML_DEFAULT:
			chToken = sc.currentPos;
			if (issmlf(sc.ch))
				state2 = SCE_SML_IDENTIFIER;
			else if (sc.Match('`') && issmlf(sc.chNext))
				state2 = SCE_SML_TAGNAME;
			else if (sc.Match('#')&&isdigit(sc.chNext))
					state2 = SCE_SML_LINENUM;
			else if (sc.Match('#','\"')){
					state2 = SCE_SML_CHAR,chLit = 0;
					sc.Forward();

				}
			else if (isdigit(sc.ch)) {
				state2 = SCE_SML_NUMBER, chBase = 10;
				if (sc.Match('0') && strchr("xX", sc.chNext))
					chBase = 16, sc.Forward();}
			else if (sc.Match('\"')&&sc.chPrev!='#')
				state2 = SCE_SML_STRING;
			else if (sc.Match('(', '*')){
				state2 = SCE_SML_COMMENT,
					sc.ch = ' ',
					sc.Forward();}
			else if (strchr("!~"
					"=<>@^+-*/"
					"()[];,:.#", sc.ch))
				state2 = SCE_SML_OPERATOR;
			break;

		case SCE_SML_IDENTIFIER:
			if (!(issml(sc.ch) || sc.Match('\''))) {
				const int n = sc.currentPos - chToken;
				if (n < 24) {
					char t[24];
					for (int i = -n; i < 0; i++)
						t[n + i] = static_cast<char>(sc.GetRelative(i));
					t[n] = '\0';
					if ((n == 1 && sc.chPrev == '_') || keywords.InList(t))
						sc.ChangeState(SCE_SML_KEYWORD);
					else if (keywords2.InList(t))
						sc.ChangeState(SCE_SML_KEYWORD2);
					else if (keywords3.InList(t))
						sc.ChangeState(SCE_SML_KEYWORD3);
				}
				state2 = SCE_SML_DEFAULT, advance = false;
			}
			break;

		case SCE_SML_TAGNAME:
			if (!(issml(sc.ch) || sc.Match('\'')))
				state2 = SCE_SML_DEFAULT, advance = false;
			break;

		case SCE_SML_LINENUM:
			if (!isdigit(sc.ch))
				state2 = SCE_SML_DEFAULT, advance = false;
			break;

		case SCE_SML_OPERATOR: {
			const char* o = 0;
			if (issml(sc.ch) || isspace(sc.ch)
				|| (o = strchr(")]};,\'\"`#", sc.ch),o)
				|| !strchr("!$%&*+-./:<=>?@^|~", sc.ch)) {
				if (o && strchr(")]};,", sc.ch)) {
					if ((sc.Match(')') && sc.chPrev == '(')
						|| (sc.Match(']') && sc.chPrev == '['))
						sc.ChangeState(SCE_SML_KEYWORD);
					chColor++;
				} else
					advance = false;
				state2 = SCE_SML_DEFAULT;
			}
			break;
		}

		case SCE_SML_NUMBER:
			if (issmld(sc.ch) || IsADigit(sc.ch, chBase))
				break;
			if ((sc.Match('l') || sc.Match('L') || sc.Match('n'))
				&& (issmld(sc.chPrev) || IsADigit(sc.chPrev, chBase)))
				break;
			if (chBase == 10) {
				if (sc.Match('.') && issmld(sc.chPrev))
					break;
				if ((sc.Match('e') || sc.Match('E'))
					&& (issmld(sc.chPrev) || sc.chPrev == '.'))
					break;
				if ((sc.Match('+') || sc.Match('-'))
					&& (sc.chPrev == 'e' || sc.chPrev == 'E'))
					break;
			}
			state2 = SCE_SML_DEFAULT, advance = false;
			break;

		case SCE_SML_CHAR:
			if (sc.Match('\\')) {
				chLit = 1;
				if (sc.chPrev == '\\')
					sc.ch = ' ';
			} else if ((sc.Match('\"') && sc.chPrev != '\\') || sc.atLineEnd) {
				state2 = SCE_SML_DEFAULT;
				chLit = 1;
				if (sc.Match('\"'))
					chColor++;
				else
					sc.ChangeState(SCE_SML_IDENTIFIER);
			} else if (chLit < 1 && sc.currentPos - chToken >= 3)
				sc.ChangeState(SCE_SML_IDENTIFIER), advance = false;
			break;

		case SCE_SML_STRING:
			if (sc.Match('\\') && sc.chPrev == '\\')
				sc.ch = ' ';
			else if (sc.Match('\"') && sc.chPrev != '\\')
				state2 = SCE_SML_DEFAULT, chColor++;
			break;

		case SCE_SML_COMMENT:
		case SCE_SML_COMMENT1:
		case SCE_SML_COMMENT2:
		case SCE_SML_COMMENT3:
			if (sc.Match('(', '*'))
				state2 = sc.state + 1, chToken = sc.currentPos,
					sc.ch = ' ',
					sc.Forward(), nesting++;
			else if (sc.Match(')') && sc.chPrev == '*') {
				if (nesting)
					state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--;
				else
					state2 = SCE_SML_DEFAULT;
				chColor++;
			} else if (useMagic && sc.currentPos - chToken == 4
				&& sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@')
				sc.state |= 0x10;
			break;
		}

		if (state2 >= 0)
			styler.ColourTo(chColor, sc.state), sc.ChangeState(state2);
		if (advance)
			sc.Forward();
	}

	sc.Complete();
}

void FoldSMLDoc(
	unsigned int startPos, int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler)
{
	//supress "not used" warnings
	startPos || length || initStyle || keywordlists[0] || styler.Length();
}

static const char * const SMLWordListDesc[] = {
	"Keywords",
	"Keywords2",
	"Keywords3",
	0
};

LexerModule lmSML(SCLEX_SML, ColouriseSMLDoc, "SML", FoldSMLDoc, SMLWordListDesc);

<commit_msg>Credit to original author.<commit_after>// Scintilla source code edit control
/** @file LexSML.cxx
 ** Lexer for SML.
 **/
// Copyright 2009 by James Moffatt and Yuzhou Xin
// Modified from LexCaml.cxx by Robert Roessler <robertr@rftp.com> Copyright 2005
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

inline int  issml(int c) {return isalnum(c) || c == '_';}
inline int issmlf(int c) {return isalpha(c) || c == '_';}
inline int issmld(int c) {return isdigit(c) || c == '_';}

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

void ColouriseSMLDoc(
	unsigned int startPos, int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler)
{
	StyleContext sc(startPos, length, initStyle, styler);
	int nesting = 0;
	if (sc.state < SCE_SML_STRING)
		sc.state = SCE_SML_DEFAULT;
	if (sc.state >= SCE_SML_COMMENT)
		nesting = (sc.state & 0x0f) - SCE_SML_COMMENT;

	int chBase = 0, chToken = 0, chLit = 0;
	WordList& keywords  = *keywordlists[0];
	WordList& keywords2 = *keywordlists[1];
	WordList& keywords3 = *keywordlists[2];
	const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0);

	while (sc.More()) {
		int state2 = -1;
		int chColor = sc.currentPos - 1;
		bool advance = true;

		switch (sc.state & 0x0f) {
		case SCE_SML_DEFAULT:
			chToken = sc.currentPos;
			if (issmlf(sc.ch))
				state2 = SCE_SML_IDENTIFIER;
			else if (sc.Match('`') && issmlf(sc.chNext))
				state2 = SCE_SML_TAGNAME;
			else if (sc.Match('#')&&isdigit(sc.chNext))
					state2 = SCE_SML_LINENUM;
			else if (sc.Match('#','\"')){
					state2 = SCE_SML_CHAR,chLit = 0;
					sc.Forward();

				}
			else if (isdigit(sc.ch)) {
				state2 = SCE_SML_NUMBER, chBase = 10;
				if (sc.Match('0') && strchr("xX", sc.chNext))
					chBase = 16, sc.Forward();}
			else if (sc.Match('\"')&&sc.chPrev!='#')
				state2 = SCE_SML_STRING;
			else if (sc.Match('(', '*')){
				state2 = SCE_SML_COMMENT,
					sc.ch = ' ',
					sc.Forward();}
			else if (strchr("!~"
					"=<>@^+-*/"
					"()[];,:.#", sc.ch))
				state2 = SCE_SML_OPERATOR;
			break;

		case SCE_SML_IDENTIFIER:
			if (!(issml(sc.ch) || sc.Match('\''))) {
				const int n = sc.currentPos - chToken;
				if (n < 24) {
					char t[24];
					for (int i = -n; i < 0; i++)
						t[n + i] = static_cast<char>(sc.GetRelative(i));
					t[n] = '\0';
					if ((n == 1 && sc.chPrev == '_') || keywords.InList(t))
						sc.ChangeState(SCE_SML_KEYWORD);
					else if (keywords2.InList(t))
						sc.ChangeState(SCE_SML_KEYWORD2);
					else if (keywords3.InList(t))
						sc.ChangeState(SCE_SML_KEYWORD3);
				}
				state2 = SCE_SML_DEFAULT, advance = false;
			}
			break;

		case SCE_SML_TAGNAME:
			if (!(issml(sc.ch) || sc.Match('\'')))
				state2 = SCE_SML_DEFAULT, advance = false;
			break;

		case SCE_SML_LINENUM:
			if (!isdigit(sc.ch))
				state2 = SCE_SML_DEFAULT, advance = false;
			break;

		case SCE_SML_OPERATOR: {
			const char* o = 0;
			if (issml(sc.ch) || isspace(sc.ch)
				|| (o = strchr(")]};,\'\"`#", sc.ch),o)
				|| !strchr("!$%&*+-./:<=>?@^|~", sc.ch)) {
				if (o && strchr(")]};,", sc.ch)) {
					if ((sc.Match(')') && sc.chPrev == '(')
						|| (sc.Match(']') && sc.chPrev == '['))
						sc.ChangeState(SCE_SML_KEYWORD);
					chColor++;
				} else
					advance = false;
				state2 = SCE_SML_DEFAULT;
			}
			break;
		}

		case SCE_SML_NUMBER:
			if (issmld(sc.ch) || IsADigit(sc.ch, chBase))
				break;
			if ((sc.Match('l') || sc.Match('L') || sc.Match('n'))
				&& (issmld(sc.chPrev) || IsADigit(sc.chPrev, chBase)))
				break;
			if (chBase == 10) {
				if (sc.Match('.') && issmld(sc.chPrev))
					break;
				if ((sc.Match('e') || sc.Match('E'))
					&& (issmld(sc.chPrev) || sc.chPrev == '.'))
					break;
				if ((sc.Match('+') || sc.Match('-'))
					&& (sc.chPrev == 'e' || sc.chPrev == 'E'))
					break;
			}
			state2 = SCE_SML_DEFAULT, advance = false;
			break;

		case SCE_SML_CHAR:
			if (sc.Match('\\')) {
				chLit = 1;
				if (sc.chPrev == '\\')
					sc.ch = ' ';
			} else if ((sc.Match('\"') && sc.chPrev != '\\') || sc.atLineEnd) {
				state2 = SCE_SML_DEFAULT;
				chLit = 1;
				if (sc.Match('\"'))
					chColor++;
				else
					sc.ChangeState(SCE_SML_IDENTIFIER);
			} else if (chLit < 1 && sc.currentPos - chToken >= 3)
				sc.ChangeState(SCE_SML_IDENTIFIER), advance = false;
			break;

		case SCE_SML_STRING:
			if (sc.Match('\\') && sc.chPrev == '\\')
				sc.ch = ' ';
			else if (sc.Match('\"') && sc.chPrev != '\\')
				state2 = SCE_SML_DEFAULT, chColor++;
			break;

		case SCE_SML_COMMENT:
		case SCE_SML_COMMENT1:
		case SCE_SML_COMMENT2:
		case SCE_SML_COMMENT3:
			if (sc.Match('(', '*'))
				state2 = sc.state + 1, chToken = sc.currentPos,
					sc.ch = ' ',
					sc.Forward(), nesting++;
			else if (sc.Match(')') && sc.chPrev == '*') {
				if (nesting)
					state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--;
				else
					state2 = SCE_SML_DEFAULT;
				chColor++;
			} else if (useMagic && sc.currentPos - chToken == 4
				&& sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@')
				sc.state |= 0x10;
			break;
		}

		if (state2 >= 0)
			styler.ColourTo(chColor, sc.state), sc.ChangeState(state2);
		if (advance)
			sc.Forward();
	}

	sc.Complete();
}

void FoldSMLDoc(
	unsigned int startPos, int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler)
{
	//supress "not used" warnings
	startPos || length || initStyle || keywordlists[0] || styler.Length();
}

static const char * const SMLWordListDesc[] = {
	"Keywords",
	"Keywords2",
	"Keywords3",
	0
};

LexerModule lmSML(SCLEX_SML, ColouriseSMLDoc, "SML", FoldSMLDoc, SMLWordListDesc);

<|endoftext|>


<commit_before>/******************************************************************************\
* LuaVariable.hpp                                                              *
* A variable living in a Lua interpreter.                                      *
* Leandro Motta Barros                                                         *
\******************************************************************************/

#ifndef _DILUCULUM_LUA_VARIABLE_HPP_
#define _DILUCULUM_LUA_VARIABLE_HPP_

#include <vector>
#include "LuaValue.hpp"

namespace Diluculum
{
   /** A variable living in a Lua state. Notice the crucial difference: unlike a
    *  \c LuaValue, a \c LuaVariable necessarily has a real counterpart in a Lua
    *  state. Thus, when something is assigned to a \c LuaVariable, the value of
    *  the corresponding variable in the Lua state is changed, too.
    *
<tt>LuaVariable</tt>s cannot be directly constructed. They are
    *  designed to be returned by <tt>LuaState</tt>'s subscript operator.
    */
   class LuaVariable
   {
      friend class LuaState;

      public:
         /** Assigns a new value to this \c LuaVariable. The corresponding
          *  variable in the Lua state is updated accordingly.
          *  @note Notice that this is the assignment of a new value to a
          *        variable. The user is also allowed to assign a
          *        \c LuaVariable to another \c LuaVariable (using the
          *        compiler-generated assignment operator). In that case, the
          *        \c LuaVariable at the left hand side will refer to the same
          *        variable as the \c LuaVariable at the right hand side, but no
          *        values will be changed.
          *  @param rhs The new value for the variable.
          *  @return \c rhs, so that a sequence of assignments, like
          *          <tt>a = b = c = 1;</tt> works. Actually, returning
          *          \c rhs is the same as returning <tt>this->value()</tt>,
          *          that perhaps make more sense.
          *  @todo There is a <tt>throw LuaError ("Duh.");</tt> statement in the
          *        implementation. This is ridiculous, and (worse!) the
          *        exception is not documented. Bad, uh?
          */
         const LuaValue& operator= (const LuaValue& rhs);

         /** Returns the value associated with this variable. If the variable
          *  does not exist, returns \c Nil.
          *  @throw TypeMismatchError If this \c LuaVariable tries to subscript
          *         something that is not a table.
          */
         LuaValue value() const;

         /** Assuming that this \c LuaVariable holds a table, returns the value
          *  whose index is \c key.
          *  @param key The key whose value is desired.
          *  @return The value whose index is \c key.
          *  @note This method doesn't throw anything, even if this
          *        \c LuaVariable doesn't hold a table. But an exception will
          *        be thrown if one tries to access the value of the returned
          *        variable (see \c value()).
          */
         LuaVariable operator[] (const LuaValue& key) const;

         /** Checks whether the value stored in this variable is equal to the
          *  value at \c rhs.
          *  @param rhs The value against which the comparison will be done.
          *  @return \c true if this variable's value is equal to \c rhs.
          *          \c false otherwise.
          *  @throw TypeMismatchError If this \c LuaVariable tries to subscript
          *         something that is not a table.
          */
         bool operator== (const LuaValue& rhs) const
         { return value() == rhs; }

         /** Checks whether this \c LuaVariable refers to the same variable as
          *  \c rhs.
          *  @param rhs The variable against which the comparison will be done.
          *  @return \c true if both involved <tt>LuaVariable</tt>s refer to the
          *          same variable. \c false otherwise.
          */
         bool operator== (const LuaVariable& rhs) const
         { return state_ == rhs.state_ && keys_ == rhs.keys_; }

         /** Checks whether this \c LuaVariable refers to a different variable
          *  than \c rhs.
          *  @param rhs The variable against which the comparison will be done.
          *  @return \c false if both involved <tt>LuaVariable</tt>s refer to the
          *          same variable. \c true otherwise.
          */
         bool operator!= (const LuaVariable& rhs) const
         { return state_ != rhs.state_ || keys_ != rhs.keys_; }

      private:
         /// A sequence of keys, used to access nested tables.
         typedef std::vector<LuaValue> KeyList;

         /** Constructs a \c LuaVariable.
          *   @note This is private because no one is expected to construct a
          *         \c LuaVariable directly. For Diluculum users, the only
          *         allowed way to create a new \c LuaVariable is by using
          *         <tt>LuaState</tt>'s subscript operator.
          *   @param state The <tt>lua_State*</tt> in which the variable
          *          represented by this \c LuaVariable resides.
          *   @param key The "key" used to access the variable represented by
          *          this \c LuaVariable. This can be variable name (for the case
          *          of a global variable) or a "real" key (when it is a field in
          *          a possibly nested table).

          *   @param predKeys The sequence of keys used to access the table that
          *          contains the variable represented by this \c LuaVariable.
          *          For a global variable, this list will be empty. For a
          *          variable stored in a possibly nested table, the list can be
          *          arbitrarily long.
          */
         LuaVariable (lua_State* state, const LuaValue& key,
                      const KeyList& predKeys = KeyList());

         /// The Lua state in which this \c LuaVariable lives.
         lua_State* state_;

         /** The sequence of keys used to get to this variable. For a global
          *  variable, this will consist of a single key; for variables inside
          *  nested tables, this sequence can be arbitrarily long.
          *
Just to relate this with the parameters passed to the
          *  constructor: this sequence equals to \c predKeys parameter, with
          *  the \c key parameter appended to it.
          */
         std::vector<LuaValue> keys_;
   };

} // namespace Diluculum

#endif // _DILUCULUM_LUA_VARIABLE_HPP_
<commit_msg>Removed a blank line that shouldn't exist.<commit_after>/******************************************************************************\
* LuaVariable.hpp                                                              *
* A variable living in a Lua interpreter.                                      *
* Leandro Motta Barros                                                         *
\******************************************************************************/

#ifndef _DILUCULUM_LUA_VARIABLE_HPP_
#define _DILUCULUM_LUA_VARIABLE_HPP_

#include <vector>
#include "LuaValue.hpp"

namespace Diluculum
{
   /** A variable living in a Lua state. Notice the crucial difference: unlike a
    *  \c LuaValue, a \c LuaVariable necessarily has a real counterpart in a Lua
    *  state. Thus, when something is assigned to a \c LuaVariable, the value of
    *  the corresponding variable in the Lua state is changed, too.
    *
<tt>LuaVariable</tt>s cannot be directly constructed. They are
    *  designed to be returned by <tt>LuaState</tt>'s subscript operator.
    */
   class LuaVariable
   {
      friend class LuaState;

      public:
         /** Assigns a new value to this \c LuaVariable. The corresponding
          *  variable in the Lua state is updated accordingly.
          *  @note Notice that this is the assignment of a new value to a
          *        variable. The user is also allowed to assign a
          *        \c LuaVariable to another \c LuaVariable (using the
          *        compiler-generated assignment operator). In that case, the
          *        \c LuaVariable at the left hand side will refer to the same
          *        variable as the \c LuaVariable at the right hand side, but no
          *        values will be changed.
          *  @param rhs The new value for the variable.
          *  @return \c rhs, so that a sequence of assignments, like
          *          <tt>a = b = c = 1;</tt> works. Actually, returning
          *          \c rhs is the same as returning <tt>this->value()</tt>,
          *          that perhaps make more sense.
          *  @todo There is a <tt>throw LuaError ("Duh.");</tt> statement in the
          *        implementation. This is ridiculous, and (worse!) the
          *        exception is not documented. Bad, uh?
          */
         const LuaValue& operator= (const LuaValue& rhs);

         /** Returns the value associated with this variable. If the variable
          *  does not exist, returns \c Nil.
          *  @throw TypeMismatchError If this \c LuaVariable tries to subscript
          *         something that is not a table.
          */
         LuaValue value() const;

         /** Assuming that this \c LuaVariable holds a table, returns the value
          *  whose index is \c key.
          *  @param key The key whose value is desired.
          *  @return The value whose index is \c key.
          *  @note This method doesn't throw anything, even if this
          *        \c LuaVariable doesn't hold a table. But an exception will
          *        be thrown if one tries to access the value of the returned
          *        variable (see \c value()).
          */
         LuaVariable operator[] (const LuaValue& key) const;

         /** Checks whether the value stored in this variable is equal to the
          *  value at \c rhs.
          *  @param rhs The value against which the comparison will be done.
          *  @return \c true if this variable's value is equal to \c rhs.
          *          \c false otherwise.
          *  @throw TypeMismatchError If this \c LuaVariable tries to subscript
          *         something that is not a table.
          */
         bool operator== (const LuaValue& rhs) const
         { return value() == rhs; }

         /** Checks whether this \c LuaVariable refers to the same variable as
          *  \c rhs.
          *  @param rhs The variable against which the comparison will be done.
          *  @return \c true if both involved <tt>LuaVariable</tt>s refer to the
          *          same variable. \c false otherwise.
          */
         bool operator== (const LuaVariable& rhs) const
         { return state_ == rhs.state_ && keys_ == rhs.keys_; }

         /** Checks whether this \c LuaVariable refers to a different variable
          *  than \c rhs.
          *  @param rhs The variable against which the comparison will be done.
          *  @return \c false if both involved <tt>LuaVariable</tt>s refer to the
          *          same variable. \c true otherwise.
          */
         bool operator!= (const LuaVariable& rhs) const
         { return state_ != rhs.state_ || keys_ != rhs.keys_; }

      private:
         /// A sequence of keys, used to access nested tables.
         typedef std::vector<LuaValue> KeyList;

         /** Constructs a \c LuaVariable.
          *   @note This is private because no one is expected to construct a
          *         \c LuaVariable directly. For Diluculum users, the only
          *         allowed way to create a new \c LuaVariable is by using
          *         <tt>LuaState</tt>'s subscript operator.
          *   @param state The <tt>lua_State*</tt> in which the variable
          *          represented by this \c LuaVariable resides.
          *   @param key The "key" used to access the variable represented by
          *          this \c LuaVariable. This can be variable name (for the case
          *          of a global variable) or a "real" key (when it is a field in
          *          a possibly nested table).
          *   @param predKeys The sequence of keys used to access the table that
          *          contains the variable represented by this \c LuaVariable.
          *          For a global variable, this list will be empty. For a
          *          variable stored in a possibly nested table, the list can be
          *          arbitrarily long.
          */
         LuaVariable (lua_State* state, const LuaValue& key,
                      const KeyList& predKeys = KeyList());

         /// The Lua state in which this \c LuaVariable lives.
         lua_State* state_;

         /** The sequence of keys used to get to this variable. For a global
          *  variable, this will consist of a single key; for variables inside
          *  nested tables, this sequence can be arbitrarily long.
          *
Just to relate this with the parameters passed to the
          *  constructor: this sequence equals to \c predKeys parameter, with
          *  the \c key parameter appended to it.
          */
         std::vector<LuaValue> keys_;
   };

} // namespace Diluculum

#endif // _DILUCULUM_LUA_VARIABLE_HPP_
<|endoftext|>