<commit_before>/*

The MIT License (MIT)

Copyright (c) 2014 https://github.com/labyrinthofdreams

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.

*/

#ifndef NODES_HPP
#define NODES_HPP

#include <cstddef>
#include <stdexcept>
#include <string>
#include <vector>
#include "types.hpp"

namespace templet {
namespace exception {

/**
 * @brief The invalid tag error is a generic error type
 */
class InvalidTagError : public std::runtime_error {
public:
    InvalidTagError(const char* reason) : std::runtime_error(reason) {}
    InvalidTagError(const std::string& reason) : std::runtime_error(reason) {}
};

/**
 * @brief The missing tag error is thrown when a referenced name
 * in a template tag is not found in the map of values
 */
class MissingTagError : public std::runtime_error {
public:
    MissingTagError(const char* reason) : std::runtime_error(reason) {}
    MissingTagError(const std::string& reason) : std::runtime_error(reason) {}
};

/**
 * @brief The expression syntax error is thrown when there's an error
 * in parsing tag expressions (e.g. if, for)
 */
class ExpressionSyntaxError : public std::runtime_error {
public:
    ExpressionSyntaxError(const char* reason) : std::runtime_error(reason) {}
    ExpressionSyntaxError(const std::string& reason) : std::runtime_error(reason) {}
};

} // namespace exception

namespace nodes {

using ::templet::types::DataMap;

/**
 * @brief The NodeType enum describes what the node represents
 */
enum class NodeType {
    Invalid,    ///< Base Node class
    Text,       ///< A text block
    Value,      ///< A variable block
    IfValue,    ///< An if block
    ElifValue,  ///< An elif block
    ElseValue,  ///< An else block
    ForValue    ///< A for loop block
};

/**
 * @brief The Node class represents a block from the template
 */
class Node {
public:
    Node() = default;

    virtual ~Node() = default;

    /**
     * @brief Set child nodes for this node type
     *
     * By-value parameter leaves the option for user to copy/move the children
     *
     * @exception std::runtime_error If called on a node that doesn't support children
     */
    virtual void setChildren(std::vector<std::shared_ptr<Node>> /*newNodes*/);

    /**
     * @brief Evaluates the Node and outputs the computed value in ostream os
     */
    virtual void evaluate(std::ostream& /*os*/, const DataMap& /*kv*/) const = 0;

    virtual NodeType type() const;
};

/**
 * @brief The Text class represents a plain text block in the template
 */
class Text : public Node {
private:
    std::string _in;

public:
    Text() = default;

    /**
     * @brief Construct a text node with text
     * @param text Text block from the template
     */
    Text(std::string text);

    void evaluate(std::ostream& os, const DataMap& /*kv*/) const override;

    NodeType type() const override;
};

/**
 * @brief The Value class represents a variable in the template
 *
 * Variables can be replaced by another value in the output
 */
class Value : public Node {
private:
    std::string _name;

public:
    /**
     * @brief Construct a value node with name
     *
     * See \link isValidTag \endlink for valid tag names
     *
     * @param name Variable name to replace
     * @exception Throws templet::exception::InvalidTagError if invalid tag name
     */
    Value(std::string name);

    void evaluate(std::ostream& os, const DataMap& kv) const override;

    NodeType type() const override;
};

/**
 * @brief The IfValue class represents a conditional block in the template
 *
 * Conditional blocks can be omitted/included from the output
 */
class IfValue : public Node {
protected:
    std::string _name;
    std::vector<std::shared_ptr<Node>> _nodes;

public:
    /**
     * @brief Construct an if block node with name
     *
     * See \link isValidTag \endlink for valid tag names
     *
     * @param name Name of the conditional if block
     * @exception Throws templet::exception::InvalidTagError if invalid tag name
     */
    IfValue(std::string name);

    void setChildren(std::vector<std::shared_ptr<Node>> children) override;

    void evaluate(std::ostream& os, const DataMap& kv) const override;

    NodeType type() const override;
};

class ElifValue : public IfValue {
public:
    ElifValue(std::string name);

    virtual NodeType type() const override;
};

class ElseValue : public Node {
private:
    std::vector<std::shared_ptr<Node>> _nodes;

public:
    ElseValue() = default;

    void setChildren(std::vector<std::shared_ptr<Node>> children) override;

    void evaluate(std::ostream& os, const DataMap& kv) const override;

    NodeType type() const override;
};

/**
 * @brief The ForValue class represents a for statement block
 *
 * For statements can be used to traverse lists
 */
class ForValue : public Node {
private:
    std::string _name;
    std::string _alias;
    std::vector<std::shared_ptr<Node>> _nodes;

public:
    ForValue(std::string name, std::string alias);

    void setChildren(std::vector<std::shared_ptr<Node>> children) override;

    void evaluate(std::ostream& os, const DataMap& kv) const override;

    NodeType type() const override;
};

/**
 * @brief Parse a value tag
 *
 * Ex: {$first_name}
 *
 * @param in String to parse
 * @exception templet::exception::InvalidTagError if invalid tag
 * @return Parsed tag as unique pointer to Value node
 */
std::shared_ptr<Node> parse_value_tag(std::string in);

/**
 * @brief Parse an if value tag
 *
 * Ex: {% if is_admin %}
 *
 * @param in String to parse
 * @exception templet::exception::InvalidTagError if invalid tag
 * @return Parsed tag as unique pointer to IfValue node
 */
std::shared_ptr<Node> parse_ifvalue_tag(std::string in);

std::shared_ptr<Node> parse_elifvalue_tag(std::string in);

/**
 * @brief Parse a for value tag
 *
 * Ex: {% for users as user %}{$ user }{% endfor %}
 *
 * @param in String to parse
 * @exception templet::exception::InvalidTagError if invalid tag
 * @return Parsed tag as unique pointer to ForValue node
 */
std::shared_ptr<Node> parse_forvalue_tag(std::string in);

} // namespace nodes
} // namespace templet

#endif // NODES_HPP
<commit_msg>Add documentation<commit_after>/*

The MIT License (MIT)

Copyright (c) 2014 https://github.com/labyrinthofdreams

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.

*/

#ifndef NODES_HPP
#define NODES_HPP

#include <cstddef>
#include <stdexcept>
#include <string>
#include <vector>
#include "types.hpp"

namespace templet {
namespace exception {

/**
 * @brief The invalid tag error is a generic error type
 */
class InvalidTagError : public std::runtime_error {
public:
    InvalidTagError(const char* reason) : std::runtime_error(reason) {}
    InvalidTagError(const std::string& reason) : std::runtime_error(reason) {}
};

/**
 * @brief The missing tag error is thrown when a referenced name
 * in a template tag is not found in the map of values
 */
class MissingTagError : public std::runtime_error {
public:
    MissingTagError(const char* reason) : std::runtime_error(reason) {}
    MissingTagError(const std::string& reason) : std::runtime_error(reason) {}
};

/**
 * @brief The expression syntax error is thrown when there's an error
 * in parsing tag expressions (e.g. if, for)
 */
class ExpressionSyntaxError : public std::runtime_error {
public:
    ExpressionSyntaxError(const char* reason) : std::runtime_error(reason) {}
    ExpressionSyntaxError(const std::string& reason) : std::runtime_error(reason) {}
};

} // namespace exception

namespace nodes {

using ::templet::types::DataMap;

/**
 * @brief The NodeType enum describes what the node represents
 */
enum class NodeType {
    Invalid,    ///< Base Node class
    Text,       ///< A text block
    Value,      ///< A variable block
    IfValue,    ///< An if block
    ElifValue,  ///< An elif block
    ElseValue,  ///< An else block
    ForValue    ///< A for loop block
};

/**
 * @brief The Node class represents a block from the template
 */
class Node {
public:
    Node() = default;

    virtual ~Node() = default;

    /**
     * @brief Set child nodes for this node type
     *
     * By-value parameter leaves the option for user to copy/move the children
     *
     * @exception std::runtime_error If called on a node that doesn't support children
     */
    virtual void setChildren(std::vector<std::shared_ptr<Node>> /*newNodes*/);

    /**
     * @brief Evaluates the Node and outputs the computed value in ostream os
     */
    virtual void evaluate(std::ostream& /*os*/, const DataMap& /*kv*/) const = 0;

    virtual NodeType type() const;
};

/**
 * @brief The Text class represents a plain text block in the template
 */
class Text : public Node {
private:
    std::string _in;

public:
    Text() = default;

    /**
     * @brief Construct a text node with text
     * @param text Text block from the template
     */
    Text(std::string text);

    void evaluate(std::ostream& os, const DataMap& /*kv*/) const override;

    NodeType type() const override;
};

/**
 * @brief The Value class represents a variable in the template
 *
 * Variables can be replaced by another value in the output
 */
class Value : public Node {
private:
    std::string _name;

public:
    /**
     * @brief Construct a value node with name
     *
     * See \link isValidTag \endlink for valid tag names
     *
     * @param name Variable name to replace
     * @exception Throws templet::exception::InvalidTagError if invalid tag name
     */
    Value(std::string name);

    void evaluate(std::ostream& os, const DataMap& kv) const override;

    NodeType type() const override;
};

/**
 * @brief The IfValue class represents a conditional block in the template
 *
 * Conditional blocks can be omitted/included from the output
 */
class IfValue : public Node {
protected:
    std::string _name;
    std::vector<std::shared_ptr<Node>> _nodes;

public:
    /**
     * @brief Construct an if block node with name
     *
     * See \link isValidTag \endlink for valid tag names
     *
     * @param name Name of the conditional if block
     * @exception Throws templet::exception::InvalidTagError if invalid tag name
     */
    IfValue(std::string name);

    void setChildren(std::vector<std::shared_ptr<Node>> children) override;

    void evaluate(std::ostream& os, const DataMap& kv) const override;

    NodeType type() const override;
};

/**
 * @brief \sa IfValue
 */
class ElifValue : public IfValue {
public:
    ElifValue(std::string name);

    virtual NodeType type() const override;
};

/**
 * @brief Else value evaluates its child nodes if
 * previous if-elif nodes failed
 */
class ElseValue : public Node {
private:
    std::vector<std::shared_ptr<Node>> _nodes;

public:
    ElseValue() = default;

    void setChildren(std::vector<std::shared_ptr<Node>> children) override;

    void evaluate(std::ostream& os, const DataMap& kv) const override;

    NodeType type() const override;
};

/**
 * @brief The ForValue class represents a for statement block
 *
 * For statements can be used to traverse lists
 */
class ForValue : public Node {
private:
    std::string _name;
    std::string _alias;
    std::vector<std::shared_ptr<Node>> _nodes;

public:
    ForValue(std::string name, std::string alias);

    void setChildren(std::vector<std::shared_ptr<Node>> children) override;

    void evaluate(std::ostream& os, const DataMap& kv) const override;

    NodeType type() const override;
};

/**
 * @brief Parse a value tag
 *
 * Ex: {$first_name}
 *
 * @param in String to parse
 * @exception templet::exception::InvalidTagError if invalid tag
 * @return Parsed tag
 */
std::shared_ptr<Node> parse_value_tag(std::string in);

/**
 * @brief Parse an if value tag
 *
 * Ex: {% if is_admin %}
 *
 * @param in String to parse
 * @exception templet::exception::InvalidTagError if invalid tag
 * @return Parsed tag as unique pointer to IfValue node
 */
std::shared_ptr<Node> parse_ifvalue_tag(std::string in);

/**
 * @brief \sa parse_ifvalue_tag
 * @param in String to parse
 * @exception templet::exception::InvalidTagError if invalid tag
 * @return Parsed tag
 */
std::shared_ptr<Node> parse_elifvalue_tag(std::string in);

/**
 * @brief Parse a for value tag
 *
 * Ex: {% for users as user %}{$ user }{% endfor %}
 *
 * @param in String to parse
 * @exception templet::exception::InvalidTagError if invalid tag
 * @return Parsed tag
 */
std::shared_ptr<Node> parse_forvalue_tag(std::string in);

} // namespace nodes
} // namespace templet

