<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2008 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

/**
  \file    TransferFunction1D.cpp
  \author  Jens Krueger
           SCI Institute
           University of Utah
  \version 1.0
  \date    September 2008
*/

#include "TransferFunction1D.h"
#include <fstream>
#include <memory.h>

using namespace std;

TransferFunction1D::TransferFunction1D(size_t iSize) :
  m_vValueBBox(0,0)
{
  Resize(iSize);
}

TransferFunction1D::TransferFunction1D(const std::string& filename) {
  Load(filename);
}

TransferFunction1D::~TransferFunction1D(void)
{
}

void TransferFunction1D::Resize(size_t iSize) {
  vColorData.resize(iSize);
}

float TransferFunction1D::Smoothstep(float x) const {
  return 3*x*x-2*x*x*x;
}

void TransferFunction1D::SetStdFunction(float fCenterPoint, float fInvGradient) {
  SetStdFunction(fCenterPoint, fInvGradient,0);
  SetStdFunction(fCenterPoint, fInvGradient,1);
  SetStdFunction(fCenterPoint, fInvGradient,2);
  SetStdFunction(fCenterPoint, fInvGradient,3);
}

void TransferFunction1D::SetStdFunction(float fCenterPoint, float fInvGradient, int iComponent) {
  size_t iCenterPoint = size_t((vColorData.size()-1) * float(std::min<float>(std::max<float>(0,fCenterPoint),1)));
  size_t iInvGradient = size_t((vColorData.size()-1) * float(std::min<float>(std::max<float>(0,fInvGradient),1)));

  size_t iRampStartPoint = (iInvGradient/2 > iCenterPoint)                      ? 0                 : iCenterPoint-(iInvGradient/2);
  size_t iRampEndPoint   = (iInvGradient/2 + iCenterPoint > vColorData.size())  ? vColorData.size() : iCenterPoint+(iInvGradient/2);

  for (size_t i = 0;i<iRampStartPoint;i++)
    vColorData[i][iComponent] = 0;

  for (size_t i = iRampStartPoint;i<iRampEndPoint;i++) {
    float fValue = Smoothstep(float(i-iCenterPoint+(iInvGradient/2))/float(iInvGradient));
    vColorData[i][iComponent] = fValue;
  }

  for (size_t i = iRampEndPoint;i<vColorData.size();i++)
    vColorData[i][iComponent] = 1;

  ComputeNonZeroLimits();
}

void TransferFunction1D::Clear() {
  for (size_t i = 0;i<vColorData.size();i++)
    vColorData[i] = FLOATVECTOR4(0,0,0,0);

  m_vValueBBox = UINT64VECTOR2(0,0);
}

void TransferFunction1D::Resample(size_t iTargetSize) {
  size_t iSourceSize = vColorData.size();

  if (iTargetSize == iSourceSize) return;

  vector< FLOATVECTOR4 > vTmpColorData(iTargetSize);

  if (iTargetSize < iSourceSize) {
    // downsample
    size_t iFrom = 0;
    for (size_t i = 0;i<vTmpColorData.size();i++) {

      size_t iTo = iFrom + iSourceSize/iTargetSize;

      vTmpColorData[i] = 0;
      for (size_t j = iFrom;j<iTo;j++) {
        vTmpColorData[i] += vColorData[j];
      }
      vTmpColorData[i] /= float(iTo-iFrom);

      iTargetSize -= 1;
      iSourceSize -= iTo-iFrom;

      iFrom = iTo;
    }
  } else {
    // upsample
    for (size_t i = 0;i<vTmpColorData.size();i++) {
      float fPos = float(i) * float(iSourceSize-1)/float(iTargetSize);
      size_t iFloor = size_t(floor(fPos));
      size_t iCeil  = std::min(iFloor+1, vColorData.size()-1);
      float fInterp = fPos - float(iFloor);

      vTmpColorData[i] = vColorData[iFloor] * (1-fInterp) + vColorData[iCeil] * fInterp;
    }

  }

  vColorData = vTmpColorData;
  ComputeNonZeroLimits();
}

bool TransferFunction1D::Load(const std::string& filename, size_t iTargetSize) {
  if (!Load(filename)) {
    return false;
  } else {
    Resample(iTargetSize);
    return true;
  }
}

bool TransferFunction1D::Load(const std::string& filename) {
  ifstream file(filename.c_str());
  if (!Load(file)) return false;
  file.close();
  ComputeNonZeroLimits();
  return true;
}

bool TransferFunction1D::Load(ifstream& file, size_t iTargetSize) {
  if (!Load(file)) {
    return false;
  } else {
    Resample(iTargetSize);
    return true;
  }
}

bool TransferFunction1D::Save(const std::string& filename) const {
  ofstream file(filename.c_str());
  if (!Save(file)) return false;
  file.close();
  return true;
}

bool TransferFunction1D::Load(ifstream& file) {
  UINT32 iSize;
  file >> iSize;
  vColorData.resize(iSize);

  for(size_t i=0;i<vColorData.size();++i){
    for(size_t j=0;j<4;++j){
      file >> vColorData[i][j];
    }
  }

  return true;
}

bool TransferFunction1D::Save(ofstream& file) const {
  if (!file.is_open()) return false;

  file << vColorData.size() << endl;

  for(size_t i=0;i<vColorData.size();++i){
    for(size_t j=0;j<4;++j){
      file << vColorData[i][j] << " ";
    }
    file << endl;
  }

  return true;
}

void TransferFunction1D::GetByteArray(unsigned char** pcData,
                                      unsigned char cUsedRange) const {
  if (*pcData == NULL) *pcData = new unsigned char[vColorData.size()*4];

  unsigned char *pcDataIterator = *pcData;
  for (size_t i = 0;i<vColorData.size();i++) {
    *pcDataIterator++ = (unsigned char)(vColorData[i][0]*cUsedRange);
    *pcDataIterator++ = (unsigned char)(vColorData[i][1]*cUsedRange);
    *pcDataIterator++ = (unsigned char)(vColorData[i][2]*cUsedRange);
    *pcDataIterator++ = (unsigned char)(vColorData[i][3]*cUsedRange);
  }
}

void TransferFunction1D::GetShortArray(unsigned short** psData,
                                       unsigned short sUsedRange) const {
  if (*psData == NULL) *psData = new unsigned short[vColorData.size()*4];

  unsigned short *psDataIterator = *psData;
  for (size_t i = 0;i<vColorData.size();i++) {
    *psDataIterator++ = (unsigned short)(vColorData[i][0]*sUsedRange);
    *psDataIterator++ = (unsigned short)(vColorData[i][1]*sUsedRange);
    *psDataIterator++ = (unsigned short)(vColorData[i][2]*sUsedRange);
    *psDataIterator++ = (unsigned short)(vColorData[i][3]*sUsedRange);
  }
}

void TransferFunction1D::GetFloatArray(float** pfData) const {
  if (*pfData == NULL) *pfData = new float[4*vColorData.size()];
  memcpy(*pfData, &pfData[0], sizeof(float)*4*vColorData.size());
}

void TransferFunction1D::ComputeNonZeroLimits() {
  m_vValueBBox = UINT64VECTOR2(UINT64(vColorData.size()),0);

  for (size_t i = 0;i<vColorData.size();i++) {
    if (vColorData[i][3] != 0) {
      m_vValueBBox.x = MIN(m_vValueBBox.x, i);
      m_vValueBBox.y = i;
    }
  }
}
<commit_msg>Don't do the allocation if we have no data to copy.<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2008 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

/**
  \file    TransferFunction1D.cpp
  \author  Jens Krueger
           SCI Institute
           University of Utah
  \version 1.0
  \date    September 2008
*/

#include "TransferFunction1D.h"
#include <fstream>
#include <memory.h>

using namespace std;

TransferFunction1D::TransferFunction1D(size_t iSize) :
  m_vValueBBox(0,0)
{
  Resize(iSize);
}

TransferFunction1D::TransferFunction1D(const std::string& filename) {
  Load(filename);
}

TransferFunction1D::~TransferFunction1D(void)
{
}

void TransferFunction1D::Resize(size_t iSize) {
  vColorData.resize(iSize);
}

float TransferFunction1D::Smoothstep(float x) const {
  return 3*x*x-2*x*x*x;
}

void TransferFunction1D::SetStdFunction(float fCenterPoint, float fInvGradient) {
  SetStdFunction(fCenterPoint, fInvGradient,0);
  SetStdFunction(fCenterPoint, fInvGradient,1);
  SetStdFunction(fCenterPoint, fInvGradient,2);
  SetStdFunction(fCenterPoint, fInvGradient,3);
}

void TransferFunction1D::SetStdFunction(float fCenterPoint, float fInvGradient, int iComponent) {
  size_t iCenterPoint = size_t((vColorData.size()-1) * float(std::min<float>(std::max<float>(0,fCenterPoint),1)));
  size_t iInvGradient = size_t((vColorData.size()-1) * float(std::min<float>(std::max<float>(0,fInvGradient),1)));

  size_t iRampStartPoint = (iInvGradient/2 > iCenterPoint)                      ? 0                 : iCenterPoint-(iInvGradient/2);
  size_t iRampEndPoint   = (iInvGradient/2 + iCenterPoint > vColorData.size())  ? vColorData.size() : iCenterPoint+(iInvGradient/2);

  for (size_t i = 0;i<iRampStartPoint;i++)
    vColorData[i][iComponent] = 0;

  for (size_t i = iRampStartPoint;i<iRampEndPoint;i++) {
    float fValue = Smoothstep(float(i-iCenterPoint+(iInvGradient/2))/float(iInvGradient));
    vColorData[i][iComponent] = fValue;
  }

  for (size_t i = iRampEndPoint;i<vColorData.size();i++)
    vColorData[i][iComponent] = 1;

  ComputeNonZeroLimits();
}

void TransferFunction1D::Clear() {
  for (size_t i = 0;i<vColorData.size();i++)
    vColorData[i] = FLOATVECTOR4(0,0,0,0);

  m_vValueBBox = UINT64VECTOR2(0,0);
}