#endif // NODES_HPP
<|endoftext|>


<commit_before>#include "opencv2/highgui/highgui.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>

#include <sys/types.h>      // for folder cration in ubuntu
#include <sys/stat.h>         // for folder cration in ubuntu
#include <unistd.h>            // for folder cration in ubuntu

//############## VARIABLES #######################
enum Mode{IMGCAP, VIDEXT, VIEW, EXIT};
cv::Mat frameShow;
cv::Mat frame;

//############## SETTINGS ########################
Mode mode = VIEW;
//const size_t nbimg = 0;

//############## FUNCTION PROTOTYPES ###############
void liveView();
void imgcap();
bool vidext();
bool keyhandler();
void showText(std::string text, cv::Mat &img, int pos);
void createSavesFolder(std::string filename);
void capture(cv::Mat &img);
void capture(size_t &count, cv::Mat &img);

int main(int argc, char *argv[]){
  createSavesFolder("../saves");
  createSavesFolder("../vid_extr2");
  while(true){
      switch(mode){
        case IMGCAP : imgcap(); break;
        case VIDEXT : vidext(); break;
        case VIEW : liveView(); break;
        case EXIT : return(0);
        }
      keyhandler();
      cv::imshow("Imeo Tool", frameShow);
      cv::waitKey(1);
    }
}

inline void liveView(){
  capture(frameShow);
  showText("Press 's' to start/stop recording", frameShow, 3);
  showText("Press 'v' to extract an img seq of a .mp4 video file", frameShow, 2);
}

inline void imgcap(){
  static size_t i = 0;
  capture(frameShow);
  frame = frameShow.clone();
  std::stringstream filename;
  filename << "img" << std::setw(5) << std::setfill('0') << std::to_string(i) << ".png";
  std::stringstream msg;
  msg << "File " << filename.str() << " saved!";
  filename.str("../saves/"+filename.str());
  cv::imwrite(filename.str(), frame);
  showText(msg.str(), frameShow, 2);
  i++;
}

inline bool vidext(){
  static size_t i = 0;
  static size_t count = 0;
  static cv::VideoCapture video("../dataset2.mp4");
  static const size_t count_max = (video.get(CV_CAP_PROP_FRAME_COUNT)-1);
  if(count >= count_max){
      showText("Video extracting finished", frameShow, 2);
      cv::waitKey(1000);
      showText("Video extracting finished.", frameShow, 2);
      cv::waitKey(1000);
      showText("Video extracting finished..", frameShow, 2);
      cv::waitKey(1000);
      showText("Video extracting finished...", frameShow, 2);
      cv::waitKey(1000);
      showText("\n>> Starting livestream in 2 seconds...", frameShow, 2);
      cv::waitKey(2000);
      mode = VIEW;
      return 0;
    } else{
      capture(count, frame);
      frameShow = frame.clone();

      std::stringstream filename;
      filename << "vid" << std::setw(5) << std::setfill('0') << std::to_string(count) << ".png";
      std::stringstream msg;
      msg << "File " << filename.str() << " saved!";
      filename.str("../vid_extr2/"+filename.str());
      count++;

      cv::imwrite(filename.str(), frame);
      showText(msg.str(), frameShow, 2);
    }
}

inline bool keyhandler(){
  switch(cv::waitKey(10)){
    case 's' : mode = mode == IMGCAP ? VIEW : IMGCAP; break;
    case 'v' : mode = mode == VIDEXT ? VIEW : VIDEXT; break;
    case 27 : std::cout << "\t(info) ESC key pressed by user" << std::endl; mode = EXIT; return(false); break;
    }
  return true;
}

inline void showText(std::string text, cv::Mat &img, int pos){
  int baseline = 0;
  const int tFont = cv::FONT_HERSHEY_SIMPLEX;
  const double tScale = 0.7;
  const cv::Scalar tColour(255, 0, 60);
  const int tLineType = cv::LineTypes::LINE_AA;
  const int tThickness = 1;
  cv::Size textprop = cv::getTextSize(text, tFont, tScale, tThickness, &baseline);
  cv::Point tOrigin(static_cast<int>(img.cols/2), static_cast<int>(img.rows-textprop.height*pos*1.2));
  cv::putText(img, text, tOrigin, tFont, tScale, tColour, tThickness, tLineType, false);
}

void createSavesFolder(std::string filename){
  struct stat st = {0};
  if (stat(filename.c_str(), &st) == -1) {      // creating directory if not existing
      mkdir(filename.c_str(), 0700);
    }
}

void capture(cv::Mat &img){
  switch(mode){
    case VIEW :
    case IMGCAP :
      static cv::VideoCapture cap(0);
      cap >> img;
      break;
    default : // do nothing
      break;
    }
}

void capture(size_t &count, cv::Mat &img){
  static cv::VideoCapture video("../dataset2.mp4");
  video.set(CV_CAP_PROP_POS_FRAMES, count);
  video.read(img);
}
<commit_msg>added additional documentation<commit_after>#include "opencv2/highgui/highgui.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/imgproc.hpp"

#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>            // for setw(), setfill(), etc.

#include <sys/types.h>      // for folder cration in ubuntu
#include <sys/stat.h>         // for folder cration in ubuntu
#include <unistd.h>            // for folder cration in ubuntu

//############## VARIABLES #######################
enum Mode{IMGCAP, VIDEXT, VIEW, EXIT};
cv::Mat frameShow;
cv::Mat frame;

//############## SETTINGS ########################
Mode mode = VIEW;
//const size_t nbimg = 0;

//############## FUNCTION PROTOTYPES ###############
// camera live view
void liveView();
// saves images from camera live view
void imgcap();
// extracts an image sequence from a video
bool vidext();
// program control
bool keyhandler();
// text overlay in live view
void showText(std::string text, cv::Mat &img, int pos);
// folder creation
void createSavesFolder(std::string filename);
// nomal capture
void capture(cv::Mat &img);
// capture for creating image sequences from videos >> esp. for vidext()
void capture(size_t &count, cv::Mat &img);

int main(int argc, char *argv[]){
  createSavesFolder("../saves");
  createSavesFolder("../vid_extr2");
  while(true){
      switch(mode){
        case IMGCAP : imgcap(); break;
        case VIDEXT : vidext(); break;
        case VIEW : liveView(); break;
        case EXIT : return(0);
        }
      keyhandler();
      cv::imshow("Imeo Tool", frameShow);
      cv::waitKey(1);
    }
}

inline void liveView(){
  capture(frameShow);
  showText("Press 's' to start/stop recording", frameShow, 3);
  showText("Press 'v' to extract an img seq of a .mp4 video file", frameShow, 2);
}

inline void imgcap(){
  static size_t i = 0;
  capture(frameShow);
  frame = frameShow.clone();
  std::stringstream filename;
  filename << "img" << std::setw(5) << std::setfill('0') << std::to_string(i) << ".png";
  std::stringstream msg;
  msg << "File " << filename.str() << " saved!";
  filename.str("../saves/"+filename.str());
  cv::imwrite(filename.str(), frame);
  showText(msg.str(), frameShow, 2);
  i++;
}

inline bool vidext(){
  static size_t i = 0;
  static size_t count = 0;
  static cv::VideoCapture video("../dataset2.mp4");
  static const size_t count_max = (video.get(CV_CAP_PROP_FRAME_COUNT)-1);
  if(count >= count_max){
      showText("Video extracting finished", frameShow, 2);
      cv::waitKey(1000);
      showText("Video extracting finished.", frameShow, 2);
      cv::waitKey(1000);
      showText("Video extracting finished..", frameShow, 2);
      cv::waitKey(1000);
      showText("Video extracting finished...", frameShow, 2);
      cv::waitKey(1000);
      showText("\n>> Starting livestream in 2 seconds...", frameShow, 2);
      cv::waitKey(2000);
      mode = VIEW;
      return 0;
    } else{
      capture(count, frame);
      frameShow = frame.clone();

      std::stringstream filename;
      filename << "vid" << std::setw(5) << std::setfill('0') << std::to_string(count) << ".png";
      std::stringstream msg;
      msg << "File " << filename.str() << " saved!";
      filename.str("../vid_extr2/"+filename.str());
      count++;

      cv::imwrite(filename.str(), frame);
      showText(msg.str(), frameShow, 2);
    }
}

inline bool keyhandler(){
  switch(cv::waitKey(10)){
    case 's' : mode = mode == IMGCAP ? VIEW : IMGCAP; break;
    case 'v' : mode = mode == VIDEXT ? VIEW : VIDEXT; break;
    case 27 : std::cout << "\t(info) ESC key pressed by user" << std::endl; mode = EXIT; return(false); break;
    }
  return true;
}

inline void showText(std::string text, cv::Mat &img, int pos){
  int baseline = 0;
  const int tFont = cv::FONT_HERSHEY_SIMPLEX;
  const double tScale = 0.7;
  const cv::Scalar tColour(255, 0, 60);
  const int tLineType = cv::LineTypes::LINE_AA;
  const int tThickness = 1;
  cv::Size textprop = cv::getTextSize(text, tFont, tScale, tThickness, &baseline);
  cv::Point tOrigin(static_cast<int>(img.cols/2), static_cast<int>(img.rows-textprop.height*pos*1.2));
  cv::putText(img, text, tOrigin, tFont, tScale, tColour, tThickness, tLineType, false);
}

void createSavesFolder(std::string filename){
  struct stat st = {0};
  if (stat(filename.c_str(), &st) == -1) {      // creating directory if not existing
      mkdir(filename.c_str(), 0700);
    }
}

void capture(cv::Mat &img){
  switch(mode){
    case VIEW :
    case IMGCAP :
      static cv::VideoCapture cap(0);
      cap >> img;
      break;
    default : // do nothing
      break;
    }
}

void capture(size_t &count, cv::Mat &img){
  static cv::VideoCapture video("../dataset2.mp4");
  video.set(CV_CAP_PROP_POS_FRAMES, count);
  video.read(img);
}
<|endoftext|>


<commit_before>/*
 * SessionProjectTemplate.cpp
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
#include <session/SessionProjectTemplate.hpp>

#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/function.hpp>
#include <boost/range/adaptors.hpp>

#include <core/Algorithm.hpp>
#include <core/Error.hpp>
#include <core/Exec.hpp>
#include <core/FilePath.hpp>
#include <core/FileSerializer.hpp>
#include <core/text/DcfParser.hpp>

#include <session/SessionModuleContext.hpp>

#include <session/SessionPackageProvidedExtension.hpp>

#define kProjectTemplateLocal "(local)"
#define kRStudioProjectTemplatesPath "rstudio/projects/templates"

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace projects {
namespace templates {

Error fromJson(
      const json::Object& object,
      ProjectTemplateWidgetDescription* pDescription)
{
   ProjectTemplateWidgetDescription description;

   core::Error error = core::json::readObject(
            object,
            "parameter", &description.parameter,
            "type",      &description.type,
            "label",     &description.label,
            "fields",    &description.fields);

   if (error)
      return error;

   *pDescription = description;
   return Success();
}

json::Value ProjectTemplateWidgetDescription::toJson() const
{
   core::json::Object object;

   object["parameter"] = parameter;
   object["type"]      = type;
   object["label"]     = label;
   object["fields"]    = core::json::toJsonArray(fields);

   return object;
}

Error fromJson(
      const json::Object& object,
      ProjectTemplateDescription* pDescription)
{
   Error error;
   ProjectTemplateDescription description;

   error = json::readObject(
            object,
            "package",  &description.package,
            "binding",  &description.binding,
            "title",    &description.title,
            "subtitle", &description.subtitle,
            "caption",  &description.caption,
            "icon",     &description.icon);

   if (error)
      return error;

   json::Array array;
   error = json::readObject(object, "widgets", &array);
   if (error)
      return error;

   BOOST_FOREACH(const json::Value& value, array)
   {
      if (!json::isType<json::Object>(value))
         return json::errors::typeMismatch(
                  value,
                  json::ObjectType,
                  ERROR_LOCATION);

      ProjectTemplateWidgetDescription widget;
      error = fromJson(value.get_obj(), &widget);
      if (error)
         return error;

      description.widgets.push_back(widget);
   }

   *pDescription = description;
   return Success();
}

json::Value ProjectTemplateDescription::toJson() const
{
   core::json::Object object;

   object["package"]  = package;
   object["binding"]  = binding;
   object["title"]    = title;
   object["subtitle"] = subtitle;
   object["caption"]  = caption;
   object["icon"]     = icon;

   core::json::Array widgetsJson;
   BOOST_FOREACH(const ProjectTemplateWidgetDescription& widgetDescription, widgets)
   {
      widgetsJson.push_back(widgetDescription.toJson());
   }
   object["widgets"] = widgetsJson;

   return object;
}

namespace {

Error parseFields(const std::string& fields, std::vector<std::string>* pFields)
{
   std::vector<std::string> parsedFields;
   text::parseCsvLine(
            fields.begin(),
            fields.end(),
            true,
            &parsedFields);

   if (parsedFields.empty())
      return systemError(boost::system::errc::protocol_error, ERROR_LOCATION);

   for (std::size_t i = 0, n = parsedFields.size(); i < n; ++i)
      parsedFields[i] = string_utils::trimWhitespace(parsedFields[i]);

   *pFields = parsedFields;
   return Success();
}

Error parseWidget(const std::string& widget, std::string* pWidgetType)
{
   std::string widgetLower = string_utils::toLower(widget);
   for (std::size_t i = 0, n = sizeof(kWidgetTypes); i < n; ++i)
   {
      const char* widgetType = kWidgetTypes[i];
      if (widgetLower == widgetType)
      {
         pWidgetType->assign(widgetType);
         return Success();
      }
   }

   return systemError(
            boost::system::errc::protocol_error,
            ERROR_LOCATION);
}

template <typename T>
core::Error populate(
      const core::FilePath& resourcePath,
      const T& map,
      ProjectTemplateDescription* pDescription)
{
   ProjectTemplateWidgetDescription widget;
   for (typename T::const_iterator it = map.begin();
        it != map.end();
        ++it)
   {
      const std::string& key   = it->first;
      const std::string& value = it->second;

      // populate primary keys
      if (key == "Binding")
         pDescription->binding = value;
      else if (key == "Title")
         pDescription->title = value;
      else if (key == "Subtitle")
         pDescription->subtitle = value;
      else if (key == "Caption")
         pDescription->caption = value;
      else if (key == "Icon")
      {
         // read icon file from disk
         core::FilePath iconPath = resourcePath.parent().complete(value);

         // encode file contents as base64
         std::string encoded;
         core::Error error = core::base64::encode(iconPath, &encoded);
         if (error)
            LOG_ERROR(error);

         // send up to client as base64-encoded blob
         pDescription->icon = encoded;
      }

      // populate widget
      else if (key == "Parameter")
         widget.parameter = value;
      else if (key == "Label")
         widget.label = value;
      else if (key == "Widget")
      {
         core::Error error = parseWidget(value, &widget.type);
         if (error)
            return error;
      }
      else if (key == "Fields")
      {
         core::Error error = parseFields(value, &widget.fields);
         if (error)
            return error;
      }
   }

   // if we discovered a widget here, add it to the description
   if (!widget.parameter.empty())
      pDescription->widgets.push_back(widget);

   return core::Success();
}

class ProjectTemplateRegistry : boost::noncopyable
{
public:

   void add(const std::string& pkgName, const ProjectTemplateDescription& description)
   {
      registry_[pkgName].push_back(description);
   }

   std::vector<ProjectTemplateDescription>& get(const std::string& pkgName)
   {
      return registry_[pkgName];
   }

   std::size_t size()
   {
      return registry_.size();
   }

   json::Value toJson()
   {
      json::Object object;

      BOOST_FOREACH(const std::string& pkgName, registry_ | boost::adaptors::map_keys)
      {
         json::Array array;
         BOOST_FOREACH(const ProjectTemplateDescription& description, registry_[pkgName])
         {
            array.push_back(description.toJson());
         }
         object[pkgName] = array;
      }

      return object;
   }

   std::map<
      std::string,
      std::vector<ProjectTemplateDescription>
   > registry_;
};

boost::shared_ptr<ProjectTemplateRegistry>& projectTemplateRegistry()
{
   static boost::shared_ptr<ProjectTemplateRegistry> instance =
         boost::make_shared<ProjectTemplateRegistry>();

   return instance;
}

class ProjectTemplateIndexer : public ppe::Indexer
{
public:

   explicit ProjectTemplateIndexer(const std::string& resourcePath)
      : ppe::Indexer(resourcePath)
   {
   }

   void addIndexingFinishedCallback(boost::function<void()> callback)
   {
      callbacks_.push_back(callback);
   }

   Error parseResourceFile(const std::string& pkgName,
                           const FilePath& resourcePath,
                           ProjectTemplateDescription* pDescription)
   {
      Error error;

      // read dcf contents
      std::string contents;
      error = core::readStringFromFile(resourcePath, &contents, string_utils::LineEndingPosix);
      if (error)
         return error;

      // attempt to parse as DCF -- multiple newlines used to separate records
      boost::regex reSeparator("\\n{2,}");
      boost::sregex_token_iterator it(contents.begin(), contents.end(), reSeparator, -1);
      boost::sregex_token_iterator end;

      for (; it != end; ++it) {
         // invoke parser on current record
         std::map<std::string, std::string> fields;
         std::string errorMessage;
         error = text::parseDcfFile(*it, true, &fields, &errorMessage);
         if (error)
            continue;

         // populate project template description based on fields
         error = populate(resourcePath, fields, pDescription);
         if (error)
            continue;
      }

      return error;
   }

private:
   void onIndexingStarted()
   {
      pRegistry_ = boost::make_shared<ProjectTemplateRegistry>();
   }

   void onWork(const std::string& pkgName, const core::FilePath& resourcePath)
   {
      Error error;

      // loop over discovered files and attempt to read template descriptions
      std::vector<FilePath> children;
      error = resourcePath.children(&children);
      if (error)
         LOG_ERROR(error);

      BOOST_FOREACH(const FilePath& childPath, children)
      {
         // skip files that don't have a dcf extension
         if (childPath.extension() != ".dcf")
            continue;

         ProjectTemplateDescription description;
         Error error = parseResourceFile(pkgName, childPath, &description);
         if (error)
         {
            LOG_ERROR(error);
            continue;
         }

         normalize(&description);

         pRegistry_->add(pkgName, description);
      }
   }

   void onIndexingCompleted()
   {
      // index a project template file in the RStudio options folder
      FilePath localTemplatesPath =
            module_context::resolveAliasedPath("~/.R/" kRStudioProjectTemplatesPath);

      if (localTemplatesPath.exists())
         onWork(kProjectTemplateLocal, localTemplatesPath);

      // update global registry
      projectTemplateRegistry() = pRegistry_;

      // add known project templates
      addKnownProjectTemplates();

      // execute any callbacks waiting for indexing to complete
      executeCallbacks();

      // notify client
      notifyClient();
   }

private:

   void addKnownProjectTemplates()
   {
      addProjectTemplate("devtools", "create", "R Package using devtools");
      addProjectTemplate("Rcpp", "Rcpp.package.skeleton", "R Package using Rcpp");
      addProjectTemplate("RcppArmadillo", "RcppArmadillo.package.skeleton", "R Package using RcppArmadillo");
      addProjectTemplate("RcppEigen", "RcppEigen.package.skeleton", "R Package using RcppEigen");
   }

   void addProjectTemplate(const std::string& package,
                           const std::string& binding,
                           const std::string& title)
   {
      // if we already have a project template registered for this
      // package with this binding, bail (this allows R packages to
      // override the default settings provided by RStudio if desired)
      std::vector<ProjectTemplateDescription>& templates =
            projectTemplateRegistry()->get(package);

      for (std::size_t i = 0, n = templates.size(); i < n; ++i)
         if (templates[i].binding == binding)
            return;

      // generate appropriate subtitle, caption from title
      std::string subtitle = "Create a new " + title;
      std::string caption  = "Create " + title;

      // add a new project template
      ProjectTemplateDescription ptd;
      ptd.package  = package;
      ptd.binding  = binding;
      ptd.title    = title;
      ptd.subtitle = subtitle;
      ptd.caption  = caption;
      projectTemplateRegistry()->add(package, ptd);
   }

   void normalize(ProjectTemplateDescription* pDescription)
   {
      std::string title = pDescription->title;

      if (pDescription->subtitle.empty())
         pDescription->subtitle = "Create a new " + title;

      if (pDescription->caption.empty())
         pDescription->caption = "Create " + title;
   }

   void executeCallbacks()
   {
      for (std::size_t i = 0, n = callbacks_.size(); i < n; ++i)
         callbacks_[i]();
      callbacks_.clear();
   }

   void notifyClient()
   {
      json::Value data = projectTemplateRegistry()->toJson();
      ClientEvent event(client_events::kProjectTemplateRegistryUpdated, data);
      module_context::enqueClientEvent(event);
   }

private:
   std::vector< boost::function<void()> > callbacks_;
   boost::shared_ptr<ProjectTemplateRegistry> pRegistry_;
};

ProjectTemplateIndexer& projectTemplateIndexer()
{
   static ProjectTemplateIndexer instance(kRStudioProjectTemplatesPath);
   return instance;
}

void reindex()
{
   projectTemplateIndexer().start();
}

void onDeferredInit(bool)
{
   if (module_context::disablePackages())
      return;

   projectTemplateIndexer().start();
}

void onConsoleInput(const std::string& input)
{
   if (module_context::disablePackages())
      return;

   const char* const commands[] = {
      "install.packages",
      "remove.packages",
      "devtools::install_github",
      "install_github",
      "devtools::load_all",
      "load_all"
   };

   std::string inputTrimmed = boost::algorithm::trim_copy(input);
   BOOST_FOREACH(const char* command, commands)
   {
      if (boost::algorithm::starts_with(inputTrimmed, command))
      {
         // we need to give R a chance to actually process the package library
         // mutating command before we update the index. schedule delayed work
         // with idleOnly = true so that it waits until the user has returned
         // to the R prompt
         module_context::scheduleDelayedWork(
                  boost::posix_time::seconds(1),
                  reindex,
                  true);
      }
   }
}

void respondWithProjectTemplateRegistry(const json::JsonRpcFunctionContinuation& continuation)
{
   json::JsonRpcResponse response;
   response.setResult(projectTemplateRegistry()->toJson());
   continuation(Success(), &response);
}

void withProjectTemplateRegistry(boost::function<void()> callback)
{
   if (projectTemplateIndexer().running())
      projectTemplateIndexer().addIndexingFinishedCallback(callback);
   else
      callback();
}

void getProjectTemplateRegistry(const json::JsonRpcRequest& request,
                                const json::JsonRpcFunctionContinuation& continuation)
{
   withProjectTemplateRegistry(
            boost::bind(respondWithProjectTemplateRegistry, boost::cref(continuation)));
}

} // end anonymous namespace

Error initialize()
{
   using namespace module_context;
   using boost::bind;

   events().onDeferredInit.connect(onDeferredInit);
   events().onConsoleInput.connect(onConsoleInput);

   ExecBlock initBlock;
   initBlock.addFunctions()
         (bind(sourceModuleRFile, "SessionProjectTemplate.R"))
         (bind(registerAsyncRpcMethod, "get_project_template_registry", getProjectTemplateRegistry));
   return initBlock.execute();
}

} // end namespace templates
} // end namespace projects
} // end namespace modules
} // end namespace session
} // end namespace rstudio
<commit_msg>index in 'rstudio/templates/project'<commit_after>/*
 * SessionProjectTemplate.cpp
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
#include <session/SessionProjectTemplate.hpp>

#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/function.hpp>
#include <boost/range/adaptors.hpp>

#include <core/Algorithm.hpp>
#include <core/Error.hpp>
#include <core/Exec.hpp>
#include <core/FilePath.hpp>
#include <core/FileSerializer.hpp>
#include <core/text/DcfParser.hpp>

#include <session/SessionModuleContext.hpp>

#include <session/SessionPackageProvidedExtension.hpp>

#define kProjectTemplateLocal "(local)"
#define kRStudioProjectTemplatesPath "rstudio/templates/projects"

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace projects {
namespace templates {

Error fromJson(
      const json::Object& object,
      ProjectTemplateWidgetDescription* pDescription)
{
   ProjectTemplateWidgetDescription description;

   core::Error error = core::json::readObject(
            object,
            "parameter", &description.parameter,
            "type",      &description.type,
            "label",     &description.label,
            "fields",    &description.fields);

   if (error)
      return error;

   *pDescription = description;
   return Success();
}

json::Value ProjectTemplateWidgetDescription::toJson() const
{
   core::json::Object object;

   object["parameter"] = parameter;
   object["type"]      = type;
   object["label"]     = label;
   object["fields"]    = core::json::toJsonArray(fields);

   return object;
}

Error fromJson(
      const json::Object& object,
      ProjectTemplateDescription* pDescription)
{
   Error error;
   ProjectTemplateDescription description;

   error = json::readObject(
            object,
            "package",  &description.package,
            "binding",  &description.binding,
            "title",    &description.title,
            "subtitle", &description.subtitle,
            "caption",  &description.caption,
            "icon",     &description.icon);

   if (error)
      return error;

   json::Array array;
   error = json::readObject(object, "widgets", &array);
   if (error)
      return error;

   BOOST_FOREACH(const json::Value& value, array)
   {
      if (!json::isType<json::Object>(value))
         return json::errors::typeMismatch(
                  value,
                  json::ObjectType,
                  ERROR_LOCATION);

      ProjectTemplateWidgetDescription widget;
      error = fromJson(value.get_obj(), &widget);
      if (error)
         return error;

      description.widgets.push_back(widget);
   }

   *pDescription = description;
   return Success();
}

json::Value ProjectTemplateDescription::toJson() const
{
   core::json::Object object;

   object["package"]  = package;
   object["binding"]  = binding;
   object["title"]    = title;
   object["subtitle"] = subtitle;
   object["caption"]  = caption;
   object["icon"]     = icon;

   core::json::Array widgetsJson;
   BOOST_FOREACH(const ProjectTemplateWidgetDescription& widgetDescription, widgets)
   {
      widgetsJson.push_back(widgetDescription.toJson());
   }
   object["widgets"] = widgetsJson;

   return object;
}

namespace {

Error parseFields(const std::string& fields, std::vector<std::string>* pFields)
{
   std::vector<std::string> parsedFields;
   text::parseCsvLine(
            fields.begin(),
            fields.end(),
            true,
            &parsedFields);

   if (parsedFields.empty())
      return systemError(boost::system::errc::protocol_error, ERROR_LOCATION);

   for (std::size_t i = 0, n = parsedFields.size(); i < n; ++i)
      parsedFields[i] = string_utils::trimWhitespace(parsedFields[i]);

   *pFields = parsedFields;
   return Success();
}

Error parseWidget(const std::string& widget, std::string* pWidgetType)
{
   std::string widgetLower = string_utils::toLower(widget);
   for (std::size_t i = 0, n = sizeof(kWidgetTypes); i < n; ++i)
   {
      const char* widgetType = kWidgetTypes[i];
      if (widgetLower == widgetType)
      {
         pWidgetType->assign(widgetType);
         return Success();
      }
   }

   return systemError(
            boost::system::errc::protocol_error,
            ERROR_LOCATION);
}

template <typename T>
core::Error populate(
      const core::FilePath& resourcePath,
      const T& map,
      ProjectTemplateDescription* pDescription)
{
   ProjectTemplateWidgetDescription widget;
   for (typename T::const_iterator it = map.begin();
        it != map.end();
        ++it)
   {
      const std::string& key   = it->first;
      const std::string& value = it->second;

      // populate primary keys
      if (key == "Binding")
         pDescription->binding = value;
      else if (key == "Title")
         pDescription->title = value;
      else if (key == "Subtitle")
         pDescription->subtitle = value;
      else if (key == "Caption")
         pDescription->caption = value;
      else if (key == "Icon")
      {
         // read icon file from disk
         core::FilePath iconPath = resourcePath.parent().complete(value);

         // encode file contents as base64
         std::string encoded;
         core::Error error = core::base64::encode(iconPath, &encoded);
         if (error)
            LOG_ERROR(error);

         // send up to client as base64-encoded blob
         pDescription->icon = encoded;
      }

      // populate widget
      else if (key == "Parameter")
         widget.parameter = value;
      else if (key == "Label")
         widget.label = value;
      else if (key == "Widget")
      {
         core::Error error = parseWidget(value, &widget.type);
         if (error)
            return error;
      }
      else if (key == "Fields")
      {
         core::Error error = parseFields(value, &widget.fields);
         if (error)
            return error;
      }
   }

   // if we discovered a widget here, add it to the description
   if (!widget.parameter.empty())
      pDescription->widgets.push_back(widget);

   return core::Success();
}

class ProjectTemplateRegistry : boost::noncopyable
{
public:

   void add(const std::string& pkgName, const ProjectTemplateDescription& description)
   {
      registry_[pkgName].push_back(description);
   }

   std::vector<ProjectTemplateDescription>& get(const std::string& pkgName)
   {
      return registry_[pkgName];
   }

   std::size_t size()
   {
      return registry_.size();
   }

   json::Value toJson()
   {
      json::Object object;

      BOOST_FOREACH(const std::string& pkgName, registry_ | boost::adaptors::map_keys)
      {
         json::Array array;
         BOOST_FOREACH(const ProjectTemplateDescription& description, registry_[pkgName])
         {
            array.push_back(description.toJson());
         }
         object[pkgName] = array;
      }

      return object;
   }

   std::map<
      std::string,
      std::vector<ProjectTemplateDescription>
   > registry_;
};

boost::shared_ptr<ProjectTemplateRegistry>& projectTemplateRegistry()
{
   static boost::shared_ptr<ProjectTemplateRegistry> instance =
         boost::make_shared<ProjectTemplateRegistry>();

   return instance;
}

class ProjectTemplateIndexer : public ppe::Indexer
{
public:

   explicit ProjectTemplateIndexer(const std::string& resourcePath)
      : ppe::Indexer(resourcePath)
   {
   }

   void addIndexingFinishedCallback(boost::function<void()> callback)
   {
      callbacks_.push_back(callback);
   }

   Error parseResourceFile(const std::string& pkgName,
                           const FilePath& resourcePath,
                           ProjectTemplateDescription* pDescription)
   {
      Error error;

      // read dcf contents
      std::string contents;
      error = core::readStringFromFile(resourcePath, &contents, string_utils::LineEndingPosix);
      if (error)
         return error;

      // attempt to parse as DCF -- multiple newlines used to separate records
      boost::regex reSeparator("\\n{2,}");
      boost::sregex_token_iterator it(contents.begin(), contents.end(), reSeparator, -1);
      boost::sregex_token_iterator end;

      for (; it != end; ++it) {
         // invoke parser on current record
         std::map<std::string, std::string> fields;
         std::string errorMessage;
         error = text::parseDcfFile(*it, true, &fields, &errorMessage);
         if (error)
            continue;

         // populate project template description based on fields
         error = populate(resourcePath, fields, pDescription);
         if (error)
            continue;
      }

      return error;
   }

private:
   void onIndexingStarted()
   {
      pRegistry_ = boost::make_shared<ProjectTemplateRegistry>();
   }

   void onWork(const std::string& pkgName, const core::FilePath& resourcePath)
   {
      Error error;

      // loop over discovered files and attempt to read template descriptions
      std::vector<FilePath> children;
      error = resourcePath.children(&children);
      if (error)
         LOG_ERROR(error);

      BOOST_FOREACH(const FilePath& childPath, children)
      {
         // skip files that don't have a dcf extension
         if (childPath.extension() != ".dcf")
            continue;

         ProjectTemplateDescription description;
         Error error = parseResourceFile(pkgName, childPath, &description);
         if (error)
         {
            LOG_ERROR(error);
            continue;
         }

         normalize(&description);

         pRegistry_->add(pkgName, description);
      }
   }

   void onIndexingCompleted()
   {
      // index a project template file in the RStudio options folder
      FilePath localTemplatesPath =
            module_context::resolveAliasedPath("~/.R/" kRStudioProjectTemplatesPath);

      if (localTemplatesPath.exists())
         onWork(kProjectTemplateLocal, localTemplatesPath);

      // update global registry
      projectTemplateRegistry() = pRegistry_;

      // add known project templates
      addKnownProjectTemplates();

      // execute any callbacks waiting for indexing to complete
      executeCallbacks();

      // notify client
      notifyClient();
   }

private:

   void addKnownProjectTemplates()
   {
      addProjectTemplate("devtools", "create", "R Package using devtools");
      addProjectTemplate("Rcpp", "Rcpp.package.skeleton", "R Package using Rcpp");
      addProjectTemplate("RcppArmadillo", "RcppArmadillo.package.skeleton", "R Package using RcppArmadillo");
      addProjectTemplate("RcppEigen", "RcppEigen.package.skeleton", "R Package using RcppEigen");
   }

   void addProjectTemplate(const std::string& package,
                           const std::string& binding,
                           const std::string& title)
   {
      // if we already have a project template registered for this
      // package with this binding, bail (this allows R packages to
      // override the default settings provided by RStudio if desired)
      std::vector<ProjectTemplateDescription>& templates =
            projectTemplateRegistry()->get(package);

      for (std::size_t i = 0, n = templates.size(); i < n; ++i)
         if (templates[i].binding == binding)
            return;

      // generate appropriate subtitle, caption from title
      std::string subtitle = "Create a new " + title;
      std::string caption  = "Create " + title;

      // add a new project template
      ProjectTemplateDescription ptd;
      ptd.package  = package;
      ptd.binding  = binding;
      ptd.title    = title;
      ptd.subtitle = subtitle;
      ptd.caption  = caption;
      projectTemplateRegistry()->add(package, ptd);
   }

   void normalize(ProjectTemplateDescription* pDescription)
   {
      std::string title = pDescription->title;

      if (pDescription->subtitle.empty())
         pDescription->subtitle = "Create a new " + title;

      if (pDescription->caption.empty())
         pDescription->caption = "Create " + title;
   }

   void executeCallbacks()
   {
      for (std::size_t i = 0, n = callbacks_.size(); i < n; ++i)
         callbacks_[i]();
      callbacks_.clear();
   }

   void notifyClient()
   {
      json::Value data = projectTemplateRegistry()->toJson();
      ClientEvent event(client_events::kProjectTemplateRegistryUpdated, data);
      module_context::enqueClientEvent(event);
   }

private:
   std::vector< boost::function<void()> > callbacks_;
   boost::shared_ptr<ProjectTemplateRegistry> pRegistry_;
};

ProjectTemplateIndexer& projectTemplateIndexer()
{
   static ProjectTemplateIndexer instance(kRStudioProjectTemplatesPath);
   return instance;
}

void reindex()
{
   projectTemplateIndexer().start();
}

void onDeferredInit(bool)
{
   if (module_context::disablePackages())
      return;

   projectTemplateIndexer().start();
}

void onConsoleInput(const std::string& input)
{
   if (module_context::disablePackages())
      return;

   const char* const commands[] = {
      "install.packages",
      "remove.packages",
      "devtools::install_github",
      "install_github",
      "devtools::load_all",
      "load_all"
   };

   std::string inputTrimmed = boost::algorithm::trim_copy(input);
   BOOST_FOREACH(const char* command, commands)
   {
      if (boost::algorithm::starts_with(inputTrimmed, command))
      {
         // we need to give R a chance to actually process the package library
         // mutating command before we update the index. schedule delayed work
         // with idleOnly = true so that it waits until the user has returned
         // to the R prompt
         module_context::scheduleDelayedWork(
                  boost::posix_time::seconds(1),
                  reindex,
                  true);
      }
   }
}

void respondWithProjectTemplateRegistry(const json::JsonRpcFunctionContinuation& continuation)
{
   json::JsonRpcResponse response;
   response.setResult(projectTemplateRegistry()->toJson());
   continuation(Success(), &response);
}

void withProjectTemplateRegistry(boost::function<void()> callback)
{
   if (projectTemplateIndexer().running())
      projectTemplateIndexer().addIndexingFinishedCallback(callback);
   else
      callback();
}

void getProjectTemplateRegistry(const json::JsonRpcRequest& request,
                                const json::JsonRpcFunctionContinuation& continuation)
{
   withProjectTemplateRegistry(
            boost::bind(respondWithProjectTemplateRegistry, boost::cref(continuation)));
}

} // end anonymous namespace

Error initialize()
{
   using namespace module_context;
   using boost::bind;

   events().onDeferredInit.connect(onDeferredInit);
   events().onConsoleInput.connect(onConsoleInput);

   ExecBlock initBlock;
   initBlock.addFunctions()
         (bind(sourceModuleRFile, "SessionProjectTemplate.R"))
         (bind(registerAsyncRpcMethod, "get_project_template_registry", getProjectTemplateRegistry));
   return initBlock.execute();
}

} // end namespace templates
} // end namespace projects
} // end namespace modules
} // end namespace session
} // end namespace rstudio
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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. */