void TransferFunction1D::Resample(size_t iTargetSize) {
  size_t iSourceSize = vColorData.size();

  if (iTargetSize == iSourceSize) return;

  vector< FLOATVECTOR4 > vTmpColorData(iTargetSize);

  if (iTargetSize < iSourceSize) {
    // downsample
    size_t iFrom = 0;
    for (size_t i = 0;i<vTmpColorData.size();i++) {

      size_t iTo = iFrom + iSourceSize/iTargetSize;

      vTmpColorData[i] = 0;
      for (size_t j = iFrom;j<iTo;j++) {
        vTmpColorData[i] += vColorData[j];
      }
      vTmpColorData[i] /= float(iTo-iFrom);

      iTargetSize -= 1;
      iSourceSize -= iTo-iFrom;

      iFrom = iTo;
    }
  } else {
    // upsample
    for (size_t i = 0;i<vTmpColorData.size();i++) {
      float fPos = float(i) * float(iSourceSize-1)/float(iTargetSize);
      size_t iFloor = size_t(floor(fPos));
      size_t iCeil  = std::min(iFloor+1, vColorData.size()-1);
      float fInterp = fPos - float(iFloor);

      vTmpColorData[i] = vColorData[iFloor] * (1-fInterp) + vColorData[iCeil] * fInterp;
    }

  }

  vColorData = vTmpColorData;
  ComputeNonZeroLimits();
}

bool TransferFunction1D::Load(const std::string& filename, size_t iTargetSize) {
  if (!Load(filename)) {
    return false;
  } else {
    Resample(iTargetSize);
    return true;
  }
}

bool TransferFunction1D::Load(const std::string& filename) {
  ifstream file(filename.c_str());
  if (!Load(file)) return false;
  file.close();
  ComputeNonZeroLimits();
  return true;
}

bool TransferFunction1D::Load(ifstream& file, size_t iTargetSize) {
  if (!Load(file)) {
    return false;
  } else {
    Resample(iTargetSize);
    return true;
  }
}

bool TransferFunction1D::Save(const std::string& filename) const {
  ofstream file(filename.c_str());
  if (!Save(file)) return false;
  file.close();
  return true;
}

bool TransferFunction1D::Load(ifstream& file) {
  UINT32 iSize;
  file >> iSize;
  vColorData.resize(iSize);

  for(size_t i=0;i<vColorData.size();++i){
    for(size_t j=0;j<4;++j){
      file >> vColorData[i][j];
    }
  }

  return true;
}

bool TransferFunction1D::Save(ofstream& file) const {
  if (!file.is_open()) return false;

  file << vColorData.size() << endl;

  for(size_t i=0;i<vColorData.size();++i){
    for(size_t j=0;j<4;++j){
      file << vColorData[i][j] << " ";
    }
    file << endl;
  }

  return true;
}

void TransferFunction1D::GetByteArray(unsigned char** pcData,
                                      unsigned char cUsedRange) const {
  // bail out immediately if we've got no data
  if(vColorData.empty()) { return; }

  if (*pcData == NULL) *pcData = new unsigned char[vColorData.size()*4];

  unsigned char *pcDataIterator = *pcData;
  for (size_t i = 0;i<vColorData.size();i++) {
    *pcDataIterator++ = (unsigned char)(vColorData[i][0]*cUsedRange);
    *pcDataIterator++ = (unsigned char)(vColorData[i][1]*cUsedRange);
    *pcDataIterator++ = (unsigned char)(vColorData[i][2]*cUsedRange);
    *pcDataIterator++ = (unsigned char)(vColorData[i][3]*cUsedRange);
  }
}

void TransferFunction1D::GetShortArray(unsigned short** psData,
                                       unsigned short sUsedRange) const {
  // bail out immediately if we've got no data
  if(vColorData.empty()) { return; }

  if (*psData == NULL) *psData = new unsigned short[vColorData.size()*4];

  unsigned short *psDataIterator = *psData;
  for (size_t i = 0;i<vColorData.size();i++) {
    *psDataIterator++ = (unsigned short)(vColorData[i][0]*sUsedRange);
    *psDataIterator++ = (unsigned short)(vColorData[i][1]*sUsedRange);
    *psDataIterator++ = (unsigned short)(vColorData[i][2]*sUsedRange);
    *psDataIterator++ = (unsigned short)(vColorData[i][3]*sUsedRange);
  }
}

void TransferFunction1D::GetFloatArray(float** pfData) const {
  // bail out immediately if we've got no data
  if(vColorData.empty()) { return; }

  if (*pfData == NULL) *pfData = new float[4*vColorData.size()];
  memcpy(*pfData, &pfData[0], sizeof(float)*4*vColorData.size());
}