#include "paddle/framework/operator.h"
#include "gtest/gtest.h"
#include "paddle/framework/op_registry.h"

namespace paddle {
namespace framework {

static int op_run_num = 0;

class OpWithoutKernelTest : public OperatorBase {
  DEFINE_OPERATOR_CTOR(OpWithoutKernelTest, framework::OperatorBase)

 public:
  void Init() override { x = 1; }
  void InferShape(const Scope& scope) const override {}
  void Run(const Scope& scope,
           const platform::DeviceContext& dev_ctx) const override {
    ++op_run_num;
    ASSERT_EQ(static_cast<int>(inputs_.size()), 1);
    ASSERT_EQ(static_cast<int>(outputs_.size()), 1);
    ASSERT_EQ(scope.FindVar(inputs_.at("input")[0]), nullptr);
    ASSERT_EQ(x, 1);
    ASSERT_NE(scope.FindVar(outputs_.at("output")[0]), nullptr);
  }

 public:
  float x = 0;
};

class OpeWithoutKernelTestProtoAndCheckerMaker : public OpProtoAndCheckerMaker {
 public:
  OpeWithoutKernelTestProtoAndCheckerMaker(OpProto* proto,
                                           OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("input", "input of test op");
    AddOutput("output", "output of test op");
    AddAttr<float>("scale", "scale of cosine op");
    AddComment("This is test op");
  }
};

}  // namespace framework
}  // namespace paddle

static void BuildVar(const std::string& param_name,
                     std::initializer_list<const char*> arguments,
                     paddle::framework::OpDesc::Var* var) {
  var->set_parameter(param_name);
  for (auto& arg_name : arguments) {
    *var->mutable_arguments()->Add() = arg_name;
  }
}

REGISTER_OP(test_operator, paddle::framework::OpWithoutKernelTest,
            paddle::framework::OpeWithoutKernelTestProtoAndCheckerMaker);

TEST(OperatorBase, all) {
  paddle::framework::OpDesc op_desc;
  op_desc.set_type("test_operator");
  BuildVar("input", {"IN1"}, op_desc.add_inputs());
  BuildVar("output", {"OUT1"}, op_desc.add_outputs());

  auto attr = op_desc.mutable_attrs()->Add();
  attr->set_name("scale");
  attr->set_type(paddle::framework::AttrType::FLOAT);
  attr->set_f(3.14);

  paddle::platform::CPUDeviceContext device_context;
  paddle::framework::Scope scope;

  auto op = paddle::framework::OpRegistry::CreateOp(op_desc);
  scope.NewVar("OUT1");
  ASSERT_EQ(paddle::framework::op_run_num, 0);
  op->InferShape(scope);
  op->Run(scope, device_context);
  ASSERT_EQ(paddle::framework::op_run_num, 1);
}

namespace paddle {
namespace framework {

class OpKernelTestProtoAndCheckerMaker : public OpProtoAndCheckerMaker {
 public:
  OpKernelTestProtoAndCheckerMaker(OpProto* proto, OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("x", "input of test op");
    AddOutput("y", "output of test op");
    AddAttr<float>("scale", "scale of cosine op")
        .SetDefault(1.0)
        .LargerThan(0.0);
    AddComment("This is test op");
  }
};

static int cpu_kernel_run_num = 0;

class OpWithKernelTest : public OperatorWithKernel {
  DEFINE_OPERATOR_CTOR(OpWithKernelTest, framework::OperatorWithKernel)
 protected:
  void InferShape(const framework::InferShapeContext& ctx) const override {}
};

template <typename T1, typename T2>
class CPUKernelTest : public OpKernel {
 public:
  void Compute(const ExecutionContext& ctx) const {
    std::cout << "this is cpu kernel" << std::endl;
    std::cout << ctx.op_.DebugString() << std::endl;
    cpu_kernel_run_num++;
    ASSERT_EQ(ctx.op_.Input("x"), "IN1");
    ASSERT_EQ(ctx.op_.Output("y"), "OUT1");
  }
};

class OpKernelTestMultiInputsProtoAndCheckerMaker
    : public OpProtoAndCheckerMaker {
 public:
  OpKernelTestMultiInputsProtoAndCheckerMaker(OpProto* proto,
                                              OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("xs", "inputs of test op").AsDuplicable();
    AddInput("k", "input of test op");
    AddOutput("ys", "outputs of test op").AsDuplicable();
    AddAttr<float>("scale", "scale of cosine op")
        .SetDefault(1.0)
        .LargerThan(0.0);
    AddComment("This is test op");
  }
};

class CPUKernalMultiInputsTest : public OpKernel {
 public:
  void Compute(const ExecutionContext& ctx) const {
    auto xs = ctx.op_.Inputs("xs");
    ASSERT_EQ(xs.size(), 3UL);
    ASSERT_EQ(xs[0], "x0");
    ASSERT_EQ(xs[1], "x1");
    ASSERT_EQ(xs[2], "x2");

    auto inVar0 = ctx.MultiInputVar("xs");
    ASSERT_EQ(inVar0.size(), 3U);

    auto intVar1 = ctx.InputVar("k");
    ASSERT_NE(intVar1, nullptr);

    auto outVar0 = ctx.MultiOutputVar("ys");
    ASSERT_EQ(outVar0.size(), 2U);

    auto inTensor0 = ctx.MultiInput<Tensor>("xs");
    ASSERT_EQ(inTensor0.size(), 3U);

    auto intTensor1 = ctx.Input<Tensor>("k");
    ASSERT_NE(intTensor1, nullptr);

    auto outTensor0 = ctx.MultiOutput<Tensor>("ys");
    ASSERT_EQ(outTensor0.size(), 2U);

    auto k = ctx.op_.Input("k");
    ASSERT_EQ(k, "k0");

    auto ys = ctx.op_.Outputs("ys");
    ASSERT_EQ(ys.size(), 2UL);
    ASSERT_EQ(ys[0], "y0");
    ASSERT_EQ(ys[1], "y1");
  }
};

}  // namespace framework
}  // namespace paddle

REGISTER_OP(op_with_kernel, paddle::framework::OpWithKernelTest,
            paddle::framework::OpKernelTestProtoAndCheckerMaker);
REGISTER_OP_CPU_KERNEL(op_with_kernel,
                       paddle::framework::CPUKernelTest<float, float>);

// test with single input
TEST(OpKernel, all) {
  paddle::framework::OpDesc op_desc;
  op_desc.set_type("op_with_kernel");
  BuildVar("IN1", {"x"}, op_desc.add_inputs());
  BuildVar("OUT1", {"y"}, op_desc.add_outputs());

  auto attr = op_desc.mutable_attrs()->Add();
  attr->set_name("scale");
  attr->set_type(paddle::framework::AttrType::FLOAT);
  attr->set_f(3.14);

  paddle::platform::CPUDeviceContext cpu_device_context;
  paddle::framework::Scope scope;

  auto op = paddle::framework::OpRegistry::CreateOp(op_desc);
  ASSERT_EQ(paddle::framework::cpu_kernel_run_num, 0);
  op->Run(scope, cpu_device_context);
  ASSERT_EQ(paddle::framework::cpu_kernel_run_num, 1);
}

REGISTER_OP(op_multi_inputs_with_kernel, paddle::framework::OpWithKernelTest,
            paddle::framework::OpKernelTestMultiInputsProtoAndCheckerMaker);
REGISTER_OP_CPU_KERNEL(op_multi_inputs_with_kernel,
                       paddle::framework::CPUKernalMultiInputsTest);

// test with multi inputs
TEST(OpKernel, multi_inputs) {
  using namespace paddle::framework;

  OpDesc op_desc;
  op_desc.set_type("op_multi_inputs_with_kernel");
  BuildVar("xs", {"x0", "x1", "x2"}, op_desc.add_inputs());
  BuildVar("k", {"k0"}, op_desc.add_inputs());
  BuildVar("ys", {"y0", "y1"}, op_desc.add_outputs());

  auto attr = op_desc.mutable_attrs()->Add();
  attr->set_name("scale");
  attr->set_type(paddle::framework::AttrType::FLOAT);
  attr->set_f(3.14);

  paddle::platform::CPUDeviceContext cpu_device_context;
  paddle::framework::Scope scope;
  scope.NewVar("x0")->GetMutable<Tensor>();
  scope.NewVar("x1")->GetMutable<Tensor>();
  scope.NewVar("x2")->GetMutable<Tensor>();
  scope.NewVar("k0")->GetMutable<Tensor>();
  scope.NewVar("y0")->GetMutable<Tensor>();
  scope.NewVar("y1")->GetMutable<Tensor>();

  auto op = paddle::framework::OpRegistry::CreateOp(op_desc);
  op->Run(scope, cpu_device_context);
}
<commit_msg>Fix CI<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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. */