void TransferFunction1D::ComputeNonZeroLimits() {
  m_vValueBBox = UINT64VECTOR2(UINT64(vColorData.size()),0);

  for (size_t i = 0;i<vColorData.size();i++) {
    if (vColorData[i][3] != 0) {
      m_vValueBBox.x = MIN(m_vValueBBox.x, i);
      m_vValueBBox.y = i;
    }
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright © 2015, United States Government, as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All rights reserved.
 *
 * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
 * under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
*/

/**
 * @file ScarrArmModel.cpp
 * @brief Contains the implementation of class ScarrArmModel.
 * Measurements are scaled to average adult male
 * $Id$
 */

// This module
#include "ScarrArmModel.h"
// This library
#include "core/tgBasicActuator.h"
#include "core/tgRod.h"
#include "core/abstractMarker.h"
#include "tgcreator/tgBuildSpec.h"
#include "tgcreator/tgBasicActuatorInfo.h"
#include "tgcreator/tgRodInfo.h"
#include "tgcreator/tgStructure.h"
#include "tgcreator/tgStructureInfo.h"
// The Bullet Physics library
#include "LinearMath/btVector3.h"
// The C++ Standard Library
#include <stdexcept>

namespace
{
    // see tgBaseString.h for a descripton of some of these rod parameters
    // (specifically, those related to the motor moving the strings.)
    // NOTE that any parameter that depends on units of length will scale
    // with the current gravity scaling. E.g., with gravity as 98.1,
    // the length units below are in decimeters.

    // Note: This current model of the SUPERball rod is 1.5m long by 3 cm radius,
    // which is 0.00424 m^3.
    // For SUPERball v1.5, mass = 3.5kg per strut, which comes out to
    // 0.825 kg / (decimeter^3).

    // similarly, frictional parameters are for the tgRod objects.
    const struct Config
    {
        double density;
        double radius;
        double stiffness;
        double damping;
        double rod_length;
        double rod_space;
        double friction;
        double rollFriction;
        double restitution;
        double pretension;
        bool   history;
        double maxTens;
        double targetVelocity;
    } c =
   {
     0.825,    // density (kg / length^3)
     0.31,     // radius (length)
     3000.0,   // stiffness (kg / sec^2)
     200.0,    // damping (kg / sec)
     15.0,     // rod_length (length)
     7.5,      // rod_space (length)
     1.0,      // friction (unitless)
     0.01,     // rollFriction (unitless)
     0.2,      // restitution (?)
     0,        // pretension (force)
     false,    // history (boolean)
     100000,   // maxTens
     10000    // targetVelocity
#if (0)
     20000     // maxAcc
#endif
     // Use the below values for earlier versions of simulation.
     // 1.006,
     // 0.31,
     // 300000.0,
     // 3000.0,
     // 15.0,
     // 7.5,
  };
} // namespace

/*
 * helper arrays for node and rod numbering schema
 */
/*returns the number of the rod for a given node */
//const int rodNumbersPerNode[11]={0,1,2,3,3,4,0,1,2,5,5,4,6};

/*returns the node that is at the other end of the given node */
//const int otherEndOfTheRod[11]={6,7,8,4,3,11,0,1,2,10,9,5,12};

/*returns the node that is at the parallel rod
 * and at the same end of the given node
 */
//const int parallelNode[11]={1,0,5,9,10,2,7,6,11,3,4,8,12};

ScarrArmModel::ScarrArmModel() : tgModel()
{
}

ScarrArmModel::~ScarrArmModel()
{
}

void ScarrArmModel::addNodes(tgStructure& s)
{
    const double scale = 0.1;
    const size_t nNodes = 11;

    // Average Adult Male Measurements with scale
    // Lengths are in mm
    const double a = 22 * scale; //2.2cm
    const double b = 265 * scale;
    const double c = 334 * scale;
    const double d = 66 * scale;
    const double e = 246 * scale;
    const double f = 25 * scale;
    const double g = 17 * scale;
    const double sigma = 1; //TODO: tinker
    const double ulna_diameter = g*2; //TODO: tinker
    const double x = a/2;
    const double z = c/2;

    nodePositions.push_back(btVector3(a/2, 0, 0));
    nodePositions.push_back(btVector3(0, 0, -g));
    nodePositions.push_back(btVector3(-a/2, 0, 0));
    nodePositions.push_back(btVector3(0, f, 0));
    nodePositions.push_back(btVector3(0, -f, 0));
    nodePositions.push_back(btVector3(0, 0, d));
    nodePositions.push_back(btVector3(0, 0, c));
    nodePositions.push_back(btVector3(x, 0, z));
    nodePositions.push_back(btVector3(b+a/2, 0, 0));
    nodePositions.push_back(btVector3(a/2 + sigma, 0, -ulna_diameter));
    nodePositions.push_back(btVector3(a/2 + sigma + e, 0, -ulna_diameter));

    for(size_t i=0;i<nNodes;i++) {
		s.addNode(nodePositions[i][0],nodePositions[i][1],nodePositions[i][2]);
    }
}

void ScarrArmModel::addRods(tgStructure& s)
{
    s.addPair(5,  6,  "massless rod");
    s.addPair(5,  6,  "rod");
    s.addPair(3,  5,  "rod");
    s.addPair(4,  5,  "rod");

    s.addPair(0,  1,  "rod");
    s.addPair(0,  8,  "rod");
    s.addPair(1,  2,  "rod");

    s.addPair(9, 10,  "rod");
}

/*
void ScarrArmModel::addMarkers(tgStructure &s)
{
    std::vector<tgRod *> rods=find<tgRod>("rod");

	for(int i=0;i<10;i++)
	{
		const btRigidBody* bt = rods[rodNumbersPerNode[i]]->getPRigidBody();
		btTransform inverseTransform = bt->getWorldTransform().inverse();
		btVector3 pos = inverseTransform * (nodePositions[i]);
		abstractMarker tmp=abstractMarker(bt,pos,btVector3(0.08*i,1.0 - 0.08*i,.0),i);
		this->addMarker(tmp);
	}
}
*/

void ScarrArmModel::addMuscles(tgStructure& s)
{
    s.addPair(0, 3, "muscle");
    s.addPair(0, 4, "muscle");
    s.addPair(1, 3, "muscle");
    s.addPair(1, 4, "muscle");
    s.addPair(2, 3, "muscle");
    s.addPair(2, 4, "muscle");
    s.addPair(3, 9, "muscle");
    s.addPair(4, 9, "muscle");
    //s.addPair(5, 7, "muscle");
    //s.addPair(6, 7, "muscle");
    //s.addPair(7, 8, "muscle");
    s.addPair(6, 8, "muscle");
    s.addPair(8, 10, "muscle");
}

void ScarrArmModel::setup(tgWorld& world)
{

    const tgRod::Config rodConfig(c.radius, c.density, c.friction, c.rollFriction, c.restitution);
    const tgRod::Config rodConfigMassless(c.radius, 0.001/*c.density*/, c.friction, c.rollFriction, c.restitution); //TODO: Fix
    /// @todo acceleration constraint was removed on 12/10/14 Replace with tgKinematicActuator as appropreate
    tgBasicActuator::Config muscleConfig(c.stiffness, c.damping, c.pretension, c.history, c.maxTens, c.targetVelocity);

    // Start creating the structure
    tgStructure s;
    addNodes(s);
    addRods(s);
    addMuscles(s);

//    // Add a rotation. This is needed if the ground slopes too much, otherwise glitches put a rod below the ground.
//    btVector3 rotationPoint = btVector3(0, 0, 0); // origin
//    btVector3 rotationAxis = btVector3(0, 1, 0);  // y-axis
//    double rotationAngle = M_PI/2;
//    s.addRotation(rotationPoint, rotationAxis, rotationAngle);
//    s.move(btVector3(0,30,0));

    // Create the build spec that uses tags to turn the structure into a real model
    tgBuildSpec spec;
    spec.addBuilder("massless rod", new tgRodInfo(rodConfigMassless));
    spec.addBuilder("rod", new tgRodInfo(rodConfig));
    spec.addBuilder("muscle", new tgBasicActuatorInfo(muscleConfig));

    // Create your structureInfo
    tgStructureInfo structureInfo(s, spec);

    // Use the structureInfo to build ourselves
    structureInfo.buildInto(*this, world);

    // We could now use tgCast::filter or similar to pull out the
    // models (e.g. muscles) that we want to control.
    allMuscles = tgCast::filter<tgModel, tgBasicActuator> (getDescendants());

    // call the onSetup methods of all observed things e.g. controllers
    notifySetup();

    // Actually setup the children
    tgModel::setup(world);

    //map the rods and add the markers to them
    //addMarkers(s);

    btVector3 location(0,10.0,0);
    //btVector3 rotation(M_PI/2,0,0);
    btVector3 rotation(0,0,0);
  	btVector3 speed(0,0,0);
    this->moveModel(location,rotation,speed);
}

void ScarrArmModel::step(double dt)
{
    // Precondition
    if (dt <= 0.0)
    {
        throw std::invalid_argument("dt is not positive");
    }
    else
    {
        // Notify observers (controllers) of the step so that they can take action
        notifyStep(dt);
        tgModel::step(dt);  // Step any children
    }
}

void ScarrArmModel::onVisit(tgModelVisitor& r)
{
    tgModel::onVisit(r);
}

const std::vector<tgBasicActuator*>& ScarrArmModel::getAllMuscles() const
{
    return allMuscles;
}

void ScarrArmModel::teardown()
{
    tgModel::teardown();
}

void ScarrArmModel::moveModel(btVector3 positionVector,btVector3 rotationVector,btVector3 speedVector)
{
    std::vector<tgRod *> rods=find<tgRod>("rod");

	btQuaternion initialRotationQuat;
	initialRotationQuat.setEuler(rotationVector[0],rotationVector[1],rotationVector[2]);
	btTransform initialTransform;
	initialTransform.setIdentity();
	initialTransform.setRotation(initialRotationQuat);
	initialTransform.setOrigin(positionVector);
	for(size_t i=0;i<rods.size();i++) {
			rods[i]->getPRigidBody()->setLinearVelocity(speedVector);
			rods[i]->getPRigidBody()->setWorldTransform(initialTransform * rods[i]->getPRigidBody()->getWorldTransform());
	}
}
<commit_msg>Added support rod, but it isn't massless<commit_after>/*
 * Copyright © 2015, United States Government, as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 * All rights reserved.
 *
 * The NASA Tensegrity Robotics Toolkit (NTRT) v1 platform is licensed
 * under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
*/

/**
 * @file ScarrArmModel.cpp
 * @brief Contains the implementation of class ScarrArmModel.
 * Measurements are scaled to average adult male
 * $Id$
 */

// This module
#include "ScarrArmModel.h"
// This library
#include "core/tgBasicActuator.h"
#include "core/tgRod.h"
#include "core/abstractMarker.h"
#include "tgcreator/tgBuildSpec.h"
#include "tgcreator/tgBasicActuatorInfo.h"
#include "tgcreator/tgRodInfo.h"
#include "tgcreator/tgStructure.h"
#include "tgcreator/tgStructureInfo.h"
// The Bullet Physics library
#include "LinearMath/btVector3.h"
// The C++ Standard Library
#include <stdexcept>

namespace
{
    // see tgBaseString.h for a descripton of some of these rod parameters
    // (specifically, those related to the motor moving the strings.)
    // NOTE that any parameter that depends on units of length will scale
    // with the current gravity scaling. E.g., with gravity as 98.1,
    // the length units below are in decimeters.

    // Note: This current model of the SUPERball rod is 1.5m long by 3 cm radius,
    // which is 0.00424 m^3.
    // For SUPERball v1.5, mass = 3.5kg per strut, which comes out to
    // 0.825 kg / (decimeter^3).

    // similarly, frictional parameters are for the tgRod objects.
    const struct Config
    {
        double density;
        double radius;
        double stiffness;
        double damping;
        double rod_length;
        double rod_space;
        double friction;
        double rollFriction;
        double restitution;
        double pretension;
        bool   history;
        double maxTens;
        double targetVelocity;
    } c =
   {
     0.825,    // density (kg / length^3)
     0.31,     // radius (length)
     3000.0,   // stiffness (kg / sec^2)
     200.0,    // damping (kg / sec)
     15.0,     // rod_length (length)
     7.5,      // rod_space (length)
     1.0,      // friction (unitless)
     0.01,     // rollFriction (unitless)
     0.2,      // restitution (?)
     0,        // pretension (force)
     false,    // history (boolean)
     100000,   // maxTens
     10000    // targetVelocity
#if (0)
     20000     // maxAcc
#endif
     // Use the below values for earlier versions of simulation.
     // 1.006,
     // 0.31,
     // 300000.0,
     // 3000.0,
     // 15.0,
     // 7.5,
  };
} // namespace

/*
 * helper arrays for node and rod numbering schema
 */
/*returns the number of the rod for a given node */
//const int rodNumbersPerNode[11]={0,1,2,3,3,4,0,1,2,5,5,4,6};

/*returns the node that is at the other end of the given node */
//const int otherEndOfTheRod[11]={6,7,8,4,3,11,0,1,2,10,9,5,12};

/*returns the node that is at the parallel rod
 * and at the same end of the given node
 */
//const int parallelNode[11]={1,0,5,9,10,2,7,6,11,3,4,8,12};

ScarrArmModel::ScarrArmModel() : tgModel()
{
}

ScarrArmModel::~ScarrArmModel()
{
}

void ScarrArmModel::addNodes(tgStructure& s)
{
    const double scale = 0.1;
    const size_t nNodes = 11 + 2; //2 for massless rod

    // Average Adult Male Measurements with scale
    // Lengths are in mm
    const double a = 22 * scale; //2.2cm
    const double b = 265 * scale;
    const double c = 334 * scale;
    const double d = 66 * scale;
    const double e = 246 * scale;
    const double f = 25 * scale;
    const double g = 17 * scale;
    const double sigma = 1; //TODO: tinker
    const double ulna_diameter = g*2; //TODO: tinker
    const double x = a/2;
    const double z = c/2;

    nodePositions.push_back(btVector3(a/2, 0, 0));
    nodePositions.push_back(btVector3(0, 0, -g));
    nodePositions.push_back(btVector3(-a/2, 0, 0));
    nodePositions.push_back(btVector3(0, f, 0));
    nodePositions.push_back(btVector3(0, -f, 0));
    nodePositions.push_back(btVector3(0, 0, d));
    nodePositions.push_back(btVector3(0, 0, c));
    nodePositions.push_back(btVector3(x, 0, z));
    nodePositions.push_back(btVector3(b+a/2, 0, 0));
    nodePositions.push_back(btVector3(a/2 + sigma, 0, -ulna_diameter));
    nodePositions.push_back(btVector3(a/2 + sigma + e, 0, -ulna_diameter));

    //Massless rod
    nodePositions.push_back(btVector3(0, f, c+1));
    nodePositions.push_back(btVector3(0, -f, c+1));

    for(size_t i=0;i<nNodes;i++) {
		s.addNode(nodePositions[i][0],nodePositions[i][1],nodePositions[i][2]);
    }
}

void ScarrArmModel::addRods(tgStructure& s)
{
    s.addPair(5,  6,  "rod");
    s.addPair(3,  5,  "rod");
    s.addPair(4,  5,  "rod");

    s.addPair(0,  1,  "rod");
    s.addPair(0,  8,  "rod");
    s.addPair(1,  2,  "rod");

    s.addPair(9, 10,  "rod");
    s.addPair(11, 12, "massless rod");
}

/*
void ScarrArmModel::addMarkers(tgStructure &s)
{
    std::vector<tgRod *> rods=find<tgRod>("rod");

	for(int i=0;i<10;i++)
	{
		const btRigidBody* bt = rods[rodNumbersPerNode[i]]->getPRigidBody();
		btTransform inverseTransform = bt->getWorldTransform().inverse();
		btVector3 pos = inverseTransform * (nodePositions[i]);
		abstractMarker tmp=abstractMarker(bt,pos,btVector3(0.08*i,1.0 - 0.08*i,.0),i);
		this->addMarker(tmp);
	}
}
*/

void ScarrArmModel::addMuscles(tgStructure& s)
{
    s.addPair(0, 3, "muscle");
    s.addPair(0, 4, "muscle");
    s.addPair(1, 3, "muscle");
    s.addPair(1, 4, "muscle");
    s.addPair(2, 3, "muscle");
    s.addPair(2, 4, "muscle");
    s.addPair(3, 9, "muscle");
    s.addPair(4, 9, "muscle");
    //s.addPair(5, 7, "muscle");
    //s.addPair(6, 7, "muscle");
    //s.addPair(7, 8, "muscle");
    s.addPair(6, 8, "muscle");
    s.addPair(8, 10, "muscle");

    //Muscles to massless rod
    s.addPair(6, 11, "muscle");
    s.addPair(6, 12, "muscle");
}

void ScarrArmModel::setup(tgWorld& world)
{

    const tgRod::Config rodConfig(c.radius, c.density, c.friction, c.rollFriction, c.restitution);
    const tgRod::Config rodConfigMassless(c.radius, 0/*c.density*/, c.friction, c.rollFriction, c.restitution);
    /// @todo acceleration constraint was removed on 12/10/14 Replace with tgKinematicActuator as appropreate
    tgBasicActuator::Config muscleConfig(c.stiffness, c.damping, c.pretension, c.history, c.maxTens, c.targetVelocity);

    // Start creating the structure
    tgStructure s;
    addNodes(s);
    addRods(s);
    addMuscles(s);

//    // Add a rotation. This is needed if the ground slopes too much, otherwise glitches put a rod below the ground.
//    btVector3 rotationPoint = btVector3(0, 0, 0); // origin
//    btVector3 rotationAxis = btVector3(0, 1, 0);  // y-axis
//    double rotationAngle = M_PI/2;
//    s.addRotation(rotationPoint, rotationAxis, rotationAngle);
//    s.move(btVector3(0,30,0));

    // Create the build spec that uses tags to turn the structure into a real model
    tgBuildSpec spec;
    spec.addBuilder("massless rod", new tgRodInfo(rodConfigMassless));
    spec.addBuilder("rod", new tgRodInfo(rodConfig));
    spec.addBuilder("muscle", new tgBasicActuatorInfo(muscleConfig));

    // Create your structureInfo
    tgStructureInfo structureInfo(s, spec);

    // Use the structureInfo to build ourselves
    structureInfo.buildInto(*this, world);

    // We could now use tgCast::filter or similar to pull out the
    // models (e.g. muscles) that we want to control.
    allMuscles = tgCast::filter<tgModel, tgBasicActuator> (getDescendants());

    // call the onSetup methods of all observed things e.g. controllers
    notifySetup();

    // Actually setup the children
    tgModel::setup(world);

    //map the rods and add the markers to them
    //addMarkers(s);

    btVector3 location(0,10.0,0);
    //btVector3 rotation(M_PI/2,0,0);
    btVector3 rotation(0,0,0);
  	btVector3 speed(0,0,0);
    this->moveModel(location,rotation,speed);
}

void ScarrArmModel::step(double dt)
{
    // Precondition
    if (dt <= 0.0)
    {
        throw std::invalid_argument("dt is not positive");
    }
    else
    {
        // Notify observers (controllers) of the step so that they can take action
        notifyStep(dt);
        tgModel::step(dt);  // Step any children
    }
}

void ScarrArmModel::onVisit(tgModelVisitor& r)
{
    tgModel::onVisit(r);
}

const std::vector<tgBasicActuator*>& ScarrArmModel::getAllMuscles() const
{
    return allMuscles;
}

void ScarrArmModel::teardown()
{
    tgModel::teardown();
}

void ScarrArmModel::moveModel(btVector3 positionVector,btVector3 rotationVector,btVector3 speedVector)
{
    std::vector<tgRod *> rods=find<tgRod>("rod");

	btQuaternion initialRotationQuat;
	initialRotationQuat.setEuler(rotationVector[0],rotationVector[1],rotationVector[2]);
	btTransform initialTransform;
	initialTransform.setIdentity();
	initialTransform.setRotation(initialRotationQuat);
	initialTransform.setOrigin(positionVector);
	for(size_t i=0;i<rods.size();i++) {
			rods[i]->getPRigidBody()->setLinearVelocity(speedVector);
			rods[i]->getPRigidBody()->setWorldTransform(initialTransform * rods[i]->getPRigidBody()->getWorldTransform());
	}
}
<|endoftext|>


<commit_before>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation, either version 3 of the License                  *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#include <stack>
#include <sstream>
#include <algorithm>

#include "cppa/atom.hpp"
#include "cppa/object.hpp"
#include "cppa/to_string.hpp"
#include "cppa/serializer.hpp"
#include "cppa/from_string.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/uniform_type_info.hpp"

namespace cppa {

namespace {

class string_serializer : public serializer {

    std::ostream& out;

    struct pt_writer {

        std::ostream& out;

        pt_writer(std::ostream& mout) : out(mout) { }

        template<typename T>
        void operator()(const T& value) {
            out << value;
        }

        void operator()(const std::string& str) {
            out << "\"";// << str << "\"";
            for (char c : str) {
                if (c == '"') out << "\\\"";
                else out << c;
            }
            out << '"';
        }

        void operator()(const std::u16string&) { }

        void operator()(const std::u32string&) { }

    };

    bool m_after_value;
    bool m_obj_just_opened;
    std::stack<std::string> m_open_objects;

    inline void clear() {
        if (m_after_value) {
            out << ", ";
            m_after_value = false;
        }
        else if (m_obj_just_opened) {
            out << " ( ";
            m_obj_just_opened = false;
        }
    }

 public:

    string_serializer(std::ostream& mout)
        : out(mout), m_after_value(false), m_obj_just_opened(false) {
    }

    void begin_object(const std::string& type_name) {
        clear();
        m_open_objects.push(type_name);
        out << type_name;// << " ( ";
        m_obj_just_opened = true;
    }
    void end_object() {
        if (m_obj_just_opened) {
            // no open brackets to close
            m_obj_just_opened = false;
        }
        else {
            out << (m_after_value ? " )" : ")");
        }
        m_after_value = true;
        if (!m_open_objects.empty()) {
            m_open_objects.pop();
        }
    }

    void begin_sequence(size_t) {
        clear();
        out << "{ ";
    }

    void end_sequence() {
        out << (m_after_value ? " }" : "}");
        m_after_value = true;
    }

    void write_value(const primitive_variant& value) {
        clear();
        if (m_open_objects.empty()) {
            throw std::runtime_error("write_value(): m_open_objects.empty()");
        }
        if (m_open_objects.top() == "@atom") {
            if (value.ptype() != pt_uint64) {
                throw std::runtime_error("expected uint64 value after @atom");
            }
            // write atoms as strings instead of integer values
            auto av = static_cast<atom_value>(get<std::uint64_t>(value));
            (pt_writer(out))(to_string(av));
        }
        else {
            value.apply(pt_writer(out));
        }
        m_after_value = true;
    }

    void write_tuple(size_t size, const primitive_variant* values) {
        clear();
        out << "{";
        const primitive_variant* end = values + size;
        for ( ; values != end; ++values) {
            write_value(*values);
        }
        out << (m_after_value ? " }" : "}");
    }

    void write_raw(size_t, const void*) {
        throw std::runtime_error("string_serializer::write_raw: "
                                 "not implemented yet");
    }

};

class string_deserializer : public deserializer {

    std::string m_str;
    std::string::iterator m_pos;
    //size_t m_obj_count;
    std::stack<bool> m_obj_had_left_parenthesis;
    std::stack<std::string> m_open_objects;

    void skip_space_and_comma() {
        while (*m_pos == ' ' || *m_pos == ',') ++m_pos;
    }

    void throw_malformed(const std::string& error_msg) {
        throw std::logic_error("malformed string: " + error_msg);
    }

    void consume(char c) {
        skip_space_and_comma();
        if (*m_pos != c) {
            std::string error;
            error += "expected '";
            error += c;
            error += "' found '";
            error += *m_pos;
            error += "'";
            if (m_open_objects.empty() == false) {
                error += "during deserialization an instance of ";
                error += m_open_objects.top();
            }
            throw_malformed(error);
        }
        ++m_pos;
    }

    bool try_consume(char c) {
        skip_space_and_comma();
        if (*m_pos == c) {
            ++m_pos;
            return true;
        }
        return false;
    }

    inline std::string::iterator next_delimiter() {
        return std::find_if(m_pos, m_str.end(), [] (char c) -> bool {
            switch (c) {
                case '(':
                case ')':
                case '{':
                case '}':
                case ' ':
                case ',': {
                    return true;
                }
                default: {
                    return false;
                }
            }
        });
    }

    void integrity_check() {
        if (m_open_objects.empty() || m_obj_had_left_parenthesis.empty()) {
            throw_malformed("missing begin_object()");
        }
        if (m_obj_had_left_parenthesis.top() == false) {
            throw_malformed("expected left parenthesis after "
                            "begin_object call or void value");
        }
    }

 public:

    string_deserializer(const std::string& str) : m_str(str) {
        m_pos = m_str.begin();
    }

    string_deserializer(std::string&& str) : m_str(std::move(str)) {
        m_pos = m_str.begin();
    }

    std::string seek_object() {
        skip_space_and_comma();
        auto substr_end = next_delimiter();
        if (m_pos == substr_end) {
            throw_malformed("could not seek object type name");
        }
        std::string result(m_pos, substr_end);
        m_pos = substr_end;
        return result;
    }

    std::string peek_object() {
        std::string result = seek_object();
        // restore position in stream
        m_pos -= result.size();
        return result;
    }

    void begin_object(const std::string& type_name) {
        m_open_objects.push(type_name);
        //++m_obj_count;
        skip_space_and_comma();
        m_obj_had_left_parenthesis.push(try_consume('('));
        //consume('(');
    }

    void end_object() {
        if (m_obj_had_left_parenthesis.empty()) {
            throw_malformed("missing begin_object()");
        }
        else {
            if (m_obj_had_left_parenthesis.top() == true) {
                consume(')');
            }
            m_obj_had_left_parenthesis.pop();
        }
        if (m_open_objects.empty()) {
            throw std::runtime_error("no object to end");
        }
        m_open_objects.pop();
        if (m_open_objects.empty()) {
            skip_space_and_comma();
            if (m_pos != m_str.end()) {
                throw_malformed("expected end of of string");
            }
        }
    }

    size_t begin_sequence() {
        integrity_check();
        consume('{');
        return std::count(m_pos, std::find(m_pos, m_str.end(), '}'), ',') + 1;
    }

    void end_sequence() {
        integrity_check();
        consume('}');
    }

    struct from_string {
        const std::string& str;
        from_string(const std::string& s) : str(s) { }
        template<typename T>
        void operator()(T& what) {
            std::istringstream s(str);
            s >> what;
        }
        void operator()(std::string& what) {
            what = str;
        }
        void operator()(std::u16string&) { }
        void operator()(std::u32string&) { }
    };

    primitive_variant read_value(primitive_type ptype) {
        integrity_check();
        if (m_open_objects.top() == "@atom") {
            if (ptype != pt_uint64) {
                throw_malformed("expected read of pt_uint64 after @atom");
            }
            auto str_val = get<std::string>(read_value(pt_u8string));
            if (str_val.size() > 10) {
                throw_malformed("atom string size > 10");
            }
            return detail::atom_val(str_val.c_str());
        }
        skip_space_and_comma();
        std::string::iterator substr_end;
        auto find_if_cond = [] (char c) -> bool {
            switch (c) {
             case ')':
             case '}':
             case ' ':
             case ',': return true;
             default : return false;
            }
        };
        if (ptype == pt_u8string) {
            if (*m_pos == '"') {
                // skip leading "
                ++m_pos;
                char last_char = '"';
                auto find_if_str_cond = [&last_char] (char c) -> bool {
                    if (c == '"' && last_char != '\\') {
                        return true;
                    }
                    last_char = c;
                    return false;
                };
                substr_end = std::find_if(m_pos, m_str.end(), find_if_str_cond);
            }
            else {
                substr_end = std::find_if(m_pos, m_str.end(), find_if_cond);
            }
        }
        else {
            substr_end = std::find_if(m_pos, m_str.end(), find_if_cond);
        }
        if (substr_end == m_str.end()) {
            throw std::logic_error("malformed string (unterminated value)");
        }
        std::string substr(m_pos, substr_end);
        m_pos += substr.size();
        if (ptype == pt_u8string) {
            // skip trailing "
            if (*m_pos != '"') {
                std::string error_msg;
                error_msg  = "malformed string, expected '\"' found '";
                error_msg += *m_pos;
                error_msg += "'";
                throw std::logic_error(error_msg);
            }
            ++m_pos;
            // replace '\"' by '"'
            char last_char = ' ';
            auto cond = [&last_char] (char c) -> bool {
                if (c == '"' && last_char == '\\') {
                    return true;
                }
                last_char = c;
                return false;
            };
            std::string tmp;
            auto sbegin = substr.begin();
            auto send = substr.end();
            for (auto i = std::find_if(sbegin, send, cond);
                 i != send;
                 i = std::find_if(i, send, cond)) {
                --i;
                tmp.append(sbegin, i);
                tmp += '"';
                i += 2;
                sbegin = i;
            }
            if (sbegin != substr.begin()) {
                tmp.append(sbegin, send);
            }
            if (!tmp.empty()) {
                substr = std::move(tmp);
            }
        }
        primitive_variant result(ptype);
        result.apply(from_string(substr));
        return result;
    }

    void read_tuple(size_t size,
                    const primitive_type* begin,
                    primitive_variant* storage) {
        integrity_check();
        consume('{');
        const primitive_type* end = begin + size;
        for ( ; begin != end; ++begin) {
            *storage = std::move(read_value(*begin));
            ++storage;
        }
        consume('}');
    }

    void read_raw(size_t, void*) {
        throw std::runtime_error("string_deserializer::read_raw: "
                                 "not implemented yet");
    }

};

} // namespace <anonymous>

object from_string(const std::string& what) {
    string_deserializer strd(what);
    std::string uname = strd.peek_object();
    auto utype = uniform_type_info::from(uname);
    if (utype == nullptr) {
        throw std::logic_error(uname + " is not announced");
    }
    return utype->deserialize(&strd);
}

namespace detail {

std::string to_string_impl(const void *what, const uniform_type_info *utype) {
    std::ostringstream osstr;
    string_serializer strs(osstr);
    utype->serialize(what, &strs);
    return osstr.str();
}

} // namespace detail

} // namespace cppa
<commit_msg>implemented read_raw & write_raw<commit_after>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation, either version 3 of the License                  *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#include <stack>
#include <cctype>
#include <sstream>
#include <iomanip>
#include <algorithm>

#include "cppa/atom.hpp"
#include "cppa/object.hpp"
#include "cppa/to_string.hpp"
#include "cppa/serializer.hpp"
#include "cppa/from_string.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/uniform_type_info.hpp"

using namespace std;

namespace cppa {

namespace {

class string_serializer : public serializer {

    ostream& out;

    struct pt_writer {

        ostream& out;

        pt_writer(ostream& mout) : out(mout) { }

        template<typename T>
        void operator()(const T& value) {
            out << value;
        }

        void operator()(const string& str) {
            out << "\"";// << str << "\"";
            for (char c : str) {
                if (c == '"') out << "\\\"";
                else out << c;
            }
            out << '"';
        }

        void operator()(const u16string&) { }

        void operator()(const u32string&) { }

    };

    bool m_after_value;
    bool m_obj_just_opened;
    stack<string> m_open_objects;

    inline void clear() {
        if (m_after_value) {
            out << ", ";
            m_after_value = false;
        }
        else if (m_obj_just_opened) {
            out << " ( ";
            m_obj_just_opened = false;
        }
    }

 public:

    string_serializer(ostream& mout)
        : out(mout), m_after_value(false), m_obj_just_opened(false) {
    }

    void begin_object(const string& type_name) {
        clear();
        m_open_objects.push(type_name);
        out << type_name;// << " ( ";
        m_obj_just_opened = true;
    }
    void end_object() {
        if (m_obj_just_opened) {
            // no open brackets to close
            m_obj_just_opened = false;
        }
        else {
            out << (m_after_value ? " )" : ")");
        }
        m_after_value = true;
        if (!m_open_objects.empty()) {
            m_open_objects.pop();
        }
    }

    void begin_sequence(size_t) {
        clear();
        out << "{ ";
    }

    void end_sequence() {
        out << (m_after_value ? " }" : "}");
        m_after_value = true;
    }

    void write_value(const primitive_variant& value) {
        clear();
        if (m_open_objects.empty()) {
            throw runtime_error("write_value(): m_open_objects.empty()");
        }
        if (m_open_objects.top() == "@atom") {
            if (value.ptype() != pt_uint64) {
                throw runtime_error("expected uint64 value after @atom");
            }
            // write atoms as strings instead of integer values
            auto av = static_cast<atom_value>(get<uint64_t>(value));
            (pt_writer(out))(to_string(av));
        }
        else {
            value.apply(pt_writer(out));
        }
        m_after_value = true;
    }

    void write_tuple(size_t size, const primitive_variant* values) {
        clear();
        out << "{";
        const primitive_variant* end = values + size;
        for ( ; values != end; ++values) {
            write_value(*values);
        }
        out << (m_after_value ? " }" : "}");
    }

    void write_raw(size_t num_bytes, const void* buf) {
        clear();
        auto first = reinterpret_cast<const unsigned char*>(buf);
        auto last = first + num_bytes;
        out << hex;
        out << setfill('0');
        copy(first, last, ostream_iterator<size_t>(out));
        out << dec;
        m_after_value = true;
    }

};

class string_deserializer : public deserializer {

    string m_str;
    string::iterator m_pos;
    //size_t m_obj_count;
    stack<bool> m_obj_had_left_parenthesis;
    stack<string> m_open_objects;

    void skip_space_and_comma() {
        while (*m_pos == ' ' || *m_pos == ',') ++m_pos;
    }

    void throw_malformed(const string& error_msg) {
        throw logic_error("malformed string: " + error_msg);
    }

    void consume(char c) {
        skip_space_and_comma();
        if (*m_pos != c) {
            string error;
            error += "expected '";
            error += c;
            error += "' found '";
            error += *m_pos;
            error += "'";
            if (m_open_objects.empty() == false) {
                error += "during deserialization an instance of ";
                error += m_open_objects.top();
            }
            throw_malformed(error);
        }
        ++m_pos;
    }

    bool try_consume(char c) {
        skip_space_and_comma();
        if (*m_pos == c) {
            ++m_pos;
            return true;
        }
        return false;
    }

    inline string::iterator next_delimiter() {
        return find_if(m_pos, m_str.end(), [] (char c) -> bool {
            switch (c) {
                case '(':
                case ')':
                case '{':
                case '}':
                case ' ':
                case ',': {
                    return true;
                }
                default: {
                    return false;
                }
            }
        });
    }

    void integrity_check() {
        if (m_open_objects.empty() || m_obj_had_left_parenthesis.empty()) {
            throw_malformed("missing begin_object()");
        }
        if (m_obj_had_left_parenthesis.top() == false) {
            throw_malformed("expected left parenthesis after "
                            "begin_object call or void value");
        }
    }

 public:

    string_deserializer(const string& str) : m_str(str) {
        m_pos = m_str.begin();
    }

    string_deserializer(string&& str) : m_str(move(str)) {
        m_pos = m_str.begin();
    }

    string seek_object() {
        skip_space_and_comma();
        auto substr_end = next_delimiter();
        if (m_pos == substr_end) {
            throw_malformed("could not seek object type name");
        }
        string result(m_pos, substr_end);
        m_pos = substr_end;
        return result;
    }

    string peek_object() {
        string result = seek_object();
        // restore position in stream
        m_pos -= result.size();
        return result;
    }

    void begin_object(const string& type_name) {
        m_open_objects.push(type_name);
        //++m_obj_count;
        skip_space_and_comma();
        m_obj_had_left_parenthesis.push(try_consume('('));
        //consume('(');
    }

    void end_object() {
        if (m_obj_had_left_parenthesis.empty()) {
            throw_malformed("missing begin_object()");
        }
        else {
            if (m_obj_had_left_parenthesis.top() == true) {
                consume(')');
            }
            m_obj_had_left_parenthesis.pop();
        }
        if (m_open_objects.empty()) {
            throw runtime_error("no object to end");
        }
        m_open_objects.pop();
        if (m_open_objects.empty()) {
            skip_space_and_comma();
            if (m_pos != m_str.end()) {
                throw_malformed("expected end of of string");
            }
        }
    }

    size_t begin_sequence() {
        integrity_check();
        consume('{');
        return count(m_pos, find(m_pos, m_str.end(), '}'), ',') + 1;
    }

    void end_sequence() {
        integrity_check();
        consume('}');
    }

    struct from_string {
        const string& str;
        from_string(const string& s) : str(s) { }
        template<typename T>
        void operator()(T& what) {
            istringstream s(str);
            s >> what;
        }
        void operator()(string& what) {
            what = str;
        }
        void operator()(u16string&) { }
        void operator()(u32string&) { }
    };

    primitive_variant read_value(primitive_type ptype) {
        integrity_check();
        if (m_open_objects.top() == "@atom") {
            if (ptype != pt_uint64) {
                throw_malformed("expected read of pt_uint64 after @atom");
            }
            auto str_val = get<string>(read_value(pt_u8string));
            if (str_val.size() > 10) {
                throw_malformed("atom string size > 10");
            }
            return detail::atom_val(str_val.c_str());
        }
        skip_space_and_comma();
        string::iterator substr_end;
        auto find_if_cond = [] (char c) -> bool {
            switch (c) {
             case ')':
             case '}':
             case ' ':
             case ',': return true;
             default : return false;
            }
        };
        if (ptype == pt_u8string) {
            if (*m_pos == '"') {
                // skip leading "
                ++m_pos;
                char last_char = '"';
                auto find_if_str_cond = [&last_char] (char c) -> bool {
                    if (c == '"' && last_char != '\\') {
                        return true;
                    }
                    last_char = c;
                    return false;
                };
                substr_end = find_if(m_pos, m_str.end(), find_if_str_cond);
            }
            else {
                substr_end = find_if(m_pos, m_str.end(), find_if_cond);
            }
        }
        else {
            substr_end = find_if(m_pos, m_str.end(), find_if_cond);
        }
        if (substr_end == m_str.end()) {
            throw logic_error("malformed string (unterminated value)");
        }
        string substr(m_pos, substr_end);
        m_pos += substr.size();
        if (ptype == pt_u8string) {
            // skip trailing "
            if (*m_pos != '"') {
                string error_msg;
                error_msg  = "malformed string, expected '\"' found '";
                error_msg += *m_pos;
                error_msg += "'";
                throw logic_error(error_msg);
            }
            ++m_pos;
            // replace '\"' by '"'
            char last_char = ' ';
            auto cond = [&last_char] (char c) -> bool {
                if (c == '"' && last_char == '\\') {
                    return true;
                }
                last_char = c;
                return false;
            };
            string tmp;
            auto sbegin = substr.begin();
            auto send = substr.end();
            for (auto i = find_if(sbegin, send, cond);
                 i != send;
                 i = find_if(i, send, cond)) {
                --i;
                tmp.append(sbegin, i);
                tmp += '"';
                i += 2;
                sbegin = i;
            }
            if (sbegin != substr.begin()) {
                tmp.append(sbegin, send);
            }
            if (!tmp.empty()) {
                substr = move(tmp);
            }
        }
        primitive_variant result(ptype);
        result.apply(from_string(substr));
        return result;
    }

    void read_tuple(size_t size,
                    const primitive_type* begin,
                    primitive_variant* storage) {
        integrity_check();
        consume('{');
        const primitive_type* end = begin + size;
        for ( ; begin != end; ++begin) {
            *storage = move(read_value(*begin));
            ++storage;
        }
        consume('}');
    }

    void read_raw(size_t buf_size, void* vbuf) {
        auto buf = reinterpret_cast<unsigned char*>(vbuf);
        integrity_check();
        skip_space_and_comma();
        auto next_nibble = [&]() -> size_t {
            if (*m_pos == '\0') {
                throw_malformed("unexpected end-of-string");
            }
            char c = *m_pos++;
            if (!isxdigit(c)) {
                throw_malformed("unexpected character, expected [0-9a-f]");
            }
            return static_cast<size_t>(isdigit(c) ? c - '0' : (c - 'a' + 10));
        };
        for (size_t i = 0; i < buf_size; ++i) {
            auto nibble = next_nibble();
            *buf++ = static_cast<unsigned char>((nibble << 4) | next_nibble());
        }
    }

};

} // namespace <anonymous>

object from_string(const string& what) {
    string_deserializer strd(what);
    string uname = strd.peek_object();
    auto utype = uniform_type_info::from(uname);
    if (utype == nullptr) {
        throw logic_error(uname + " is not announced");
    }
    return utype->deserialize(&strd);
}

namespace detail {

string to_string_impl(const void *what, const uniform_type_info *utype) {
    ostringstream osstr;
    string_serializer strs(osstr);
    utype->serialize(what, &strs);
    return osstr.str();
}

} // namespace detail

} // namespace cppa
<|endoftext|>


<commit_before>#include <v8.h>
#include <node.h>

using namespace node;
using namespace v8;

// We start with an empty global scope, but we need various JavaScript
// primitives (Array, Object, encode, parseInt, etc).  We're going to create
// these primitives by running a script and assigning the result to a property
// on the global scope.
//
// There are two types of primitives: primitives we extract in the context
// (e.g. constructor for String) and primitives we extract from Zombie's global
// scope (e.g. Date object). The former has their InContext flag set to true.
//
// Since there is no String in our global scope, we need to either get it from
// another scope or create it in some other way. If we copy it from another
// scope, we get a different function, and when we later try to do something
// like this, if fails: "foo".constructor == String
//
// So instead we're going to use the current context to get the constructor for
// an empty string and assign that to the String property. We need to do this
// in the same context in which we're going to use the global scope.
//
// OTOH we have no way of obtaining a constructor for Date in that way, so we
// copy it from Zombie's global scope, and to do that we need to execute the
// script in the current context.
//
// If we're just copying a function, the script is the same as the primitive
// name and you can use the single argument constructor.
class SetPrimitive { private:
  // The script we're going to execute. Compile once for performance (this
  // really makes a difference of about 1 second in the test suite).
  Persistent<Script> script; const char *name; bool in_context;

public:
  // All powerful constructor. Specify primitive name, code we need to run to
  // extract its value, and whether or not we need to run it in context.
  //
  // If called with two arguments, we assume this script needs to be evaluated
  // in context.
  //
  // If called with one argument, we assume it's copying a property from the
  // current context, the code is the same as the primitive name and it
  // executes in the current context.
  SetPrimitive(const char *name, const char *code = NULL, bool in_context = true) {
    this->name = name;
    if (code == NULL) {
      code = name;
      in_context = false;
    }
    script = Persistent<Script>::New(Script::New(String::New(code)));
    this->in_context = in_context;
  }

  // Returns the name of this primitive (e.g. Array, escape).
  Handle<String> GetName() {
    return String::New(name);
  }

  // Returns the value of this primitive (e.g. array constructor, escape function).
  Handle<Value> GetValue() {
    return script->Run();
  }

  // Returns true if we need to run this primitive in context.
  bool InContext() {
    return in_context;
  }

};

// Isolated V8 Context/global scope for evaluating JavaScript, with access to
// all window methods/properties.
class WindowContext: ObjectWrap {
private:

  // V8 Context we evaluate all code in.
  Persistent<Context> context;
  // Global scope provides access to properties and methods.
  Persistent<Object> global;

public:

  static Persistent<FunctionTemplate> s_ct;
  static SetPrimitive *primitives[];

  static void Init(Handle<Object> target) {
    Local<FunctionTemplate> t = FunctionTemplate::New(New);

    s_ct = Persistent<FunctionTemplate>::New(t);
    s_ct->InstanceTemplate()->SetInternalFieldCount(1);
    s_ct->SetClassName(String::NewSymbol("WindowContext"));

    Local<ObjectTemplate> instance_t = t->InstanceTemplate();
    instance_t->SetAccessor(String::New("global"), GetGlobal);
    instance_t->SetAccessor(String::New("g"), GetG);
    NODE_SET_PROTOTYPE_METHOD(s_ct, "evaluate", Evaluate);

    target->Set(String::NewSymbol("WindowContext"), s_ct->GetFunction());
  }

  // Create a new wrapper context around the global object.
  WindowContext(Handle<Object> global) {
    Handle<ObjectTemplate> tmpl = ObjectTemplate::New();
    this->global = Persistent<Object>::New(global);
    tmpl->SetNamedPropertyHandler(GetProperty, SetProperty, QueryProperty, DeleteProperty, EnumerateProperties, this->global);
    context = Context::New(NULL, tmpl);

    // Copy primitivies in context.
    context->Enter();
    SetPrimitive *primitive;
    for (int i = 0 ; (primitive = primitives[i]) ; ++i)
      if (primitive->InContext())
        global->Set(primitive->GetName(), primitive->GetValue());
    context->Exit();
    // Copy primitivies outside context.
    for (int i = 0 ; (primitive = primitives[i]) ; ++i)
      if (!primitive->InContext())
        global->Set(primitive->GetName(), primitive->GetValue());
  }

  ~WindowContext() {
    global.Dispose();
    context.Dispose();
  }

  // Takes single argument, the global object.
  static Handle<Value> New(const Arguments& args) {
    WindowContext* wc = new WindowContext(Handle<Object>::Cast(args[0]));
    wc->Wrap(args.This());
    return args.This();
  }

  // Returns the global object.
  static Handle<Value> GetGlobal(Local<String> name, const AccessorInfo& info) {
    WindowContext* wc = ObjectWrap::Unwrap<WindowContext>(info.This());
    return wc->global;
  }

  static Handle<Value> GetG(Local<String> name, const AccessorInfo& info) {
    WindowContext* wc = ObjectWrap::Unwrap<WindowContext>(info.This());
    return wc->context->Global();
  }

  // Evaluate expression or function in this context.  First argument is either
  // a function or a script (String).  In the later case, second argument
  // specifies filename.
  static Handle<Value> Evaluate(const Arguments& args) {
    WindowContext* wc = ObjectWrap::Unwrap<WindowContext>(args.This());
    Handle<Value> result;
    TryCatch trycatch;
    wc->context->Enter();
    if (args[0]->IsFunction()) {
      // Execute function in the global scope.
      Function *fn = Function::Cast(*args[0]);
      result = fn->Call(wc->global, 0, NULL);
    } else {
      // Coerce argument into a string and execute that as a function.
      Local<String> source = args[0]->ToString();
      Local<String> filename = args[1]->ToString();
      Handle<Script> script = Script::New(source, filename);
      result = script->Run();
    }
    wc->context->Exit();
    if (result.IsEmpty())
      trycatch.ReThrow();
    return result;
  }

  // Returns the value of a property from the global scope.
  static Handle<Value> GetProperty(Local<String> name, const AccessorInfo &info) {
    Local<Object> self = Local<Object>::Cast(info.Data());
    return self->Get(name);
  }

  // Sets the value of a property in the global scope.
  static Handle<Value> SetProperty(Local<String> name, Local<Value> value, const AccessorInfo &info) {
    Local<Object> self = Local<Object>::Cast(info.Data());
    self->Set(name, Persistent<Value>::New(value));
    return value;
  }

  // Deletes a property from the global scope.
  static Handle<Boolean> DeleteProperty(Local<String> name, const AccessorInfo &info) {
    HandleScope scope;
    Local<Object> self = Local<Object>::Cast(info.Data());
    Persistent<Value> value = (Persistent<Value>) self->Get(name);
    bool deleted = self->Delete(name);
    if (deleted)
      value.Dispose();
    return scope.Close(Boolean::New(deleted));
  }

  // Enumerate all named properties in the global scope.
  static Handle<Array> EnumerateProperties(const AccessorInfo &info) {
    HandleScope scope;
    Local<Object> self = Local<Object>::Cast(info.Data());
    return scope.Close(self->GetPropertyNames());
  }

  static Handle<Integer> QueryProperty(Local<String> name, const AccessorInfo &info) {
    HandleScope scope;
    return scope.Close(Integer::New(None));
  }

};

Persistent<FunctionTemplate> WindowContext::s_ct;
SetPrimitive *WindowContext::primitives[] = {
  new SetPrimitive("Array", "[].constructor"),
  new SetPrimitive("Boolean", "true.constructor"),
  new SetPrimitive("Function", "(function() {}).constructor"),
  new SetPrimitive("Number", "(1).constructor"),
  new SetPrimitive("Object", "({}).constructor"),
  new SetPrimitive("RegExp", "/./.constructor"),
  new SetPrimitive("String", "''.constructor"),
  new SetPrimitive("Date"),
  new SetPrimitive("Error"),
  new SetPrimitive("Image", "{}", false),
  new SetPrimitive("Math"),
  new SetPrimitive("decodeURI"),
  new SetPrimitive("decodeURIComponent"),
  new SetPrimitive("encodeURI"),
  new SetPrimitive("encodeURIComponent"),
  new SetPrimitive("escape"),
  new SetPrimitive("eval"),
  new SetPrimitive("isFinite"),
  new SetPrimitive("isNaN"),
  new SetPrimitive("parseFloat"),
  new SetPrimitive("parseInt"),
  new SetPrimitive("unescape")
};

extern "C" {
  static void init(Handle<Object> target) {
    WindowContext::Init(target);
  }
  NODE_MODULE(window_context, init);
}
<commit_msg>Got to remember to not remove the terminating NULL.<commit_after>#include <v8.h>
#include <node.h>

using namespace node;
using namespace v8;

// We start with an empty global scope, but we need various JavaScript
// primitives (Array, Object, encode, parseInt, etc).  We're going to create
// these primitives by running a script and assigning the result to a property
// on the global scope.
//
// There are two types of primitives: primitives we extract in the context
// (e.g. constructor for String) and primitives we extract from Zombie's global
// scope (e.g. Date object). The former has their InContext flag set to true.
//
// Since there is no String in our global scope, we need to either get it from
// another scope or create it in some other way. If we copy it from another
// scope, we get a different function, and when we later try to do something
// like this, if fails: "foo".constructor == String
//
// So instead we're going to use the current context to get the constructor for
// an empty string and assign that to the String property. We need to do this
// in the same context in which we're going to use the global scope.
//
// OTOH we have no way of obtaining a constructor for Date in that way, so we
// copy it from Zombie's global scope, and to do that we need to execute the
// script in the current context.
//
// If we're just copying a function, the script is the same as the primitive
// name and you can use the single argument constructor.
class SetPrimitive { private:
  // The script we're going to execute. Compile once for performance (this
  // really makes a difference of about 1 second in the test suite).
  Persistent<Script> script; const char *name; bool in_context;

public:
  // All powerful constructor. Specify primitive name, code we need to run to
  // extract its value, and whether or not we need to run it in context.
  //
  // If called with two arguments, we assume this script needs to be evaluated
  // in context.
  //
  // If called with one argument, we assume it's copying a property from the
  // current context, the code is the same as the primitive name and it
  // executes in the current context.
  SetPrimitive(const char *name, const char *code = NULL, bool in_context = true) {
    this->name = name;
    if (code == NULL) {
      code = name;
      in_context = false;
    }
    script = Persistent<Script>::New(Script::New(String::New(code)));
    this->in_context = in_context;
  }

  // Returns the name of this primitive (e.g. Array, escape).
  Handle<String> GetName() {
    return String::New(name);
  }

  // Returns the value of this primitive (e.g. array constructor, escape function).
  Handle<Value> GetValue() {
    return script->Run();
  }

  // Returns true if we need to run this primitive in context.
  bool InContext() {
    return in_context;
  }

};

// Isolated V8 Context/global scope for evaluating JavaScript, with access to
// all window methods/properties.
class WindowContext: ObjectWrap {
private:

  // V8 Context we evaluate all code in.
  Persistent<Context> context;
  // Global scope provides access to properties and methods.
  Persistent<Object> global;

public:

  static Persistent<FunctionTemplate> s_ct;
  static SetPrimitive *primitives[];

  static void Init(Handle<Object> target) {
    Local<FunctionTemplate> t = FunctionTemplate::New(New);

    s_ct = Persistent<FunctionTemplate>::New(t);
    s_ct->InstanceTemplate()->SetInternalFieldCount(1);
    s_ct->SetClassName(String::NewSymbol("WindowContext"));

    Local<ObjectTemplate> instance_t = t->InstanceTemplate();
    instance_t->SetAccessor(String::New("global"), GetGlobal);
    instance_t->SetAccessor(String::New("g"), GetG);
    NODE_SET_PROTOTYPE_METHOD(s_ct, "evaluate", Evaluate);

    target->Set(String::NewSymbol("WindowContext"), s_ct->GetFunction());
  }

  // Create a new wrapper context around the global object.
  WindowContext(Handle<Object> global) {
    Handle<ObjectTemplate> tmpl = ObjectTemplate::New();
    this->global = Persistent<Object>::New(global);
    tmpl->SetNamedPropertyHandler(GetProperty, SetProperty, QueryProperty, DeleteProperty, EnumerateProperties, this->global);
    context = Context::New(NULL, tmpl);

    // Copy primitivies in context.
    context->Enter();
    SetPrimitive *primitive;
    for (int i = 0 ; (primitive = primitives[i]) ; ++i)
      if (primitive->InContext())
        global->Set(primitive->GetName(), primitive->GetValue());
    context->Exit();
    // Copy primitivies outside context.
    for (int i = 0 ; (primitive = primitives[i]) ; ++i)
      if (!primitive->InContext())
        global->Set(primitive->GetName(), primitive->GetValue());
  }

  ~WindowContext() {
    global.Dispose();
    context.Dispose();
  }

  // Takes single argument, the global object.
  static Handle<Value> New(const Arguments& args) {
    WindowContext* wc = new WindowContext(Handle<Object>::Cast(args[0]));
    wc->Wrap(args.This());
    return args.This();
  }

  // Returns the global object.
  static Handle<Value> GetGlobal(Local<String> name, const AccessorInfo& info) {
    WindowContext* wc = ObjectWrap::Unwrap<WindowContext>(info.This());
    return wc->global;
  }

  static Handle<Value> GetG(Local<String> name, const AccessorInfo& info) {
    WindowContext* wc = ObjectWrap::Unwrap<WindowContext>(info.This());
    return wc->context->Global();
  }

  // Evaluate expression or function in this context.  First argument is either
  // a function or a script (String).  In the later case, second argument
  // specifies filename.
  static Handle<Value> Evaluate(const Arguments& args) {
    WindowContext* wc = ObjectWrap::Unwrap<WindowContext>(args.This());
    Handle<Value> result;
    TryCatch trycatch;
    wc->context->Enter();
    if (args[0]->IsFunction()) {
      // Execute function in the global scope.
      Function *fn = Function::Cast(*args[0]);
      result = fn->Call(wc->global, 0, NULL);
    } else {
      // Coerce argument into a string and execute that as a function.
      Local<String> source = args[0]->ToString();
      Local<String> filename = args[1]->ToString();
      Handle<Script> script = Script::New(source, filename);
      result = script->Run();
    }
    wc->context->Exit();
    if (result.IsEmpty())
      trycatch.ReThrow();
    return result;
  }

  // Returns the value of a property from the global scope.
  static Handle<Value> GetProperty(Local<String> name, const AccessorInfo &info) {
    Local<Object> self = Local<Object>::Cast(info.Data());
    return self->Get(name);
  }

  // Sets the value of a property in the global scope.
  static Handle<Value> SetProperty(Local<String> name, Local<Value> value, const AccessorInfo &info) {
    Local<Object> self = Local<Object>::Cast(info.Data());
    self->Set(name, Persistent<Value>::New(value));
    return value;
  }

  // Deletes a property from the global scope.
  static Handle<Boolean> DeleteProperty(Local<String> name, const AccessorInfo &info) {
    HandleScope scope;
    Local<Object> self = Local<Object>::Cast(info.Data());
    Persistent<Value> value = (Persistent<Value>) self->Get(name);
    bool deleted = self->Delete(name);
    if (deleted)
      value.Dispose();
    return scope.Close(Boolean::New(deleted));
  }

  // Enumerate all named properties in the global scope.
  static Handle<Array> EnumerateProperties(const AccessorInfo &info) {
    HandleScope scope;
    Local<Object> self = Local<Object>::Cast(info.Data());
    return scope.Close(self->GetPropertyNames());
  }

  static Handle<Integer> QueryProperty(Local<String> name, const AccessorInfo &info) {
    HandleScope scope;
    return scope.Close(Integer::New(None));
  }

};

Persistent<FunctionTemplate> WindowContext::s_ct;
SetPrimitive *WindowContext::primitives[] = {
  new SetPrimitive("Array", "[].constructor"),
  new SetPrimitive("Boolean", "true.constructor"),
  new SetPrimitive("Function", "(function() {}).constructor"),
  new SetPrimitive("Number", "(1).constructor"),
  new SetPrimitive("Object", "({}).constructor"),
  new SetPrimitive("RegExp", "/./.constructor"),
  new SetPrimitive("String", "''.constructor"),
  new SetPrimitive("Date"),
  new SetPrimitive("Error"),
  new SetPrimitive("Image", "{}", false),
  new SetPrimitive("Math"),
  new SetPrimitive("decodeURI"),
  new SetPrimitive("decodeURIComponent"),
  new SetPrimitive("encodeURI"),
  new SetPrimitive("encodeURIComponent"),
  new SetPrimitive("escape"),
  new SetPrimitive("eval"),
  new SetPrimitive("isFinite"),
  new SetPrimitive("isNaN"),
  new SetPrimitive("parseFloat"),
  new SetPrimitive("parseInt"),
  new SetPrimitive("unescape"),
  NULL // please don't remove
};

extern "C" {
  static void init(Handle<Object> target) {
    WindowContext::Init(target);
  }
  NODE_MODULE(window_context, init);
}
<|endoftext|>


<commit_before>// Copyright 2014 BitPay Inc.
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <ctype.h>
#include <stdio.h>
#include "univalue.h"
#include "univalue_escapes.h"

// TODO: Using UTF8

using namespace std;

static string json_escape(const string& inS)
{
    string outS;
    outS.reserve(inS.size() * 2);

    for (unsigned int i = 0; i < inS.size(); i++) {
        unsigned char ch = inS[i];
        const char *escStr = escapes[ch];

        if (escStr)
            outS += escStr;

        else if (isprint(ch))
            outS += ch;

        else {
            char tmpesc[16];
            sprintf(tmpesc, "\\u%04x", ch);
            outS += tmpesc;
        }
    }

    return outS;
}

string UniValue::write(unsigned int prettyIndent,
                       unsigned int indentLevel) const
{
    string s;
    s.reserve(1024);

    unsigned int modIndent = indentLevel;
    if (modIndent == 0)
        modIndent = 1;

    switch (typ) {
    case VNULL:
        s += "null";
        break;
    case VOBJ:
        writeObject(prettyIndent, modIndent, s);
        break;
    case VARR:
        writeArray(prettyIndent, modIndent, s);
        break;
    case VSTR:
        s += "\"" + json_escape(val) + "\"";
        break;
    case VNUM:
        s += val;
        break;
    case VBOOL:
        s += (val == "1" ? "true" : "false");
        break;
    }

    return s;
}

static string spaceStr;

static string indentStr(unsigned int prettyIndent, unsigned int indentLevel)
{
    unsigned int spaces = prettyIndent * indentLevel;
    while (spaceStr.size() < spaces)
        spaceStr += "                ";

    return spaceStr.substr(0, spaces);
}

void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
{
    s += "[";
    if (prettyIndent)
        s += "\n";

    for (unsigned int i = 0; i < values.size(); i++) {
        if (prettyIndent)
            s += indentStr(prettyIndent, indentLevel);
        s += values[i].write(prettyIndent, indentLevel + 1);
        if (i != (values.size() - 1)) {
            s += ",";
            if (prettyIndent)
                s += " ";
        }
        if (prettyIndent)
            s += "\n";
    }

    if (prettyIndent)
        s += indentStr(prettyIndent, indentLevel - 1);
    s += "]";
}

void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
{
    s += "{";
    if (prettyIndent)
        s += "\n";

    for (unsigned int i = 0; i < keys.size(); i++) {
        if (prettyIndent)
            s += indentStr(prettyIndent, indentLevel);
        s += "\"" + json_escape(keys[i]) + "\":";
        if (prettyIndent)
            s += " ";
        s += values[i].write(prettyIndent, indentLevel + 1);
        if (i != (values.size() - 1))
            s += ",";
        if (prettyIndent)
            s += "\n";
    }

    if (prettyIndent)
        s += indentStr(prettyIndent, indentLevel - 1);
    s += "}";
}

<commit_msg>univalue: make spaceStr thread-safe<commit_after>// Copyright 2014 BitPay Inc.
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <ctype.h>
#include <stdio.h>
#include "univalue.h"
#include "univalue_escapes.h"

// TODO: Using UTF8

using namespace std;

static string json_escape(const string& inS)
{
    string outS;
    outS.reserve(inS.size() * 2);

    for (unsigned int i = 0; i < inS.size(); i++) {
        unsigned char ch = inS[i];
        const char *escStr = escapes[ch];

        if (escStr)
            outS += escStr;

        else if (isprint(ch))
            outS += ch;

        else {
            char tmpesc[16];
            sprintf(tmpesc, "\\u%04x", ch);
            outS += tmpesc;
        }
    }

    return outS;
}

string UniValue::write(unsigned int prettyIndent,
                       unsigned int indentLevel) const
{
    string s;
    s.reserve(1024);

    unsigned int modIndent = indentLevel;
    if (modIndent == 0)
        modIndent = 1;

    switch (typ) {
    case VNULL:
        s += "null";
        break;
    case VOBJ:
        writeObject(prettyIndent, modIndent, s);
        break;
    case VARR:
        writeArray(prettyIndent, modIndent, s);
        break;
    case VSTR:
        s += "\"" + json_escape(val) + "\"";
        break;
    case VNUM:
        s += val;
        break;
    case VBOOL:
        s += (val == "1" ? "true" : "false");
        break;
    }

    return s;
}

static void indentStr(unsigned int prettyIndent, unsigned int indentLevel, string& s)
{
    s.append(prettyIndent * indentLevel, ' ');
}

void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
{
    s += "[";
    if (prettyIndent)
        s += "\n";

    for (unsigned int i = 0; i < values.size(); i++) {
        if (prettyIndent)
            indentStr(prettyIndent, indentLevel, s);
        s += values[i].write(prettyIndent, indentLevel + 1);
        if (i != (values.size() - 1)) {
            s += ",";
            if (prettyIndent)
                s += " ";
        }
        if (prettyIndent)
            s += "\n";
    }

    if (prettyIndent)
        indentStr(prettyIndent, indentLevel - 1, s);
    s += "]";
}

void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
{
    s += "{";
    if (prettyIndent)
        s += "\n";

    for (unsigned int i = 0; i < keys.size(); i++) {
        if (prettyIndent)
            indentStr(prettyIndent, indentLevel, s);
        s += "\"" + json_escape(keys[i]) + "\":";
        if (prettyIndent)
            s += " ";
        s += values[i].write(prettyIndent, indentLevel + 1);
        if (i != (values.size() - 1))
            s += ",";
        if (prettyIndent)
            s += "\n";
    }

    if (prettyIndent)
        indentStr(prettyIndent, indentLevel - 1, s);
    s += "}";
}

<|endoftext|>


<commit_before>#ifndef PARSER__HH
#define PARSER__HH

#include <map>
#include <iostream>
#include <string>
#include <vector>

namespace optionparser
{

typedef std::map<std::string, std::map<std::string, std::vector<std::string>>> Dictionary;

enum storage_mode { store_true, store_value, store_mult_values };

class parser
{
public:
	parser();
	~parser();

	void eat_arguments(int argc, char const *argv[]);

	void add_option(std::string longoption, std::string shortoption, storage_mode mode, std::string key = "", bool required = false);
	void add_option(std::string shortoption, storage_mode mode, std::string key = "", bool required = false);

	template <class T>
	T get_value(std::string key);

private:
	Dictionary options;

};

}

#endif<commit_msg>worked on option adding<commit_after>#ifndef PARSER__HH
#define PARSER__HH

#include <map>
#include <iostream>
#include <string>
#include <vector>

namespace optionparser
{

inline std::string remove_character(std::string str, char c = ' ');

typedef std::map<std::string, std::map<std::string, std::vector<std::string>>> Archive;

typedef std::map<std::string, std::map<std::string, std::string>> Dictionary;

enum storage_mode { store_true, store_value, store_mult_values };

class parser
{
public:
	parser();
	~parser();

	// void eat_arguments(int argc, char const *argv[]);

	void add_option(std::string longoption, std::string shortoption, storage_mode mode, std::string key = "", bool required = false);
	void add_option(std::string shortoption, storage_mode mode, std::string key = "", bool required = false);

	// template <class T>
	// T get_value(std::string key);

private:
	Archive m_options;
	Dictionary m_long_flags, m_short_flags;
};

void parser::add_option(std::string longoption, std::string shortoption,
	storage_mode mode, std::string key = "", bool required = false)
{
	if (key == "")
	{
		key = remove_character(longoption, '-');
	}
	if (required)
	{
		std::string req_string = "required";
	}
	else
	{
		std::string req_string = "optional";
	}
	m_long_flags[req_string][key] = shortoption;
	m_short_flags[req_string][key] = longoption;
}

inline std::string remove_character(std::string str, char c)
{
    std::string::iterator end_pos = std::remove(str.begin(), str.end(), c);
    str.erase(end_pos, str.end());
    return str;
}

}

#endif<|endoftext|>