#include "paddle/framework/operator.h"
#include "gtest/gtest.h"
#include "paddle/framework/op_registry.h"

namespace paddle {
namespace framework {

static int op_run_num = 0;

class OpWithoutKernelTest : public OperatorBase {
  DEFINE_OPERATOR_CTOR(OpWithoutKernelTest, framework::OperatorBase)

 public:
  void Init() override { x = 1; }
  void InferShape(const Scope& scope) const override {}
  void Run(const Scope& scope,
           const platform::DeviceContext& dev_ctx) const override {
    ++op_run_num;
    ASSERT_EQ(static_cast<int>(inputs_.size()), 1);
    ASSERT_EQ(static_cast<int>(outputs_.size()), 1);
    ASSERT_EQ(scope.FindVar(inputs_.at("input")[0]), nullptr);
    ASSERT_EQ(x, 1);
    ASSERT_NE(scope.FindVar(outputs_.at("output")[0]), nullptr);
  }

 public:
  float x = 0;
};

class OpeWithoutKernelTestProtoAndCheckerMaker : public OpProtoAndCheckerMaker {
 public:
  OpeWithoutKernelTestProtoAndCheckerMaker(OpProto* proto,
                                           OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("input", "input of test op");
    AddOutput("output", "output of test op");
    AddAttr<float>("scale", "scale of cosine op");
    AddComment("This is test op");
  }
};

}  // namespace framework
}  // namespace paddle

static void BuildVar(const std::string& param_name,
                     std::initializer_list<const char*> arguments,
                     paddle::framework::OpDesc::Var* var) {
  var->set_parameter(param_name);
  for (auto& arg_name : arguments) {
    *var->mutable_arguments()->Add() = arg_name;
  }
}

REGISTER_OP(test_operator, paddle::framework::OpWithoutKernelTest,
            paddle::framework::OpeWithoutKernelTestProtoAndCheckerMaker);

TEST(OperatorBase, all) {
  paddle::framework::OpDesc op_desc;
  op_desc.set_type("test_operator");
  BuildVar("input", {"IN1"}, op_desc.add_inputs());
  BuildVar("output", {"OUT1"}, op_desc.add_outputs());

  auto attr = op_desc.mutable_attrs()->Add();
  attr->set_name("scale");
  attr->set_type(paddle::framework::AttrType::FLOAT);
  attr->set_f(3.14);

  paddle::platform::CPUDeviceContext device_context;
  paddle::framework::Scope scope;

  auto op = paddle::framework::OpRegistry::CreateOp(op_desc);
  scope.NewVar("OUT1");
  ASSERT_EQ(paddle::framework::op_run_num, 0);
  op->InferShape(scope);
  op->Run(scope, device_context);
  ASSERT_EQ(paddle::framework::op_run_num, 1);
}

namespace paddle {
namespace framework {

class OpKernelTestProtoAndCheckerMaker : public OpProtoAndCheckerMaker {
 public:
  OpKernelTestProtoAndCheckerMaker(OpProto* proto, OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("x", "input of test op");
    AddOutput("y", "output of test op");
    AddAttr<float>("scale", "scale of cosine op")
        .SetDefault(1.0)
        .LargerThan(0.0);
    AddComment("This is test op");
  }
};

static int cpu_kernel_run_num = 0;

class OpWithKernelTest : public OperatorWithKernel {
  DEFINE_OPERATOR_CTOR(OpWithKernelTest, framework::OperatorWithKernel)
 protected:
  void InferShape(const framework::InferShapeContext& ctx) const override {}
};

template <typename T1, typename T2>
class CPUKernelTest : public OpKernel {
 public:
  void Compute(const ExecutionContext& ctx) const {
    std::cout << "this is cpu kernel" << std::endl;
    std::cout << ctx.op_.DebugString() << std::endl;
    cpu_kernel_run_num++;
    ASSERT_EQ(ctx.op_.Input("x"), "IN1");
    ASSERT_EQ(ctx.op_.Output("y"), "OUT1");
  }
};

class OpKernelTestMultiInputsProtoAndCheckerMaker
    : public OpProtoAndCheckerMaker {
 public:
  OpKernelTestMultiInputsProtoAndCheckerMaker(OpProto* proto,
                                              OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("xs", "inputs of test op").AsDuplicable();
    AddInput("k", "input of test op");
    AddOutput("ys", "outputs of test op").AsDuplicable();
    AddAttr<float>("scale", "scale of cosine op")
        .SetDefault(1.0)
        .LargerThan(0.0);
    AddComment("This is test op");
  }
};

class CPUKernalMultiInputsTest : public OpKernel {
 public:
  void Compute(const ExecutionContext& ctx) const {
    auto xs = ctx.op_.Inputs("xs");
    ASSERT_EQ(xs.size(), 3UL);
    ASSERT_EQ(xs[0], "x0");
    ASSERT_EQ(xs[1], "x1");
    ASSERT_EQ(xs[2], "x2");

    auto inVar0 = ctx.MultiInputVar("xs");
    ASSERT_EQ(inVar0.size(), 3U);

    auto intVar1 = ctx.InputVar("k");
    ASSERT_NE(intVar1, nullptr);

    auto outVar0 = ctx.MultiOutputVar("ys");
    ASSERT_EQ(outVar0.size(), 2U);

    auto inTensor0 = ctx.MultiInput<Tensor>("xs");
    ASSERT_EQ(inTensor0.size(), 3U);

    auto intTensor1 = ctx.Input<Tensor>("k");
    ASSERT_NE(intTensor1, nullptr);

    auto outTensor0 = ctx.MultiOutput<Tensor>("ys");
    ASSERT_EQ(outTensor0.size(), 2U);

    auto k = ctx.op_.Input("k");
    ASSERT_EQ(k, "k0");

    auto ys = ctx.op_.Outputs("ys");
    ASSERT_EQ(ys.size(), 2UL);
    ASSERT_EQ(ys[0], "y0");
    ASSERT_EQ(ys[1], "y1");
  }
};

}  // namespace framework
}  // namespace paddle

REGISTER_OP(op_with_kernel, paddle::framework::OpWithKernelTest,
            paddle::framework::OpKernelTestProtoAndCheckerMaker);
REGISTER_OP_CPU_KERNEL(op_with_kernel,
                       paddle::framework::CPUKernelTest<float, float>);

// test with single input
TEST(OpKernel, all) {
  paddle::framework::OpDesc op_desc;
  op_desc.set_type("op_with_kernel");
  BuildVar("x", {"IN1"}, op_desc.add_inputs());
  BuildVar("y", {"OUT1"}, op_desc.add_outputs());

  auto attr = op_desc.mutable_attrs()->Add();
  attr->set_name("scale");
  attr->set_type(paddle::framework::AttrType::FLOAT);
  attr->set_f(3.14);

  paddle::platform::CPUDeviceContext cpu_device_context;
  paddle::framework::Scope scope;

  auto op = paddle::framework::OpRegistry::CreateOp(op_desc);
  ASSERT_EQ(paddle::framework::cpu_kernel_run_num, 0);
  op->Run(scope, cpu_device_context);
  ASSERT_EQ(paddle::framework::cpu_kernel_run_num, 1);
}

REGISTER_OP(op_multi_inputs_with_kernel, paddle::framework::OpWithKernelTest,
            paddle::framework::OpKernelTestMultiInputsProtoAndCheckerMaker);
REGISTER_OP_CPU_KERNEL(op_multi_inputs_with_kernel,
                       paddle::framework::CPUKernalMultiInputsTest);

// test with multi inputs
TEST(OpKernel, multi_inputs) {
  using namespace paddle::framework;

  OpDesc op_desc;
  op_desc.set_type("op_multi_inputs_with_kernel");
  BuildVar("xs", {"x0", "x1", "x2"}, op_desc.add_inputs());
  BuildVar("k", {"k0"}, op_desc.add_inputs());
  BuildVar("ys", {"y0", "y1"}, op_desc.add_outputs());

  auto attr = op_desc.mutable_attrs()->Add();
  attr->set_name("scale");
  attr->set_type(paddle::framework::AttrType::FLOAT);
  attr->set_f(3.14);

  paddle::platform::CPUDeviceContext cpu_device_context;
  paddle::framework::Scope scope;
  scope.NewVar("x0")->GetMutable<Tensor>();
  scope.NewVar("x1")->GetMutable<Tensor>();
  scope.NewVar("x2")->GetMutable<Tensor>();
  scope.NewVar("k0")->GetMutable<Tensor>();
  scope.NewVar("y0")->GetMutable<Tensor>();
  scope.NewVar("y1")->GetMutable<Tensor>();

  auto op = paddle::framework::OpRegistry::CreateOp(op_desc);
  op->Run(scope, cpu_device_context);
}
<|endoftext|>


<commit_before>// Filename: pfmBba.cxx
// Created by:  drose (02Mar11)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#include "pfmBba.h"
#include "config_pfm.h"
#include "pfmFile.h"
#include "pystub.h"

////////////////////////////////////////////////////////////////////
//     Function: PfmBba::Constructor
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
PfmBba::
PfmBba() {
  set_program_description
    ("pfm-bba generates a .bba file from a .pfm file that lists the "
     "planar bounding volume of the pfm's internal data.");

  add_option
    ("z", "", 0,
     "Treats (0,0,0) in the pfm file as a special don't-touch value.",
     &PfmBba::dispatch_none, &_got_zero_special);

  add_option
    ("o", "filename", 50,
     "Specify the filename to which the resulting bba file will be written.",
     &PfmBba::dispatch_filename, &_got_output_filename, &_output_filename);
}

////////////////////////////////////////////////////////////////////
//     Function: PfmBba::run
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void PfmBba::
run() {
  Filenames::const_iterator fi;
  for (fi = _input_filenames.begin(); fi != _input_filenames.end(); ++fi) {
    PfmFile file;
    if (!file.read(*fi)) {
      nout << "Cannot read " << *fi << "\n";
      exit(1);
    }
    if (!process_pfm(*fi, file)) {
      exit(1);
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: PfmBba::process_pfm
//       Access: Public
//  Description: Handles a single pfm file.
////////////////////////////////////////////////////////////////////
bool PfmBba::
process_pfm(const Filename &input_filename, PfmFile &file) {
  file.set_zero_special(_got_zero_special);

  Filename bba_filename;
  if (_got_output_filename) {
    bba_filename = _output_filename;
  } else {
    bba_filename = input_filename;
    bba_filename.set_extension("bba");
  }

  if (!bba_filename.empty()) {
    bba_filename.set_text();
    PT(BoundingHexahedron) bounds = file.compute_planar_bounds(pfm_bba_dist[0], pfm_bba_dist[1]);
    nassertr(bounds != (BoundingHexahedron *)NULL, false);

    pofstream out;
    if (!bba_filename.open_write(out)) {
      pfm_cat.error()
        << "Unable to open " << bba_filename << "\n";
      return false;
    }

    LPoint3 points[8];
    for (int i = 0; i < 8; ++i) {
      points[i] = bounds->get_point(i);
    }
    LPlanef plane(points[0], points[1], points[2]);
    LVector3 normal = plane.get_normal();

    static const PN_stdfloat scale = 20.0f;
    normal *= scale;
    points[0] += normal;
    points[1] += normal;
    points[2] += normal;
    points[3] += normal;

    for (int i = 0; i < 8; ++i) {
      const LPoint3 &p = points[i];
      out << p[0] << "," << p[1] << "," << p[2] << "\n";
    }
  }

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: PfmBba::handle_args
//       Access: Protected, Virtual
//  Description: Does something with the additional arguments on the
//               command line (after all the -options have been
//               parsed).  Returns true if the arguments are good,
//               false otherwise.
////////////////////////////////////////////////////////////////////
bool PfmBba::
handle_args(ProgramBase::Args &args) {
  if (args.empty()) {
    nout << "You must specify the pfm file(s) to read on the command line.\n";
    return false;
  }

  if (args.size() > 1 && _got_output_filename) {
    nout << "Cannot use -o when multiple pfm files are specified.\n";
    return false;
  }

  Args::const_iterator ai;
  for (ai = args.begin(); ai != args.end(); ++ai) {
    _input_filenames.push_back(Filename::from_os_specific(*ai));
  }

  return true;
}

int main(int argc, char *argv[]) {
  // A call to pystub() to force libpystub.so to be linked in.
  pystub();

  PfmBba prog;
  prog.parse_command_line(argc, argv);
  prog.run();
  return 0;
}
<commit_msg>small typo<commit_after>// Filename: pfmBba.cxx
// Created by:  drose (02Mar11)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#include "pfmBba.h"
#include "config_pfm.h"
#include "pfmFile.h"
#include "pystub.h"

////////////////////////////////////////////////////////////////////
//     Function: PfmBba::Constructor
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
PfmBba::
PfmBba() {
  set_program_description
    ("pfm-bba generates a .bba file from a .pfm file that lists the "
     "planar bounding volume of the pfm's internal data.");

  add_option
    ("z", "", 0,
     "Treats (0,0,0) in the pfm file as a special don't-touch value.",
     &PfmBba::dispatch_none, &_got_zero_special);

  add_option
    ("o", "filename", 50,
     "Specify the filename to which the resulting bba file will be written.",
     &PfmBba::dispatch_filename, &_got_output_filename, &_output_filename);
}

////////////////////////////////////////////////////////////////////
//     Function: PfmBba::run
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void PfmBba::
run() {
  Filenames::const_iterator fi;
  for (fi = _input_filenames.begin(); fi != _input_filenames.end(); ++fi) {
    PfmFile file;
    if (!file.read(*fi)) {
      nout << "Cannot read " << *fi << "\n";
      exit(1);
    }
    if (!process_pfm(*fi, file)) {
      exit(1);
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: PfmBba::process_pfm
//       Access: Public
//  Description: Handles a single pfm file.
////////////////////////////////////////////////////////////////////
bool PfmBba::
process_pfm(const Filename &input_filename, PfmFile &file) {
  file.set_zero_special(_got_zero_special);

  Filename bba_filename;
  if (_got_output_filename) {
    bba_filename = _output_filename;
  } else {
    bba_filename = input_filename;
    bba_filename.set_extension("bba");
  }

  if (!bba_filename.empty()) {
    bba_filename.set_text();
    PT(BoundingHexahedron) bounds = file.compute_planar_bounds(pfm_bba_dist[0], pfm_bba_dist[1]);
    nassertr(bounds != (BoundingHexahedron *)NULL, false);

    pofstream out;
    if (!bba_filename.open_write(out)) {
      pfm_cat.error()
        << "Unable to open " << bba_filename << "\n";
      return false;
    }

    LPoint3 points[8];
    for (int i = 0; i < 8; ++i) {
      points[i] = bounds->get_point(i);
    }
    LPlane plane(points[0], points[1], points[2]);
    LVector3 normal = plane.get_normal();

    static const PN_stdfloat scale = 20.0f;
    normal *= scale;
    points[0] += normal;
    points[1] += normal;
    points[2] += normal;
    points[3] += normal;

    for (int i = 0; i < 8; ++i) {
      const LPoint3 &p = points[i];
      out << p[0] << "," << p[1] << "," << p[2] << "\n";
    }
  }

  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: PfmBba::handle_args
//       Access: Protected, Virtual
//  Description: Does something with the additional arguments on the
//               command line (after all the -options have been
//               parsed).  Returns true if the arguments are good,
//               false otherwise.
////////////////////////////////////////////////////////////////////
bool PfmBba::
handle_args(ProgramBase::Args &args) {
  if (args.empty()) {
    nout << "You must specify the pfm file(s) to read on the command line.\n";
    return false;
  }

  if (args.size() > 1 && _got_output_filename) {
    nout << "Cannot use -o when multiple pfm files are specified.\n";
    return false;
  }

  Args::const_iterator ai;
  for (ai = args.begin(); ai != args.end(); ++ai) {
    _input_filenames.push_back(Filename::from_os_specific(*ai));
  }

  return true;
}

int main(int argc, char *argv[]) {
  // A call to pystub() to force libpystub.so to be linked in.
  pystub();

  PfmBba prog;
  prog.parse_command_line(argc, argv);
  prog.run();
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2015, Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "ParameterBlackboard.h"
#include "Iterator.hpp"
#include <cassert>
#include <algorithm>

// Size
void CParameterBlackboard::setSize(size_t size)
{
    mBlackboard.resize(size);
}

size_t CParameterBlackboard::getSize() const
{
    return mBlackboard.size();
}

// Single parameter access
void CParameterBlackboard::writeInteger(const void* pvSrcData, size_t size, size_t offset, bool bBigEndian)
{
    assertValidAccess(offset, size);

    auto first = MAKE_ARRAY_ITERATOR(static_cast<const uint8_t *>(pvSrcData), size);
    auto last = first + size;
    auto dest_first = atOffset(offset);

    if (!bBigEndian) {
        std::copy(first, last, dest_first);
    } else {
        std::reverse_copy(first, last, dest_first);
    }
}

void CParameterBlackboard::readInteger(void* pvDstData, size_t size, size_t offset, bool bBigEndian) const
{
    assertValidAccess(offset, size);

    auto first = atOffset(offset);
    auto last = first + size;
    auto dest_first = MAKE_ARRAY_ITERATOR(static_cast<uint8_t *>(pvDstData), size);

    if (!bBigEndian) {
        std::copy(first, last, dest_first);
    } else {
        std::reverse_copy(first, last, dest_first);
    }
}

void CParameterBlackboard::writeString(const std::string &input, size_t offset)
{
    assertValidAccess(offset, input.size() + 1);

    auto dest_last = std::copy(begin(input), end(input), atOffset(offset));
    *dest_last = '\0';
}

void CParameterBlackboard::readString(std::string &output, size_t offset) const
{
    // As the string is null terminated in the blackboard,
    // the size that will be read is not known. (>= 1)
    assertValidAccess(offset, sizeof('\0'));

    // Get the pointer to the null terminated string
    const uint8_t *first = &mBlackboard[offset];
    output = reinterpret_cast<const char *>(first);
}

void CParameterBlackboard::writeBuffer(const void* pvSrcData, size_t size, size_t offset)
{
    writeInteger(pvSrcData, size, offset, false);
}
void CParameterBlackboard::readBuffer(void* pvDstData, size_t size, size_t offset) const
{
    readInteger(pvDstData, size, offset, false);
}

// Access from/to subsystems
uint8_t* CParameterBlackboard::getLocation(size_t offset)
{
    assertValidAccess(offset, 1);
    return &mBlackboard[offset];
}

// Configuration handling
void CParameterBlackboard::restoreFrom(const CParameterBlackboard* pFromBlackboard, size_t offset)
{
    const auto &fromBB = pFromBlackboard->mBlackboard;
    assertValidAccess(offset, fromBB.size());
    std::copy(begin(fromBB), end(fromBB), atOffset(offset));
}

void CParameterBlackboard::saveTo(CParameterBlackboard* pToBlackboard, size_t offset) const
{
    auto &toBB = pToBlackboard->mBlackboard;
    assertValidAccess(offset, toBB.size());
    std::copy_n(atOffset(offset), toBB.size(), begin(toBB));
}

void CParameterBlackboard::assertValidAccess(size_t offset, size_t size) const
{
    assert(offset + size <= getSize());
}
<commit_msg>Replace an assert by ALWAYS_ASSERT<commit_after>/*
 * Copyright (c) 2011-2015, Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "ParameterBlackboard.h"
#include "Iterator.hpp"
#include "AlwaysAssert.hpp"
#include <algorithm>

// Size
void CParameterBlackboard::setSize(size_t size)
{
    mBlackboard.resize(size);
}

size_t CParameterBlackboard::getSize() const
{
    return mBlackboard.size();
}

// Single parameter access
void CParameterBlackboard::writeInteger(const void* pvSrcData, size_t size, size_t offset, bool bBigEndian)
{
    assertValidAccess(offset, size);

    auto first = MAKE_ARRAY_ITERATOR(static_cast<const uint8_t *>(pvSrcData), size);
    auto last = first + size;
    auto dest_first = atOffset(offset);

    if (!bBigEndian) {
        std::copy(first, last, dest_first);
    } else {
        std::reverse_copy(first, last, dest_first);
    }
}

void CParameterBlackboard::readInteger(void* pvDstData, size_t size, size_t offset, bool bBigEndian) const
{
    assertValidAccess(offset, size);

    auto first = atOffset(offset);
    auto last = first + size;
    auto dest_first = MAKE_ARRAY_ITERATOR(static_cast<uint8_t *>(pvDstData), size);

    if (!bBigEndian) {
        std::copy(first, last, dest_first);
    } else {
        std::reverse_copy(first, last, dest_first);
    }
}

void CParameterBlackboard::writeString(const std::string &input, size_t offset)
{
    assertValidAccess(offset, input.size() + 1);

    auto dest_last = std::copy(begin(input), end(input), atOffset(offset));
    *dest_last = '\0';
}

void CParameterBlackboard::readString(std::string &output, size_t offset) const
{
    // As the string is null terminated in the blackboard,
    // the size that will be read is not known. (>= 1)
    assertValidAccess(offset, sizeof('\0'));

    // Get the pointer to the null terminated string
    const uint8_t *first = &mBlackboard[offset];
    output = reinterpret_cast<const char *>(first);
}

void CParameterBlackboard::writeBuffer(const void* pvSrcData, size_t size, size_t offset)
{
    writeInteger(pvSrcData, size, offset, false);
}
void CParameterBlackboard::readBuffer(void* pvDstData, size_t size, size_t offset) const
{
    readInteger(pvDstData, size, offset, false);
}

// Access from/to subsystems
uint8_t* CParameterBlackboard::getLocation(size_t offset)
{
    assertValidAccess(offset, 1);
    return &mBlackboard[offset];
}

// Configuration handling
void CParameterBlackboard::restoreFrom(const CParameterBlackboard* pFromBlackboard, size_t offset)
{
    const auto &fromBB = pFromBlackboard->mBlackboard;
    assertValidAccess(offset, fromBB.size());
    std::copy(begin(fromBB), end(fromBB), atOffset(offset));
}

void CParameterBlackboard::saveTo(CParameterBlackboard* pToBlackboard, size_t offset) const
{
    auto &toBB = pToBlackboard->mBlackboard;
    assertValidAccess(offset, toBB.size());
    std::copy_n(atOffset(offset), toBB.size(), begin(toBB));
}

void CParameterBlackboard::assertValidAccess(size_t offset, size_t size) const
{
    ALWAYS_ASSERT(offset + size <= getSize(), "Invalid data size access: offset=" << offset
            << " size=" << size
            << "reference size=" << getSize());
}
<|endoftext|>


<commit_before>// Modified from chromium/src/webkit/glue/gl_bindings_skia_cmd_buffer.cc

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "GrGLInterface.h"

#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif

#include "gl2.h"
#include "gl2ext.h"

void GrGLInitializeDefaultGLInterface() {
    GrGLSetGLInterface* glInterface = new GrGLInterface;

    glInterface->fBindingsExported = kES2_GrGLBinding;
    glInterface->fActiveTexture = glActiveTexture;
    glInterface->fAttachShader = glAttachShader;
    glInterface->fBindAttribLocation = glBindAttribLocation;
    glInterface->fBindBuffer = glBindBuffer;
    glInterface->fBindTexture = glBindTexture;
    glInterface->fBlendColor = glBlendColor;
    glInterface->fBlendFunc = glBlendFunc;
    glInterface->fBufferData = glBufferData;
    glInterface->fBufferSubData = glBufferSubData;
    glInterface->fClear = glClear;
    glInterface->fClearColor = glClearColor;
    glInterface->fClearStencil = glClearStencil;
    glInterface->fColorMask = glColorMask;
    glInterface->fCompileShader = glCompileShader;
    glInterface->fCompressedTexImage2D = glCompressedTexImage2D;
    glInterface->fCreateProgram = glCreateProgram;
    glInterface->fCreateShader = glCreateShader;
    glInterface->fCullFace = glCullFace;
    glInterface->fDeleteBuffers = glDeleteBuffers;
    glInterface->fDeleteProgram = glDeleteProgram;
    glInterface->fDeleteShader = glDeleteShader;
    glInterface->fDeleteTextures = glDeleteTextures;
    glInterface->fDepthMask = glDepthMask;
    glInterface->fDisable = glDisable;
    glInterface->fDisableVertexAttribArray = glDisableVertexAttribArray;
    glInterface->fDrawArrays = glDrawArrays;
    glInterface->fDrawElements = glDrawElements;
    glInterface->fEnable = glEnable;
    glInterface->fEnableVertexAttribArray = glEnableVertexAttribArray;
    glInterface->fFrontFace = glFrontFace;
    glInterface->fGenBuffers = glGenBuffers;
    glInterface->fGenTextures = glGenTextures;
    glInterface->fGetBufferParameteriv = glGetBufferParameteriv;
    glInterface->fGetError = glGetError;
    glInterface->fGetIntegerv = glGetIntegerv;
    glInterface->fGetProgramInfoLog = glGetProgramInfoLog;
    glInterface->fGetProgramiv = glGetProgramiv;
    glInterface->fGetShaderInfoLog = glGetShaderInfoLog;
    glInterface->fGetShaderiv = glGetShaderiv;
    glInterface->fGetString = glGetString;
    glInterface->fGetUniformLocation = glGetUniformLocation;
    glInterface->fLineWidth = glLineWidth;
    glInterface->fLinkProgram = glLinkProgram;
    glInterface->fPixelStorei = glPixelStorei;
    glInterface->fReadPixels = glReadPixels;
    glInterface->fScissor = glScissor;
    glInterface->fShaderSource = glShaderSource;
    glInterface->fStencilFunc = glStencilFunc;
    glInterface->fStencilFuncSeparate = glStencilFuncSeparate;
    glInterface->fStencilMask = glStencilMask;
    glInterface->fStencilMaskSeparate = glStencilMaskSeparate;
    glInterface->fStencilOp = glStencilOp;
    glInterface->fStencilOpSeparate = glStencilOpSeparate;
    glInterface->fTexImage2D = glTexImage2D;
    glInterface->fTexParameteri = glTexParameteri;
    glInterface->fTexSubImage2D = glTexSubImage2D;
    glInterface->fUniform1f = glUniform1f;
    glInterface->fUniform1i = glUniform1i;
    glInterface->fUniform1fv = glUniform1fv;
    glInterface->fUniform1iv = glUniform1iv;
    glInterface->fUniform2f = glUniform2f;
    glInterface->fUniform2i = glUniform2i;
    glInterface->fUniform2fv = glUniform2fv;
    glInterface->fUniform2iv = glUniform2iv;
    glInterface->fUniform3f = glUniform3f;
    glInterface->fUniform3i = glUniform3i;
    glInterface->fUniform3fv = glUniform3fv;
    glInterface->fUniform3iv = glUniform3iv;
    glInterface->fUniform4f = glUniform4f;
    glInterface->fUniform4i = glUniform4i;
    glInterface->fUniform4fv = glUniform4fv;
    glInterface->fUniform4iv = glUniform4iv;
    glInterface->fUniformMatrix2fv = glUniformMatrix2fv;
    glInterface->fUniformMatrix3fv = glUniformMatrix3fv;
    glInterface->fUniformMatrix4fv = glUniformMatrix4fv;
    glInterface->fUseProgram = glUseProgram;
    glInterface->fVertexAttrib4fv = glVertexAttrib4fv;
    glInterface->fVertexAttribPointer = glVertexAttribPointer;
    glInterface->fViewport = glViewport;
    glInterface->fBindFramebuffer = glBindFramebuffer;
    glInterface->fBindRenderbuffer = glBindRenderbuffer;
    glInterface->fCheckFramebufferStatus = glCheckFramebufferStatus;
    glInterface->fDeleteFramebuffers = glDeleteFramebuffers;
    glInterface->fDeleteRenderbuffers = glDeleteRenderbuffers;
    glInterface->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
    glInterface->fFramebufferTexture2D = glFramebufferTexture2D;
    glInterface->fGenFramebuffers = glGenFramebuffers;
    glInterface->fGenRenderbuffers = glGenRenderbuffers;
    glInterface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
    glInterface->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
    glInterface->fRenderbufferStorage = glRenderbufferStorage;
    glInterface->fMapBufferOES = glMapBufferOES;
    glInterface->fUnmapBufferOES = glUnmapBufferOES;

    GrGLSetDefaultInterface(glInterface)->unref();
}
<commit_msg>Fix bitrot in GrGLDefaultInterface_android.cpp<commit_after>// Modified from chromium/src/webkit/glue/gl_bindings_skia_cmd_buffer.cc

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "GrGLInterface.h"

#ifndef GL_GLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#endif

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

void GrGLInitializeDefaultGLInterface() {
    GrGLInterface* glInterface = new GrGLInterface;

    glInterface->fBindingsExported = kES2_GrGLBinding;
    glInterface->fActiveTexture = glActiveTexture;
    glInterface->fAttachShader = glAttachShader;
    glInterface->fBindAttribLocation = glBindAttribLocation;
    glInterface->fBindBuffer = glBindBuffer;
    glInterface->fBindTexture = glBindTexture;
    glInterface->fBlendColor = glBlendColor;
    glInterface->fBlendFunc = glBlendFunc;
    glInterface->fBufferData = glBufferData;
    glInterface->fBufferSubData = glBufferSubData;
    glInterface->fClear = glClear;
    glInterface->fClearColor = glClearColor;
    glInterface->fClearStencil = glClearStencil;
    glInterface->fColorMask = glColorMask;
    glInterface->fCompileShader = glCompileShader;
    glInterface->fCompressedTexImage2D = glCompressedTexImage2D;
    glInterface->fCreateProgram = glCreateProgram;
    glInterface->fCreateShader = glCreateShader;
    glInterface->fCullFace = glCullFace;
    glInterface->fDeleteBuffers = glDeleteBuffers;
    glInterface->fDeleteProgram = glDeleteProgram;
    glInterface->fDeleteShader = glDeleteShader;
    glInterface->fDeleteTextures = glDeleteTextures;
    glInterface->fDepthMask = glDepthMask;
    glInterface->fDisable = glDisable;
    glInterface->fDisableVertexAttribArray = glDisableVertexAttribArray;
    glInterface->fDrawArrays = glDrawArrays;
    glInterface->fDrawElements = glDrawElements;
    glInterface->fEnable = glEnable;
    glInterface->fEnableVertexAttribArray = glEnableVertexAttribArray;
    glInterface->fFrontFace = glFrontFace;
    glInterface->fGenBuffers = glGenBuffers;
    glInterface->fGenTextures = glGenTextures;
    glInterface->fGetBufferParameteriv = glGetBufferParameteriv;
    glInterface->fGetError = glGetError;
    glInterface->fGetIntegerv = glGetIntegerv;
    glInterface->fGetProgramInfoLog = glGetProgramInfoLog;
    glInterface->fGetProgramiv = glGetProgramiv;
    glInterface->fGetShaderInfoLog = glGetShaderInfoLog;
    glInterface->fGetShaderiv = glGetShaderiv;
    glInterface->fGetString = glGetString;
    glInterface->fGetUniformLocation = glGetUniformLocation;
    glInterface->fLineWidth = glLineWidth;
    glInterface->fLinkProgram = glLinkProgram;
    glInterface->fPixelStorei = glPixelStorei;
    glInterface->fReadPixels = glReadPixels;
    glInterface->fScissor = glScissor;
    glInterface->fShaderSource = glShaderSource;
    glInterface->fStencilFunc = glStencilFunc;
    glInterface->fStencilFuncSeparate = glStencilFuncSeparate;
    glInterface->fStencilMask = glStencilMask;
    glInterface->fStencilMaskSeparate = glStencilMaskSeparate;
    glInterface->fStencilOp = glStencilOp;
    glInterface->fStencilOpSeparate = glStencilOpSeparate;
    glInterface->fTexImage2D = glTexImage2D;
    glInterface->fTexParameteri = glTexParameteri;
    glInterface->fTexSubImage2D = glTexSubImage2D;
    glInterface->fUniform1f = glUniform1f;
    glInterface->fUniform1i = glUniform1i;
    glInterface->fUniform1fv = glUniform1fv;
    glInterface->fUniform1iv = glUniform1iv;
    glInterface->fUniform2f = glUniform2f;
    glInterface->fUniform2i = glUniform2i;
    glInterface->fUniform2fv = glUniform2fv;
    glInterface->fUniform2iv = glUniform2iv;
    glInterface->fUniform3f = glUniform3f;
    glInterface->fUniform3i = glUniform3i;
    glInterface->fUniform3fv = glUniform3fv;
    glInterface->fUniform3iv = glUniform3iv;
    glInterface->fUniform4f = glUniform4f;
    glInterface->fUniform4i = glUniform4i;
    glInterface->fUniform4fv = glUniform4fv;
    glInterface->fUniform4iv = glUniform4iv;
    glInterface->fUniformMatrix2fv = glUniformMatrix2fv;
    glInterface->fUniformMatrix3fv = glUniformMatrix3fv;
    glInterface->fUniformMatrix4fv = glUniformMatrix4fv;
    glInterface->fUseProgram = glUseProgram;
    glInterface->fVertexAttrib4fv = glVertexAttrib4fv;
    glInterface->fVertexAttribPointer = glVertexAttribPointer;
    glInterface->fViewport = glViewport;
    glInterface->fBindFramebuffer = glBindFramebuffer;
    glInterface->fBindRenderbuffer = glBindRenderbuffer;
    glInterface->fCheckFramebufferStatus = glCheckFramebufferStatus;
    glInterface->fDeleteFramebuffers = glDeleteFramebuffers;
    glInterface->fDeleteRenderbuffers = glDeleteRenderbuffers;
    glInterface->fFramebufferRenderbuffer = glFramebufferRenderbuffer;
    glInterface->fFramebufferTexture2D = glFramebufferTexture2D;
    glInterface->fGenFramebuffers = glGenFramebuffers;
    glInterface->fGenRenderbuffers = glGenRenderbuffers;
    glInterface->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv;
    glInterface->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv;
    glInterface->fRenderbufferStorage = glRenderbufferStorage;
#if GL_OES_mapbuffer
    glInterface->fMapBuffer = glMapBufferOES;
    glInterface->fUnmapBuffer = glUnmapBufferOES;
#endif
    GrGLSetDefaultGLInterface(glInterface)->unref();
}
<|endoftext|>