<commit_before>#include "drawer.hh"

#include <cmath>
#include <cstring>
#include <deque>
#include <fstream>
#include <stdexcept>

#include "bezier.hh"

namespace
{

const std::string svg_preambule(
    "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
    "<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>\n"
    );

struct svg_shape
{
    svg_shape() = default;
    svg_shape(const svg_shape &) = delete;
    svg_shape & operator=(const svg_shape &) = delete;

    virtual void flush(std::ostream & out) = 0;

    virtual ~svg_shape()
    {
    }
};

struct svg_circle
    : public svg_shape
{
    CanvasPoint pos;
    double radius;
    std::string fill;
    double stroke_width;
    std::string stroke;

    svg_circle(const CanvasPoint & pos, double radius, const std::string & fill,
               double stroke_width, const std::string & stroke)
        : pos(pos), radius(radius), fill(fill),
          stroke_width(stroke_width), stroke(stroke)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<circle cx='" << pos.x << "' cy='" << pos.y << "' r='" << radius << "' fill='" << fill << "' "
            "stroke='" << stroke << "' stroke-width='" << stroke_width << "' />\n";
    }
};

struct svg_rect
    : public svg_shape
{
    CanvasPoint start, size;
    std::string fill;

    svg_rect(const CanvasPoint & start, const CanvasPoint & size, const std::string & fill)
        : start(start), size(size), fill(fill)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<rect x='" << start.x << "' y='" << start.y << "' "
            "width='" << size.x << "' height='" << size.y << "' fill='" << fill << "' />\n";
    }
};

struct svg_cbezier
    : public svg_shape
{
    std::vector<CanvasPoint> path;
    std::string stroke;
    double width;

    svg_cbezier(std::vector<CanvasPoint> && path, const std::string & stroke, double width)
        : path(std::move(path)), stroke(stroke), width(width)
    {
    }

    virtual void flush(std::ostream & out)
    {
        auto beziered(interpolate_bezier(path));
/*
        // drawing ugly control points, usefull for debugging
        for (auto i(beziered.cbegin()), i_end(beziered.cend());
             i != i_end; ++i)
        {
            out << "<circle cx='" << i->p.x << "' cy='" << i->p.y << "' r='2px' fill='black' />\n";
            out << "<circle cx='" << i->cm.x << "' cy='" << i->cm.y << "' r='1px' fill='blue' />\n";
            out << "<circle cx='" << i->cp.x << "' cy='" << i->cp.y << "' r='1px' fill='green' />\n";
        }
*/

        out << "<path stroke='gray' stroke-width='" << width << "' fill='none'\n  d='";
        auto prev(beziered.cbegin());
        out << 'M' << prev->p.x << ',' << prev->p.y << ' ';
        for (auto next(prev + 1), i_end(beziered.cend());
             next != i_end; prev = next, ++next)
        {
            out << 'C' << prev->cp.x << ',' << prev->cp.y << ' '
                << next->cm.x << ',' << next->cm.y << ' '
                << next->p.x << ',' << next->p.y << ' ';
        }
        out << "' />\n";
    }
};

struct svg_text
    : public svg_shape
{
    std::string body;
    CanvasPoint pos;
    double size;

    svg_text(const std::string & body, const CanvasPoint & pos, double size)
        : body(body), pos(pos), size(size)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<text x='" << pos.x << "' y='" << pos.y << "' font-size='" << size << "' font-family='sans-serif'>\n"
            << body << "\n</text>\n";
    }
};

}

struct Drawer::Implementation
{
    std::shared_ptr<Projection> projection_;
    double canvas_margin_;
    const CanvasPoint canvas_, canvas_start_, canvas_end_;
    std::deque<std::shared_ptr<svg_shape>> shapes_;

    Implementation(const CanvasPoint & canvas, double canvas_margin)
        : canvas_margin_(canvas_margin),
          canvas_(canvas),
          canvas_start_(-canvas.x / 2. - canvas_margin_, -canvas.y / 2. - canvas_margin_),
          canvas_end_(canvas.x / 2. + canvas_margin_, canvas_.y / 2. + canvas_margin_)
    {
    }

    bool in_canvas(const CanvasPoint & oc)
    {
        return oc.x >= canvas_start_.x && oc.y >= canvas_start_.y &&
            oc.x <= canvas_end_.x && oc.y <= canvas_end_.y;
    }

    double mag2size(double mag)
    {
        static const double e(exp(1));
        return exp(-mag / e);
    }

    double draw_by_magnitudo(const SolarObject & object, double jd, const CanvasPoint & coord)
    {
        double s(mag2size(object.get_magnitude(jd)));
        shapes_.push_back(std::make_shared<svg_circle>(coord, s, "red", s/10., "blue"));
        return s;
    }

    double draw_by_sdiam(const SolarObject & object, double jd, const CanvasPoint & coord, const ln_equ_posn & pos)
    {
        double s(object.get_sdiam(jd) * projection_->scale_at_point(pos) / 3600.);
        shapes_.push_back(std::make_shared<svg_circle>(coord, s, "#22222", 0., ""));
        return s;
    }
};

Drawer::Drawer(const CanvasPoint & canvas, double canvas_margin)
    : imp_(new Implementation(canvas, canvas_margin))
{
    std::string background_color("white");
    imp_->shapes_.push_back(
        std::make_shared<svg_rect>(CanvasPoint(-imp_->canvas_.x / 2., -imp_->canvas_.y / 2.),
                                   CanvasPoint(imp_->canvas_.x, imp_->canvas_.y), background_color));
}

Drawer::~Drawer()
{
}

void Drawer::set_projection(const std::shared_ptr<Projection> & projection)
{
    imp_->projection_ = projection;
}

void Drawer::store(const char * file) const
{
    std::ofstream of(file);
    if (! of)
        throw std::runtime_error("Can't open file '" + std::string(file) + "' for writing " + std::strerror(errno));

    of << svg_preambule;

    of << "<svg width='" << imp_->canvas_.x << "mm' height='" << imp_->canvas_.y << "mm' "
        "viewBox='" << -imp_->canvas_.x / 2. << ' ' << -imp_->canvas_.y / 2. <<
        ' ' << imp_->canvas_.x << ' ' << imp_->canvas_.y << "' "
        "xmlns='http://www.w3.org/2000/svg' version='1.1'>\n";

    for (auto shape(imp_->shapes_.begin()), shape_end(imp_->shapes_.end());
         shape != shape_end; ++shape)
        (*shape)->flush(of);

    of << "</svg>\n";
}

void Drawer::draw(const Star & star)
{
    static std::string black("black");
    static std::string white("white");

    CanvasPoint coord(imp_->projection_->project(star.pos_));
    if (! imp_->in_canvas(coord))
        return;

    double s(imp_->mag2size(star.vmag_));
    auto c(std::make_shared<svg_circle>(coord, s, black, .5 * s, white));
    imp_->shapes_.push_back(c);

//    if (star.vmag_ < 4. && ! star.common_name_.empty())
//        imp_->board << Lb::Text(-star.pos_.ra + s, star.pos_.dec, star.common_name_, Lb::Fonts::Helvetica, 3.);
}

void Drawer::draw(const std::vector<ln_equ_posn> & path)
{
    std::vector<CanvasPoint> ret;
    for (auto i(path.begin()), i_end(path.end());
         i != i_end; ++i)
        ret.push_back(imp_->projection_->project(*i));
    imp_->shapes_.push_back(std::make_shared<svg_cbezier>(std::move(ret), "#888888", 0.1));
}

void Drawer::draw(const std::string & body, const ln_equ_posn & pos)
{
    imp_->shapes_.push_back(std::make_shared<svg_text>(body, imp_->projection_->project(pos), 4.));
}

void Drawer::draw(const SolarObject & object, double jd, object_rendering_type type, bool label)
{
    auto pos(object.get_equ_coords(jd));
    auto coord(imp_->projection_->project(pos));

    double s(0.);
    switch (type)
    {
        case magnitudo:
            s = imp_->draw_by_magnitudo(object, jd, coord);
            break;
        case sdiam:
            s = imp_->draw_by_sdiam(object, jd, coord, pos);
            break;
    }

    if (label)
    {
        coord.x += s;
        coord.y += 1.;
        imp_->shapes_.push_back(std::make_shared<svg_text>(object.name(), coord, 4.));
    }
}
<commit_msg>clip paths<commit_after>#include "drawer.hh"

#include <cmath>
#include <cstring>
#include <deque>
#include <fstream>
#include <stdexcept>

#include "bezier.hh"

namespace
{

const std::string svg_preambule(
    "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
    "<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>\n"
    );

struct svg_shape
{
    svg_shape() = default;
    svg_shape(const svg_shape &) = delete;
    svg_shape & operator=(const svg_shape &) = delete;

    virtual void flush(std::ostream & out) = 0;

    virtual ~svg_shape()
    {
    }
};

struct svg_circle
    : public svg_shape
{
    CanvasPoint pos;
    double radius;
    std::string fill;
    double stroke_width;
    std::string stroke;

    svg_circle(const CanvasPoint & pos, double radius, const std::string & fill,
               double stroke_width, const std::string & stroke)
        : pos(pos), radius(radius), fill(fill),
          stroke_width(stroke_width), stroke(stroke)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<circle cx='" << pos.x << "' cy='" << pos.y << "' r='" << radius << "' fill='" << fill << "' "
            "stroke='" << stroke << "' stroke-width='" << stroke_width << "' />\n";
    }
};

struct svg_rect
    : public svg_shape
{
    CanvasPoint start, size;
    std::string fill;

    svg_rect(const CanvasPoint & start, const CanvasPoint & size, const std::string & fill)
        : start(start), size(size), fill(fill)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<rect x='" << start.x << "' y='" << start.y << "' "
            "width='" << size.x << "' height='" << size.y << "' fill='" << fill << "' />\n";
    }
};

struct svg_cbezier
    : public svg_shape
{
    BezierCurve path;
    std::string stroke;
    double width;

    svg_cbezier(const BezierCurve & path, const std::string & stroke, double width)
        : path(std::move(path)), stroke(stroke), width(width)
    {
    }

    virtual void flush(std::ostream & out)
    {
/*
        // drawing ugly control points, usefull for debugging
        for (auto i(path.cbegin()), i_end(path.cend());
             i != i_end; ++i)
        {
            out << "<circle cx='" << i->p.x << "' cy='" << i->p.y << "' r='2px' fill='black' />\n";
            out << "<circle cx='" << i->cm.x << "' cy='" << i->cm.y << "' r='1px' fill='blue' />\n";
            out << "<circle cx='" << i->cp.x << "' cy='" << i->cp.y << "' r='1px' fill='green' />\n";
        }
*/

        out << "<path stroke='gray' stroke-width='" << width << "' fill='none'\n  d='";
        auto prev(path.cbegin());
        out << 'M' << prev->p.x << ',' << prev->p.y << ' ';
        for (auto next(prev + 1), i_end(path.cend());
             next != i_end; prev = next, ++next)
        {
            out << 'C' << prev->cp.x << ',' << prev->cp.y << ' '
                << next->cm.x << ',' << next->cm.y << ' '
                << next->p.x << ',' << next->p.y << ' ';
        }
        out << "' />\n";
    }
};

struct svg_text
    : public svg_shape
{
    std::string body;
    CanvasPoint pos;
    double size;

    svg_text(const std::string & body, const CanvasPoint & pos, double size)
        : body(body), pos(pos), size(size)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<text x='" << pos.x << "' y='" << pos.y << "' font-size='" << size << "' font-family='sans-serif'>\n"
            << body << "\n</text>\n";
    }
};

}

struct Drawer::Implementation
{
    std::shared_ptr<Projection> projection_;
    double canvas_margin_;
    const CanvasPoint canvas_, canvas_start_, canvas_end_;
    std::deque<std::shared_ptr<svg_shape>> shapes_;

    Implementation(const CanvasPoint & canvas, double canvas_margin)
        : canvas_margin_(canvas_margin),
          canvas_(canvas),
          canvas_start_(-canvas.x / 2. - canvas_margin_, -canvas.y / 2. - canvas_margin_),
          canvas_end_(canvas.x / 2. + canvas_margin_, canvas_.y / 2. + canvas_margin_)
    {
    }

    bool in_canvas(const CanvasPoint & oc)
    {
        return oc.x >= canvas_start_.x && oc.y >= canvas_start_.y &&
            oc.x <= canvas_end_.x && oc.y <= canvas_end_.y;
    }

    double mag2size(double mag)
    {
        static const double e(exp(1));
        return exp(-mag / e);
    }

    double draw_by_magnitudo(const SolarObject & object, double jd, const CanvasPoint & coord)
    {
        double s(mag2size(object.get_magnitude(jd)));
        shapes_.push_back(std::make_shared<svg_circle>(coord, s, "red", s/10., "blue"));
        return s;
    }

    double draw_by_sdiam(const SolarObject & object, double jd, const CanvasPoint & coord, const ln_equ_posn & pos)
    {
        double s(object.get_sdiam(jd) * projection_->scale_at_point(pos) / 3600.);
        shapes_.push_back(std::make_shared<svg_circle>(coord, s, "#22222", 0., ""));
        return s;
    }

    enum {
        inside = 0, // 0000
        left   = 1, // 0001
        right  = 2, // 0010
        bottom = 4, // 0100
        top    = 8  // 1000
    };

    int Outcode(const CanvasPoint & p)
    {
        int code(0);

        if (p.x < canvas_start_.x)
            code |= left;
        else if (p.x > canvas_end_.x)
            code |= right;

        if (p.y < canvas_start_.y)
            code |= bottom;
        else if (p.y > canvas_end_.y)
            code |= top;

        return code;
    }

    bool CohenSutherland(CanvasPoint p0, CanvasPoint p1)
    {
        int code0 = Outcode(p0);
        int code1 = Outcode(p1);
        bool ret(false);

        while (true)
        {
            if (!(code0 | code1))
            {
                ret = true;
                break;
            }
            else if (code0 & code1)
            {
                break;
            }
            else
            {
                CanvasPoint p;
                int code = code0 ? code0 : code1;

                // use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0)
                if (code & top)
                {
                    p.x = p0.x + (p1.x - p0.x) * (canvas_end_.y - p0.y) / (p1.y - p0.y);
                    p.y = canvas_end_.y;
                }
                else if (code & bottom)
                {
                    p.x = p0.x + (p1.x - p0.x) * (canvas_start_.y - p0.y) / (p1.y - p0.y);
                    p.y = canvas_start_.y;
                }
                else if (code & right)
                {
                    p.y = p0.y + (p1.y - p0.y) * (canvas_end_.x - p0.x) / (p1.x - p0.x);
                    p.x = canvas_end_.x;
                }
                else if (code & left)
                {
                    p.y = p0.y + (p1.y - p0.y) * (canvas_start_.x - p0.x) / (p1.x - p0.x);
                    p.x = canvas_start_.x;
                }

                if (code == code0)
                {
                    p0 = p;
                    code0 = Outcode(p0);
                }
                else
                {
                    p1 = p;
                    code1 = Outcode(p1);
                }
            }
        }

        return ret;
    }

};

Drawer::Drawer(const CanvasPoint & canvas, double canvas_margin)
    : imp_(new Implementation(canvas, canvas_margin))
{
    std::string background_color("white");
    imp_->shapes_.push_back(
        std::make_shared<svg_rect>(CanvasPoint(-imp_->canvas_.x / 2., -imp_->canvas_.y / 2.),
                                   CanvasPoint(imp_->canvas_.x, imp_->canvas_.y), background_color));
}

Drawer::~Drawer()
{
}

void Drawer::set_projection(const std::shared_ptr<Projection> & projection)
{
    imp_->projection_ = projection;
}

void Drawer::store(const char * file) const
{
    std::ofstream of(file);
    if (! of)
        throw std::runtime_error("Can't open file '" + std::string(file) + "' for writing " + std::strerror(errno));

    of << svg_preambule;

    of << "<svg width='" << imp_->canvas_.x << "mm' height='" << imp_->canvas_.y << "mm' "
        "viewBox='" << -imp_->canvas_.x / 2. << ' ' << -imp_->canvas_.y / 2. <<
        ' ' << imp_->canvas_.x << ' ' << imp_->canvas_.y << "' "
        "xmlns='http://www.w3.org/2000/svg' version='1.1'>\n";

    for (auto shape(imp_->shapes_.begin()), shape_end(imp_->shapes_.end());
         shape != shape_end; ++shape)
        (*shape)->flush(of);

    of << "</svg>\n";
}

void Drawer::draw(const Star & star)
{
    static std::string black("black");
    static std::string white("white");

    CanvasPoint coord(imp_->projection_->project(star.pos_));
    if (! imp_->in_canvas(coord))
        return;

    double s(imp_->mag2size(star.vmag_));
    auto c(std::make_shared<svg_circle>(coord, s, black, .5 * s, white));
    imp_->shapes_.push_back(c);

//    if (star.vmag_ < 4. && ! star.common_name_.empty())
//        imp_->board << Lb::Text(-star.pos_.ra + s, star.pos_.dec, star.common_name_, Lb::Fonts::Helvetica, 3.);
}

void Drawer::draw(const std::vector<ln_equ_posn> & path)
{
    std::vector<std::vector<CanvasPoint>> ret(1);
    for (auto i(path.begin()), i_end(path.end());
         i != i_end; ++i)
    {
        auto p(imp_->projection_->project(*i));
        if (! p.nan())
            ret.back().push_back(p);
        else if (! ret.back().empty())
            ret.push_back(std::vector<CanvasPoint>());
    }

    std::vector<BezierCurve> strips(1);
    for (auto b(ret.cbegin()), b_end(ret.cend());
         b != b_end; ++b)
    {
        if (! strips.back().empty())
            strips.push_back(BezierCurve());

        auto beziered(interpolate_bezier(*b));
        auto first(beziered.cbegin()), second(first + 1);
        for (auto end(beziered.cend());
             second != end; first = second, ++second)
        {
            if (imp_->CohenSutherland(first->p, second->p))
            {
                if (strips.back().empty())
                    strips.back().push_back(*first);
                strips.back().push_back(*second);
            }
            else if (! strips.back().empty())
                strips.push_back(BezierCurve());
        }
    }

    for (auto i(strips.cbegin()), i_end(strips.cend());
         i != i_end; ++i)
        if (! i->empty())
            imp_->shapes_.push_back(std::make_shared<svg_cbezier>(*i, "#888888", 0.1));
}

void Drawer::draw(const std::string & body, const ln_equ_posn & pos)
{
    imp_->shapes_.push_back(std::make_shared<svg_text>(body, imp_->projection_->project(pos), 4.));
}

void Drawer::draw(const SolarObject & object, double jd, object_rendering_type type, bool label)
{
    auto pos(object.get_equ_coords(jd));
    auto coord(imp_->projection_->project(pos));

    double s(0.);
    switch (type)
    {
        case magnitudo:
            s = imp_->draw_by_magnitudo(object, jd, coord);
            break;
        case sdiam:
            s = imp_->draw_by_sdiam(object, jd, coord, pos);
            break;
    }

    if (label)
    {
        coord.x += s;
        coord.y += 1.;
        imp_->shapes_.push_back(std::make_shared<svg_text>(object.name(), coord, 4.));
    }
}
<|endoftext|>


<commit_before>#ifndef HEFUR_ANNOUNCE_REQUEST_HH
# define HEFUR_ANNOUNCE_REQUEST_HH

namespace hefur
{
  /**
   * This class represents a generic announce request.
   * It is used by both http(s) server and upd server.
   */
  struct AnnounceRequest
  {
  };
}

#endif /* !HEFUR_ANNOUNCE_REQUEST_HH */
<commit_msg>Add internal AnnounceRequest representation.<commit_after>#ifndef HEFUR_ANNOUNCE_REQUEST_HH
# define HEFUR_ANNOUNCE_REQUEST_HH

# include <cstdint>

# include "address.hh"
# include "info-sha1.hh"

namespace hefur
{
  /**
   * This class represents a generic announce request.
   * It is used by both http(s) server and upd server.
   */
  struct AnnounceRequest
  {
    enum Event
    {
      kNone,
      kStarted,
      kCompleted,
      kStopped,
    };

    char     peerid_[20];
    InfoSha1 info_sha1_;
    Event    event_;
    uint64_t downloaded_;
    uint64_t uploaded_;
    Address  addr_;
  };
}

#endif /* !HEFUR_ANNOUNCE_REQUEST_HH */
<|endoftext|>


<commit_before>// Filename: executionEnvironment.cxx
// Created by:  drose (15May00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "executionEnvironment.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>  // for perror

#ifdef WIN32_VC
// Windows requires this for getcwd().
#include <direct.h>
#define getcwd _getcwd
#endif

// We define the symbol PREREAD_ENVIRONMENT if we cannot rely on
// getenv() to read environment variables at static init time.  In
// this case, we must read all of the environment variables directly
// and cache them locally.

#ifndef STATIC_INIT_GETENV
#define PREREAD_ENVIRONMENT
#endif

// We define the symbol HAVE_GLOBAL_ARGV if we have global variables
// named GLOBAL_ARGC/GLOBAL_ARGV that we can read at static init time
// to determine our command-line arguments.

#if defined(HAVE_GLOBAL_ARGV) && defined(PROTOTYPE_GLOBAL_ARGV)
extern char **GLOBAL_ARGV;
extern int GLOBAL_ARGC;
#endif

// Linux with GNU libc does have global argv/argc variables, but we
// can't safely access them at stat init time--at least, not in libc5.
// (It does seem to work with glibc2, however.)

ExecutionEnvironment *ExecutionEnvironment::_global_ptr = NULL;

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::Constructor
//       Access: Private
//  Description: You shouldn't need to construct one of these; there's
//               only one and it constructs itself.
////////////////////////////////////////////////////////////////////
ExecutionEnvironment::
ExecutionEnvironment() {
  read_environment_variables();
  read_args();
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnviroment::expand_string
//       Access: Public, Static
//  Description: Reads the string, looking for environment variable
//               names marked by a $.  Expands all such variable
//               names.  A repeated dollar sign ($$) is mapped to a
//               single dollar sign.
//
//               Returns the expanded string.
////////////////////////////////////////////////////////////////////
string ExecutionEnvironment::
expand_string(const string &str) {
  string result;

  size_t last = 0;
  size_t dollar = str.find('$');
  while (dollar != string::npos && dollar + 1 < str.length()) {
    size_t start = dollar + 1;

    if (str[start] == '$') {
      // A double dollar sign maps to a single dollar sign.
      result += str.substr(last, start - last);
      last = start + 1;

    } else {
      string varname;
      size_t end = start;

      if (str[start] == '{') {
        // Curly braces delimit the variable name explicitly.
        end = str.find('}', start + 1);
        if (end != string::npos) {
          varname = str.substr(start + 1, end - (start + 1));
          end++;
        }
      }

      if (end == start) {
        // Scan for the end of the variable name.
        while (end < str.length() && (isalnum(str[end]) || str[end] == '_')) {
          end++;
        }
        varname = str.substr(start, end - start);
      }

      string subst =
      result += str.substr(last, dollar - last);
      result += get_environment_variable(varname);
      last = end;
    }

    dollar = str.find('$', last);
  }

  result += str.substr(last);

  return result;
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnviroment::get_cwd
//       Access: Public, Static
//  Description: Returns the name of the current working directory.
////////////////////////////////////////////////////////////////////
Filename ExecutionEnvironment::
get_cwd() {
  // getcwd() requires us to allocate a dynamic buffer and grow it on
  // demand.
  static size_t bufsize = 1024;
  static char *buffer = NULL;

  if (buffer == (char *)NULL) {
    buffer = new char[bufsize];
  }

  while (getcwd(buffer, bufsize) == (char *)NULL) {
    if (errno != ERANGE) {
      perror("getcwd");
      return string();
    }
    delete[] buffer;
    bufsize = bufsize * 2;
    buffer = new char[bufsize];
    assert(buffer != (char *)NULL);
  }

  return Filename::from_os_specific(buffer);
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_has_environment_variable
//       Access: Private
//  Description: Returns true if the indicated environment variable
//               is defined.  The nonstatic implementation.
////////////////////////////////////////////////////////////////////
bool ExecutionEnvironment::
ns_has_environment_variable(const string &var) const {
#ifdef PREREAD_ENVIRONMENT
  return _variables.count(var) != 0;
#else
  return getenv(var.c_str()) != (char *)NULL;
#endif
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_get_environment_variable
//       Access: Private
//  Description: Returns the definition of the indicated environment
//               variable, or the empty string if the variable is
//               undefined.  The nonstatic implementation.
////////////////////////////////////////////////////////////////////
string ExecutionEnvironment::
ns_get_environment_variable(const string &var) const {
#ifdef PREREAD_ENVIRONMENT
  EnvironmentVariables::const_iterator evi;
  evi = _variables.find(var);
  if (evi != _variables.end()) {
    return (*evi).second;
  }
  return string();
#else
  const char *def = getenv(var.c_str());
  if (def != (char *)NULL) {
    return def;
  }
  return string();
#endif
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_set_environment_variable
//       Access: Private
//  Description: Changes the definition of the indicated environment
//               variable.  The nonstatic implementation.
////////////////////////////////////////////////////////////////////
void ExecutionEnvironment::
ns_set_environment_variable(const string &var, const string &value) {
  _variables[var] = value;
  string putstr = var + "=" + value;

  // putenv() requires us to malloc a new C-style string.
  char *put = (char *)malloc(putstr.length() + 1);
  strcpy(put, putstr.c_str());
  putenv(put);
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_get_num_args
//       Access: Private
//  Description: Returns the number of command-line arguments
//               available, not counting arg 0, the binary name.  The
//               nonstatic implementation.
////////////////////////////////////////////////////////////////////
int ExecutionEnvironment::
ns_get_num_args() const {
  return _args.size();
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_get_arg
//       Access: Private
//  Description: Returns the nth command-line argument.  The index n
//               must be in the range [0 .. get_num_args()).  The
//               first parameter, n == 0, is the first actual
//               parameter, not the binary name.  The nonstatic
//               implementation.
////////////////////////////////////////////////////////////////////
string ExecutionEnvironment::
ns_get_arg(int n) const {
  assert(n >= 0 && n < ns_get_num_args());
  return _args[n];
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_get_binary_name
//       Access: Private
//  Description: Returns the name of the binary executable that
//               started this program, if it can be determined.  The
//               nonstatic implementation.
////////////////////////////////////////////////////////////////////
string ExecutionEnvironment::
ns_get_binary_name() const {
  if (_binary_name.empty()) {
    return "unknown";
  }
  return _binary_name;
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::get_ptr
//       Access: Private, Static
//  Description: Returns a static pointer that may be used to access
//               the global ExecutionEnvironment object.
////////////////////////////////////////////////////////////////////
ExecutionEnvironment *ExecutionEnvironment::
get_ptr() {
  if (_global_ptr == (ExecutionEnvironment *)NULL) {
    _global_ptr = new ExecutionEnvironment;
  }
  return _global_ptr;
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::read_environment_variables
//       Access: Private
//  Description: Fills up the internal table of existing environment
//               variables, if we are in PREREAD_ENVIRONMENT mode.
//               Otherwise, does nothing.
////////////////////////////////////////////////////////////////////
void ExecutionEnvironment::
read_environment_variables() {
#ifdef PREREAD_ENVIRONMENT
#if defined(HAVE_PROC_SELF_ENVIRON)
  // In Linux, and possibly in other systems, we might not be able to
  // use getenv() at static init time.  However, we may be lucky and
  // have a file called /proc/self/environ that may be read to
  // determine all of our environment variables.

  ifstream proc("/proc/self/environ");
  if (proc.fail()) {
    cerr << "Cannot read /proc/self/environ; environment variables unavailable.\n";
    return;
  }

  int ch = proc.get();
  while (!proc.eof() && !proc.fail()) {
    string variable;
    string value;

    while (!proc.eof() && !proc.fail() && ch != '=' && ch != '\0') {
      variable += (char)ch;
      ch = proc.get();
    }

    if (ch == '=') {
      ch = proc.get();
      while (!proc.eof() && !proc.fail() && ch != '\0') {
        value += (char)ch;
        ch = proc.get();
      }
    }

    if (!variable.empty()) {
      _variables[variable] = value;
    }
    ch = proc.get();
  }
#else
  cerr << "Warning: environment variables unavailable to dconfig.\n";
#endif
#endif // PREREAD_ENVIRONMENT
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::read_args
//       Access: Private
//  Description: Reads all the command-line arguments and the name of
//               the binary file, if possible.
////////////////////////////////////////////////////////////////////
void ExecutionEnvironment::
read_args() {
#if defined(HAVE_GLOBAL_ARGV)
  int argc = GLOBAL_ARGC;
  if (argc > 0) {
    _binary_name = GLOBAL_ARGV[0];
  }

  for (int i = 1; i < argc; i++) {
    _args.push_back(GLOBAL_ARGV[i]);
  }

#elif defined(HAVE_PROC_SELF_CMDLINE)
  // In Linux, and possibly in other systems as well, we might not be
  // able to use the global ARGC/ARGV variables at static init time.
  // However, we may be lucky and have a file called
  // /proc/self/cmdline that may be read to determine all of our
  // command-line arguments.

  ifstream proc("/proc/self/cmdline");
  if (proc.fail()) {
    cerr << "Cannot read /proc/self/cmdline; command-line arguments unavailable to config.\n";
    return;
  }

  int ch = proc.get();
  int index = 0;
  while (!proc.eof() && !proc.fail()) {
    string arg;

    while (!proc.eof() && !proc.fail() && ch != '\0') {
      arg += (char)ch;
      ch = proc.get();
    }

    if (index == 0) {
      _binary_name = arg;
    } else {
      _args.push_back(arg);
    }
    index++;

    ch = proc.get();
  }
#else
  cerr << "Warning: command line parameters unavailable to dconfig.\n";
#endif
}
<commit_msg>use GetModuleFileName()<commit_after>// Filename: executionEnvironment.cxx
// Created by:  drose (15May00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "executionEnvironment.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>  // for perror

#ifdef WIN32_VC
// Windows requires this for getcwd().
#include <direct.h>
#define getcwd _getcwd

// And this is for GetModuleFileName().
#include <windows.h>
#endif

// We define the symbol PREREAD_ENVIRONMENT if we cannot rely on
// getenv() to read environment variables at static init time.  In
// this case, we must read all of the environment variables directly
// and cache them locally.

#ifndef STATIC_INIT_GETENV
#define PREREAD_ENVIRONMENT
#endif

// We define the symbol HAVE_GLOBAL_ARGV if we have global variables
// named GLOBAL_ARGC/GLOBAL_ARGV that we can read at static init time
// to determine our command-line arguments.

#if defined(HAVE_GLOBAL_ARGV) && defined(PROTOTYPE_GLOBAL_ARGV)
extern char **GLOBAL_ARGV;
extern int GLOBAL_ARGC;
#endif

// Linux with GNU libc does have global argv/argc variables, but we
// can't safely access them at stat init time--at least, not in libc5.
// (It does seem to work with glibc2, however.)

ExecutionEnvironment *ExecutionEnvironment::_global_ptr = NULL;

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::Constructor
//       Access: Private
//  Description: You shouldn't need to construct one of these; there's
//               only one and it constructs itself.
////////////////////////////////////////////////////////////////////
ExecutionEnvironment::
ExecutionEnvironment() {
  read_environment_variables();
  read_args();
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnviroment::expand_string
//       Access: Public, Static
//  Description: Reads the string, looking for environment variable
//               names marked by a $.  Expands all such variable
//               names.  A repeated dollar sign ($$) is mapped to a
//               single dollar sign.
//
//               Returns the expanded string.
////////////////////////////////////////////////////////////////////
string ExecutionEnvironment::
expand_string(const string &str) {
  string result;

  size_t last = 0;
  size_t dollar = str.find('$');
  while (dollar != string::npos && dollar + 1 < str.length()) {
    size_t start = dollar + 1;

    if (str[start] == '$') {
      // A double dollar sign maps to a single dollar sign.
      result += str.substr(last, start - last);
      last = start + 1;

    } else {
      string varname;
      size_t end = start;

      if (str[start] == '{') {
        // Curly braces delimit the variable name explicitly.
        end = str.find('}', start + 1);
        if (end != string::npos) {
          varname = str.substr(start + 1, end - (start + 1));
          end++;
        }
      }

      if (end == start) {
        // Scan for the end of the variable name.
        while (end < str.length() && (isalnum(str[end]) || str[end] == '_')) {
          end++;
        }
        varname = str.substr(start, end - start);
      }

      string subst =
      result += str.substr(last, dollar - last);
      result += get_environment_variable(varname);
      last = end;
    }

    dollar = str.find('$', last);
  }

  result += str.substr(last);

  return result;
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnviroment::get_cwd
//       Access: Public, Static
//  Description: Returns the name of the current working directory.
////////////////////////////////////////////////////////////////////
Filename ExecutionEnvironment::
get_cwd() {
  // getcwd() requires us to allocate a dynamic buffer and grow it on
  // demand.
  static size_t bufsize = 1024;
  static char *buffer = NULL;

  if (buffer == (char *)NULL) {
    buffer = new char[bufsize];
  }

  while (getcwd(buffer, bufsize) == (char *)NULL) {
    if (errno != ERANGE) {
      perror("getcwd");
      return string();
    }
    delete[] buffer;
    bufsize = bufsize * 2;
    buffer = new char[bufsize];
    assert(buffer != (char *)NULL);
  }

  return Filename::from_os_specific(buffer);
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_has_environment_variable
//       Access: Private
//  Description: Returns true if the indicated environment variable
//               is defined.  The nonstatic implementation.
////////////////////////////////////////////////////////////////////
bool ExecutionEnvironment::
ns_has_environment_variable(const string &var) const {
#ifdef PREREAD_ENVIRONMENT
  return _variables.count(var) != 0;
#else
  return getenv(var.c_str()) != (char *)NULL;
#endif
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_get_environment_variable
//       Access: Private
//  Description: Returns the definition of the indicated environment
//               variable, or the empty string if the variable is
//               undefined.  The nonstatic implementation.
////////////////////////////////////////////////////////////////////
string ExecutionEnvironment::
ns_get_environment_variable(const string &var) const {
#ifdef PREREAD_ENVIRONMENT
  EnvironmentVariables::const_iterator evi;
  evi = _variables.find(var);
  if (evi != _variables.end()) {
    return (*evi).second;
  }
  return string();
#else
  const char *def = getenv(var.c_str());
  if (def != (char *)NULL) {
    return def;
  }
  return string();
#endif
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_set_environment_variable
//       Access: Private
//  Description: Changes the definition of the indicated environment
//               variable.  The nonstatic implementation.
////////////////////////////////////////////////////////////////////
void ExecutionEnvironment::
ns_set_environment_variable(const string &var, const string &value) {
  _variables[var] = value;
  string putstr = var + "=" + value;

  // putenv() requires us to malloc a new C-style string.
  char *put = (char *)malloc(putstr.length() + 1);
  strcpy(put, putstr.c_str());
  putenv(put);
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_get_num_args
//       Access: Private
//  Description: Returns the number of command-line arguments
//               available, not counting arg 0, the binary name.  The
//               nonstatic implementation.
////////////////////////////////////////////////////////////////////
int ExecutionEnvironment::
ns_get_num_args() const {
  return _args.size();
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_get_arg
//       Access: Private
//  Description: Returns the nth command-line argument.  The index n
//               must be in the range [0 .. get_num_args()).  The
//               first parameter, n == 0, is the first actual
//               parameter, not the binary name.  The nonstatic
//               implementation.
////////////////////////////////////////////////////////////////////
string ExecutionEnvironment::
ns_get_arg(int n) const {
  assert(n >= 0 && n < ns_get_num_args());
  return _args[n];
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::ns_get_binary_name
//       Access: Private
//  Description: Returns the name of the binary executable that
//               started this program, if it can be determined.  The
//               nonstatic implementation.
////////////////////////////////////////////////////////////////////
string ExecutionEnvironment::
ns_get_binary_name() const {
  if (_binary_name.empty()) {
    return "unknown";
  }
  return _binary_name;
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::get_ptr
//       Access: Private, Static
//  Description: Returns a static pointer that may be used to access
//               the global ExecutionEnvironment object.
////////////////////////////////////////////////////////////////////
ExecutionEnvironment *ExecutionEnvironment::
get_ptr() {
  if (_global_ptr == (ExecutionEnvironment *)NULL) {
    _global_ptr = new ExecutionEnvironment;
  }
  return _global_ptr;
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::read_environment_variables
//       Access: Private
//  Description: Fills up the internal table of existing environment
//               variables, if we are in PREREAD_ENVIRONMENT mode.
//               Otherwise, does nothing.
////////////////////////////////////////////////////////////////////
void ExecutionEnvironment::
read_environment_variables() {
#ifdef PREREAD_ENVIRONMENT
#if defined(HAVE_PROC_SELF_ENVIRON)
  // In Linux, and possibly in other systems, we might not be able to
  // use getenv() at static init time.  However, we may be lucky and
  // have a file called /proc/self/environ that may be read to
  // determine all of our environment variables.

  ifstream proc("/proc/self/environ");
  if (proc.fail()) {
    cerr << "Cannot read /proc/self/environ; environment variables unavailable.\n";
    return;
  }

  int ch = proc.get();
  while (!proc.eof() && !proc.fail()) {
    string variable;
    string value;

    while (!proc.eof() && !proc.fail() && ch != '=' && ch != '\0') {
      variable += (char)ch;
      ch = proc.get();
    }

    if (ch == '=') {
      ch = proc.get();
      while (!proc.eof() && !proc.fail() && ch != '\0') {
        value += (char)ch;
        ch = proc.get();
      }
    }

    if (!variable.empty()) {
      _variables[variable] = value;
    }
    ch = proc.get();
  }
#else
  cerr << "Warning: environment variables unavailable to dconfig.\n";
#endif
#endif // PREREAD_ENVIRONMENT
}

////////////////////////////////////////////////////////////////////
//     Function: ExecutionEnvironment::read_args
//       Access: Private
//  Description: Reads all the command-line arguments and the name of
//               the binary file, if possible.
////////////////////////////////////////////////////////////////////
void ExecutionEnvironment::
read_args() {
#if defined(HAVE_GLOBAL_ARGV)
  int argc = GLOBAL_ARGC;

#ifdef WIN32_VC
  static const DWORD buffer_size = 1024;
  char buffer[buffer_size];
  DWORD size = GetModuleFileName(NULL, buffer, buffer_size);
  if (size != 0) {
    _binary_name = Filename::from_os_specific(string(buffer, size));
  }
#endif  // WIN32_VC

  if (_binary_name.empty() && argc > 0) {
    _binary_name = GLOBAL_ARGV[0];
  }

  for (int i = 1; i < argc; i++) {
    _args.push_back(GLOBAL_ARGV[i]);
  }

#elif defined(HAVE_PROC_SELF_CMDLINE)
  // In Linux, and possibly in other systems as well, we might not be
  // able to use the global ARGC/ARGV variables at static init time.
  // However, we may be lucky and have a file called
  // /proc/self/cmdline that may be read to determine all of our
  // command-line arguments.

  ifstream proc("/proc/self/cmdline");
  if (proc.fail()) {
    cerr << "Cannot read /proc/self/cmdline; command-line arguments unavailable to config.\n";
    return;
  }

  int ch = proc.get();
  int index = 0;
  while (!proc.eof() && !proc.fail()) {
    string arg;

    while (!proc.eof() && !proc.fail() && ch != '\0') {
      arg += (char)ch;
      ch = proc.get();
    }

    if (index == 0) {
      _binary_name = arg;
    } else {
      _args.push_back(arg);
    }
    index++;

    ch = proc.get();
  }
#else
  cerr << "Warning: command line parameters unavailable to dconfig.\n";
#endif
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <iostream>
#include <sstream>

#include "parsers/parse_error.hh"
#include "parsers/tina.hh"

namespace pnmc { namespace parsers {

namespace {

/*------------------------------------------------------------------------------------------------*/

unsigned int
value(std::string::const_iterator cit, std::string::const_iterator cend)
{
  std::string s(cit, cend);
  try
  {
    std::size_t pos;
    auto value = std::stoi(s, &pos);
    std::advance(cit, pos);
    if (std::distance(cit, cend) == 1)
    {
      switch (*cit)
      {
        case 'K': value *= 1000; break;
        case 'M': value *= 1000000; break;
        default: throw parse_error("Invalid suffix, got " + std::string(*cit, 1));
      }
    }
    else if (std::distance(cit, cend) > 1)
    {
      throw parse_error("Invalid suffix, got " + std::string(cit, cend));
    }
    return value;
  }
  catch (const std::invalid_argument&)
  {
    throw parse_error("Expected a value, got " + s);
  }
}

/*------------------------------------------------------------------------------------------------*/

std::pair<std::string, unsigned int>
place_valuation(const std::string& s)
{
  const auto star_cit = std::find(s.cbegin(), s.cend(), '*');
  if (star_cit == s.cend())
  {
    return std::make_pair(s, 1);
  }
  const auto valuation = value(star_cit + 1, s.cend());
  return std::make_pair(std::string(s.cbegin(), star_cit), valuation);
}

/*------------------------------------------------------------------------------------------------*/

unsigned int
marking(const std::string& s)
{
  if (*s.cbegin() == '(' and *std::prev(s.cend()) == ')')
  {
    return value(std::next(s.cbegin()), std::prev(s.cend()));
  }
  else
  {
    throw parse_error("Invalid marking format: " + s);
  }
}

} // namespace anonymous

/*------------------------------------------------------------------------------------------------*/

std::shared_ptr<pn::net>
tina(std::istream& in)
{
  // Known limitations:
  // - there's must be a transition or place per line
  // - labels are ignored

  std::shared_ptr<pn::net> net_ptr = std::make_shared<pn::net>();
  auto& net = *net_ptr;

  std::string line, s0, s1, s2, ignore;
  char peek;
  line.reserve(1024);

  while (std::getline(in, line))
  {
    std::istringstream ss(line);

    // Empty line or comment.
    if (((ss >> std::ws).peek() == std::char_traits<char>::to_int_type('#')) or not (ss >> s0))
    {
      continue;
    }

    // Net
    if (s0 == "net")
    {
      continue;
    }

    // Transitions
    else if (s0 == "tr")
    {
      std::string place_id;
      unsigned int valuation;

      if (ss >> s0)
      {
        net.add_transition(s0);
      }
      else
      {
        throw parse_error("Invalid transition: " + line);
      }

      // Ignore label, if any.
      peek = (ss >> std::ws).peek();
      if (peek == std::char_traits<char>::to_int_type(':'))
      {
        ss >> ignore >> ignore; // ':' <label>
      }

      // Skip time interval, if any.
      // We don't check if the interval is well-formed...
      peek = (ss >> std::ws).peek();
      if (   peek == std::char_traits<char>::to_int_type('[')
          or peek == std::char_traits<char>::to_int_type(']'))
      {
        ss >> s1;
      }

      bool found_arrow = false;
      while (ss >> s1)
      {
        if (s1 == "->")
        {
          found_arrow = true;
          break;
        }
        std::tie(place_id, valuation) = place_valuation(s1);
        net.add_pre_place(s0, place_id, valuation);
      }

      if (not found_arrow)
      {
        throw parse_error("Invalid transition (missing '->'): " + line);
      }

      while (ss >> s1)
      {
        std::tie(place_id, valuation) = place_valuation(s1);
        net.add_post_place(s0, place_id, valuation);
      }
    }

    // Places
    else if (s0 == "pl")
    {
      if (ss >> s1)
      {
        // Ignore label, if any.
        peek = (ss >> std::ws).peek();
        if (peek == std::char_traits<char>::to_int_type(':'))
        {
          ss >> ignore >> ignore; // ':' <label>
        }

        if (ss >> s2)
        {
          net.add_place(s1, marking(s2));
        }
        else
        {
          net.add_place(s1, 0);
        }
      }
      else
      {
        throw parse_error("Invalid place: " + line);
      }
    }

    // Error.
    else
    {
      throw parse_error("Invalid line: " + line);
    }
  }

  return net_ptr;
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace pnmc::parsers
<commit_msg>Add Tina net name to the Petri net.<commit_after>#include <algorithm>
#include <iostream>
#include <sstream>

#include "parsers/parse_error.hh"
#include "parsers/tina.hh"

namespace pnmc { namespace parsers {

namespace {

/*------------------------------------------------------------------------------------------------*/

unsigned int
value(std::string::const_iterator cit, std::string::const_iterator cend)
{
  std::string s(cit, cend);
  try
  {
    std::size_t pos;
    auto value = std::stoi(s, &pos);
    std::advance(cit, pos);
    if (std::distance(cit, cend) == 1)
    {
      switch (*cit)
      {
        case 'K': value *= 1000; break;
        case 'M': value *= 1000000; break;
        default: throw parse_error("Invalid suffix, got " + std::string(*cit, 1));
      }
    }
    else if (std::distance(cit, cend) > 1)
    {
      throw parse_error("Invalid suffix, got " + std::string(cit, cend));
    }
    return value;
  }
  catch (const std::invalid_argument&)
  {
    throw parse_error("Expected a value, got " + s);
  }
}

/*------------------------------------------------------------------------------------------------*/

std::pair<std::string, unsigned int>
place_valuation(const std::string& s)
{
  const auto star_cit = std::find(s.cbegin(), s.cend(), '*');
  if (star_cit == s.cend())
  {
    return std::make_pair(s, 1);
  }
  const auto valuation = value(star_cit + 1, s.cend());
  return std::make_pair(std::string(s.cbegin(), star_cit), valuation);
}

/*------------------------------------------------------------------------------------------------*/

unsigned int
marking(const std::string& s)
{
  if (*s.cbegin() == '(' and *std::prev(s.cend()) == ')')
  {
    return value(std::next(s.cbegin()), std::prev(s.cend()));
  }
  else
  {
    throw parse_error("Invalid marking format: " + s);
  }
}

} // namespace anonymous

/*------------------------------------------------------------------------------------------------*/

std::shared_ptr<pn::net>
tina(std::istream& in)
{
  // Known limitations:
  // - there's must be a transition or place per line
  // - labels are ignored

  std::shared_ptr<pn::net> net_ptr = std::make_shared<pn::net>();
  auto& net = *net_ptr;

  std::string line, s0, s1, s2, ignore;
  char peek;
  line.reserve(1024);

  while (std::getline(in, line))
  {
    std::istringstream ss(line);

    // Empty line or comment.
    if (((ss >> std::ws).peek() == std::char_traits<char>::to_int_type('#')) or not (ss >> s0))
    {
      continue;
    }

    // Net
    if (s0 == "net")
    {
      ss >> s0;
      net_ptr->name = s0;
    }

    // Transitions
    else if (s0 == "tr")
    {
      std::string place_id;
      unsigned int valuation;

      if (ss >> s0)
      {
        net.add_transition(s0);
      }
      else
      {
        throw parse_error("Invalid transition: " + line);
      }

      // Ignore label, if any.
      peek = (ss >> std::ws).peek();
      if (peek == std::char_traits<char>::to_int_type(':'))
      {
        ss >> ignore >> ignore; // ':' <label>
      }

      // Skip time interval, if any.
      // We don't check if the interval is well-formed...
      peek = (ss >> std::ws).peek();
      if (   peek == std::char_traits<char>::to_int_type('[')
          or peek == std::char_traits<char>::to_int_type(']'))
      {
        ss >> s1;
      }

      bool found_arrow = false;
      while (ss >> s1)
      {
        if (s1 == "->")
        {
          found_arrow = true;
          break;
        }
        std::tie(place_id, valuation) = place_valuation(s1);
        net.add_pre_place(s0, place_id, valuation);
      }

      if (not found_arrow)
      {
        throw parse_error("Invalid transition (missing '->'): " + line);
      }

      while (ss >> s1)
      {
        std::tie(place_id, valuation) = place_valuation(s1);
        net.add_post_place(s0, place_id, valuation);
      }
    }

    // Places
    else if (s0 == "pl")
    {
      if (ss >> s1)
      {
        // Ignore label, if any.
        peek = (ss >> std::ws).peek();
        if (peek == std::char_traits<char>::to_int_type(':'))
        {
          ss >> ignore >> ignore; // ':' <label>
        }

        if (ss >> s2)
        {
          net.add_place(s1, marking(s2));
        }
        else
        {
          net.add_place(s1, 0);
        }
      }
      else
      {
        throw parse_error("Invalid place: " + line);
      }
    }

    // Error.
    else
    {
      throw parse_error("Invalid line: " + line);
    }
  }

  return net_ptr;
}

/*------------------------------------------------------------------------------------------------*/

}} // namespace pnmc::parsers
<|endoftext|>


<commit_before>/**
 * Copyright 2008 Matthew Graham
 * 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 "client_server_test.h"
#include "blocking_client_queue.h"
#include "polling_server_queue.h"
#include "dispatcher.h"
#include "protocol.h"
#include "connection_listener_test.h"
#include "command_test.h"
#include "service_test.h"
#include <testpp/test.h>

mock_connection_c::mock_connection_c( std::queue< std::string > &read_queue,
			std::queue< std::string > &write_queue )
: m_read_queue( read_queue )
, m_write_queue( write_queue )
{}

void mock_connection_c::read_line( std::string &line )
{
	line = m_read_queue.front();
	m_read_queue.pop();
}

void mock_connection_c::write_line( const std::string &line )
{
	m_write_queue.push( line );
}

bool mock_connection_c::line_ready() const
{
	return ! m_read_queue.empty();
}

mock_client_server_connection_c::mock_client_server_connection_c()
: m_client_read_queue()
, m_server_read_queue()
, m_client( m_client_read_queue, m_server_read_queue )
, m_server( m_server_read_queue, m_client_read_queue )
{}

/**
 * Test that the mock_client_server_connection class works.
 */
TESTPP( test_mock_client_server_conn )
{
	mock_client_server_connection_c cs;
	connection_i &client( cs.client() );
	connection_i &server( cs.server() );

	std::string line;
	client.write_line( "test 1" );
	assertpp( server.line_ready() );
	server.read_line( line );
	assertpp( line ) == "test 1";
}

/**
 * Integration test of mock client running with mock server
 */
TESTPP( test_client_server )
{
	mock_client_server_connection_c cs;

	blocking_client_queue_c client( cs.client() );
	mock_connection_listener_c listener( cs.server() );
	polling_server_queue_c server( listener );
	dispatcher_c dispatch( server );

	protocol_c protocol( 3 );
	mock_service_c mock_srv;
	protocol.add( "mock", mock_srv );

	// need to add code and assertions here
	// create client command
	mock_command_c cmd( "id5", 17 );

	// send command to client
	client.send( cmd );

	// execute dispatcher
	dispatch.iterate();

	// read client response
	assertpp( cmd.response().code() ) == "ok";
	assertpp( cmd.response().message() ) == "id5_17";
}

<commit_msg>replaced blocking_client_queue_c with client_c<commit_after>/**
 * Copyright 2008 Matthew Graham
 * 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 "client_server_test.h"
#include "client.h"
#include "polling_server_queue.h"
#include "dispatcher.h"
#include "protocol.h"
#include "connection_listener_test.h"
#include "command_test.h"
#include "service_test.h"
#include <testpp/test.h>

mock_connection_c::mock_connection_c( std::queue< std::string > &read_queue,
			std::queue< std::string > &write_queue )
: m_read_queue( read_queue )
, m_write_queue( write_queue )
{}

void mock_connection_c::read_line( std::string &line )
{
	line = m_read_queue.front();
	m_read_queue.pop();
}

void mock_connection_c::write_line( const std::string &line )
{
	m_write_queue.push( line );
}

bool mock_connection_c::line_ready() const
{
	return ! m_read_queue.empty();
}

mock_client_server_connection_c::mock_client_server_connection_c()
: m_client_read_queue()
, m_server_read_queue()
, m_client( m_client_read_queue, m_server_read_queue )
, m_server( m_server_read_queue, m_client_read_queue )
{}

/**
 * Test that the mock_client_server_connection class works.
 */
TESTPP( test_mock_client_server_conn )
{
	mock_client_server_connection_c cs;
	connection_i &client( cs.client() );
	connection_i &server( cs.server() );

	std::string line;
	client.write_line( "test 1" );
	assertpp( server.line_ready() );
	server.read_line( line );
	assertpp( line ) == "test 1";
}

/**
 * Integration test of mock client running with mock server
 */
TESTPP( test_client_server )
{
	mock_client_server_connection_c cs;

	client_c client; // ( cs.client() );
	mock_connection_listener_c listener( cs.server() );
	polling_server_queue_c server( listener );
	dispatcher_c dispatch( server );

	protocol_c protocol( 3 );
	mock_service_c mock_srv;
	protocol.add( "mock", mock_srv );

	// need to add code and assertions here
	// create client command
	mock_command_c cmd( "id5", 17 );

	// send command to client
	client.send_request( cmd );

	// execute dispatcher
	dispatch.iterate();

	// read a command from the client
	client.wait_for_response( cmd );

	// read client response
	assertpp( cmd.response().code() ) == "ok";
	assertpp( cmd.response().message() ) == "id5_17";
}

<|endoftext|>


<commit_before>#pragma once

#include <limits>

#include "gpu_wrappers.hpp"
#include "definitions.hpp"
#include "util.hpp"

namespace arb {
namespace memory {

namespace impl {
    using size_type = std::size_t;

    constexpr bool
    is_power_of_two(size_type x) {
        return !(x&(x-1));
    }

    // returns the smallest power of two that is strictly greater than x
    constexpr size_type
    next_power_of_two(size_type x, size_type p) {
        return x==0 ? p : next_power_of_two(x-(x&p), p<<1);
    }

    // returns the smallest power of two that is greater than or equal to x
    constexpr size_type
    round_up_power_of_two(size_type x) {
        return is_power_of_two(x) ? x : next_power_of_two(x, 1);
    }

    // returns the smallest power of two that is greater than
    // or equal to sizeof(T), and greater than or equal to sizeof(void*)
    template <typename T>
    constexpr size_type
    minimum_possible_alignment() {
        return round_up_power_of_two(sizeof(T)) < sizeof(void*)
                    ?   sizeof(void*)
                    :   round_up_power_of_two(sizeof(T));
    }

    // Calculate the padding that has to be added to an array of T of length n
    // so that the size of the array in bytes is a multiple of sizeof(T).
    // The returned value is in terms of T, not bytes.
    template<typename T>
    size_type
    get_padding(const size_type alignment, size_type n) {
        // calculate the remaninder in bytes for n items of size sizeof(T)
        auto remainder = (n*sizeof(T)) % alignment;

        // calculate padding in bytes
        return remainder ? (alignment - remainder)/sizeof(T) : 0;
    }

    // allocate memory with alignment specified as a template parameter
    // returns nullptr on failure
    template <typename T, size_type alignment=minimum_possible_alignment<T>()>
    T* aligned_malloc(size_type size) {
        // double check that alignment is a multiple of sizeof(void*),
        // which is a prerequisite for posix_memalign()
        static_assert( !(alignment%sizeof(void*)),
                "alignment is not a multiple of sizeof(void*)");
        static_assert( is_power_of_two(alignment),
                "alignment is not a power of two");
        void *ptr;
        int result = posix_memalign(&ptr, alignment, size*sizeof(T));
        if(result) {
            return nullptr;
        }
        return reinterpret_cast<T*>(ptr);
    }

    template <size_type Alignment>
    class aligned_policy {
    public:
        void *allocate_policy(size_type size) {
            return reinterpret_cast<void *>(aligned_malloc<char, Alignment>(size));
        }

        void free_policy(void *ptr) {
            free(ptr);
        }

        static constexpr size_type alignment() {
            return Alignment;
        }
        static constexpr bool is_malloc_compatible() {
            return true;
        }
    };

    namespace gpu {
        template <size_type Alignment>
        class pinned_policy {
        public:
            void *allocate_policy(size_type size) {
                // first allocate memory with the desired alignment
                void* ptr = reinterpret_cast<void *>
                                (aligned_malloc<char, Alignment>(size));

                if (!ptr) {
                    return nullptr;
                }

                // register the memory
                if (!gpu_host_register(ptr, size)) {
                    free(ptr);
                    ptr = nullptr;
                }

                return ptr;
            }

            void free_policy(void *ptr) {
                if (!ptr) {
                    return;
                }
                gpu_host_unregister(ptr);
                free(ptr);
            }

            static constexpr size_type alignment() {
                return Alignment;
            }
            static constexpr bool is_malloc_compatible() {
                return true;
            }
        };

        class device_policy {
        public:
            void *allocate_policy(size_type size) {
                return gpu_malloc(size);
            }

            void free_policy(void *ptr) {
                gpu_free(ptr);
            }

            // memory allocated using cudaMalloc has alignment of 256 bytes
            // memory allocated using hipMalloc has alignment of 128 bytes
            static constexpr size_type alignment() {
#ifdef ARB_HIP
                return 128;
#else
                return 256;
#endif
            }
            static constexpr bool is_malloc_compatible() {
                return true;
            }
        };
    } // namespace gpu
} // namespace impl

template<typename T, typename Policy >
class allocator : public Policy {
    using Policy::allocate_policy;
    using Policy::free_policy;
public:
    using Policy::alignment;

    using value_type    = T;
    using pointer       = value_type*;
    using const_pointer = const value_type*;
    using reference     = value_type&;
    using const_reference = const value_type& ;
    using size_type       = std::size_t;
    using difference_type = std::ptrdiff_t;

public:
    template <typename U>
    using rebind = allocator<U, Policy>;

public:
    allocator() {}
    ~allocator() {}
    allocator(allocator const&) {}

    pointer address(reference r) {
        return &r;
    }
    const_pointer address(const_reference r) {
        return &r;
    }

    pointer allocate(size_type cnt, typename std::allocator<void>::const_pointer = 0) {
        if (cnt) {
            return reinterpret_cast<T*>(allocate_policy(cnt*sizeof(T)));
        }
        return nullptr;
    }

    void deallocate(pointer p, size_type cnt) {
        if (p) {
            free_policy(p);
        }
    }

    size_type max_size() const {
        return std::numeric_limits<size_type>::max() / sizeof(T);
    }

    void construct(pointer p, const T& t) {
        new(p) T(t);
    }

    void destroy(pointer p) {
        p->~T();
    }

    bool operator==(allocator const&) {
        return true;
    }
    bool operator!=(allocator const& a) {
        return !operator==(a);
    }
};

// pretty printers
namespace util {
    template <size_t Alignment>
    struct type_printer<impl::aligned_policy<Alignment>>{
        static std::string print() {
            std::stringstream str;
            str << "aligned_policy<" << Alignment << ">";
            return str.str();
        }
    };

    template <size_t Alignment>
    struct type_printer<impl::gpu::pinned_policy<Alignment>>{
        static std::string print() {
            std::stringstream str;
            str << "pinned_policy<" << Alignment << ">";
            return str.str();
        }
    };

    template <>
    struct type_printer<impl::gpu::device_policy>{
        static std::string print() {
            return std::string("device_policy");
        }
    };

    template <typename T, typename Policy>
    struct type_printer<allocator<T,Policy>>{
        static std::string print() {
            std::stringstream str;
            str << util::white("allocator") << "<" << type_printer<T>::print()
                << ", " << type_printer<Policy>::print() << ">";
            return str.str();
        }
    };
} // namespace util

// helper for generating an aligned allocator
template <class T, size_t alignment=impl::minimum_possible_alignment<T>()>
using aligned_allocator = allocator<T, impl::aligned_policy<alignment>>;

// For pinned and allocation set the default alignment to correspond to
// the alignment of 1024 bytes, because pinned memory is allocated at
// page boundaries. It is allocated at page boundaries (typically 4k),
// however in practice it will return pointers that are 1k aligned.
template <class T, size_t alignment=1024>
using pinned_allocator = allocator<T, impl::gpu::pinned_policy<alignment>>;

// use 256 as default alignment, because that is the default for cudaMalloc
template <class T, size_t alignment=256>
using gpu_allocator = allocator<T, impl::gpu::device_policy>;

} // namespace memory
} // namespace arb
<commit_msg>Update allocator implementations to C++17 standard (#1265)<commit_after>#pragma once

#include <limits>

#include "gpu_wrappers.hpp"
#include "definitions.hpp"
#include "util.hpp"

namespace arb {
namespace memory {

namespace impl {
    using size_type = std::size_t;

    constexpr bool
    is_power_of_two(size_type x) {
        return !(x&(x-1));
    }

    // returns the smallest power of two that is strictly greater than x
    constexpr size_type
    next_power_of_two(size_type x, size_type p) {
        return x==0 ? p : next_power_of_two(x-(x&p), p<<1);
    }

    // returns the smallest power of two that is greater than or equal to x
    constexpr size_type
    round_up_power_of_two(size_type x) {
        return is_power_of_two(x) ? x : next_power_of_two(x, 1);
    }

    // returns the smallest power of two that is greater than
    // or equal to sizeof(T), and greater than or equal to sizeof(void*)
    template <typename T>
    constexpr size_type
    minimum_possible_alignment() {
        return round_up_power_of_two(sizeof(T)) < sizeof(void*)
                    ?   sizeof(void*)
                    :   round_up_power_of_two(sizeof(T));
    }

    // Calculate the padding that has to be added to an array of T of length n
    // so that the size of the array in bytes is a multiple of sizeof(T).
    // The returned value is in terms of T, not bytes.
    template<typename T>
    size_type
    get_padding(const size_type alignment, size_type n) {
        // calculate the remaninder in bytes for n items of size sizeof(T)
        auto remainder = (n*sizeof(T)) % alignment;

        // calculate padding in bytes
        return remainder ? (alignment - remainder)/sizeof(T) : 0;
    }

    // allocate memory with alignment specified as a template parameter
    // returns nullptr on failure
    template <typename T, size_type alignment=minimum_possible_alignment<T>()>
    T* aligned_malloc(size_type size) {
        // double check that alignment is a multiple of sizeof(void*),
        // which is a prerequisite for posix_memalign()
        static_assert( !(alignment%sizeof(void*)),
                "alignment is not a multiple of sizeof(void*)");
        static_assert( is_power_of_two(alignment),
                "alignment is not a power of two");
        void *ptr;
        int result = posix_memalign(&ptr, alignment, size*sizeof(T));
        if(result) {
            return nullptr;
        }
        return reinterpret_cast<T*>(ptr);
    }

    template <size_type Alignment>
    class aligned_policy {
    public:
        void *allocate_policy(size_type size) {
            return reinterpret_cast<void *>(aligned_malloc<char, Alignment>(size));
        }

        void free_policy(void *ptr) {
            free(ptr);
        }

        static constexpr size_type alignment() {
            return Alignment;
        }
        static constexpr bool is_malloc_compatible() {
            return true;
        }
    };

    namespace gpu {
        template <size_type Alignment>
        class pinned_policy {
        public:
            void *allocate_policy(size_type size) {
                // first allocate memory with the desired alignment
                void* ptr = reinterpret_cast<void *>
                                (aligned_malloc<char, Alignment>(size));

                if (!ptr) {
                    return nullptr;
                }

                // register the memory
                if (!gpu_host_register(ptr, size)) {
                    free(ptr);
                    ptr = nullptr;
                }

                return ptr;
            }

            void free_policy(void *ptr) {
                if (!ptr) {
                    return;
                }
                gpu_host_unregister(ptr);
                free(ptr);
            }

            static constexpr size_type alignment() {
                return Alignment;
            }
            static constexpr bool is_malloc_compatible() {
                return true;
            }
        };

        class device_policy {
        public:
            void *allocate_policy(size_type size) {
                return gpu_malloc(size);
            }

            void free_policy(void *ptr) {
                gpu_free(ptr);
            }

            // memory allocated using cudaMalloc has alignment of 256 bytes
            // memory allocated using hipMalloc has alignment of 128 bytes
            static constexpr size_type alignment() {
#ifdef ARB_HIP
                return 128;
#else
                return 256;
#endif
            }
            static constexpr bool is_malloc_compatible() {
                return true;
            }
        };
    } // namespace gpu
} // namespace impl

template<typename T, typename Policy >
class allocator : public Policy {
    using Policy::allocate_policy;
    using Policy::free_policy;
public:
    using Policy::alignment;

    using value_type    = T;
    using pointer       = value_type*;
    using const_pointer = const value_type*;
    using reference     = value_type&;
    using const_reference = const value_type& ;
    using size_type       = std::size_t;
    using difference_type = std::ptrdiff_t;

public:
    template <typename U>
    using rebind = allocator<U, Policy>;

public:
    allocator() {}
    ~allocator() {}
    allocator(allocator const&) {}

    pointer address(reference r) {
        return &r;
    }
    const_pointer address(const_reference r) {
        return &r;
    }

    pointer allocate(size_type cnt) {
        if (cnt) {
            return reinterpret_cast<T*>(allocate_policy(cnt*sizeof(T)));
        }
        return nullptr;
    }

    void deallocate(pointer p, size_type cnt) {
        if (p) {
            free_policy(p);
        }
    }

    size_type max_size() const {
        return std::numeric_limits<size_type>::max() / sizeof(T);
    }

    void construct(pointer p, const T& t) {
        new(p) T(t);
    }

    void destroy(pointer p) {
        p->~T();
    }

    bool operator==(allocator const&) {
        return true;
    }
    bool operator!=(allocator const& a) {
        return !operator==(a);
    }
};

// pretty printers
namespace util {
    template <size_t Alignment>
    struct type_printer<impl::aligned_policy<Alignment>>{
        static std::string print() {
            std::stringstream str;
            str << "aligned_policy<" << Alignment << ">";
            return str.str();
        }
    };

    template <size_t Alignment>
    struct type_printer<impl::gpu::pinned_policy<Alignment>>{
        static std::string print() {
            std::stringstream str;
            str << "pinned_policy<" << Alignment << ">";
            return str.str();
        }
    };

    template <>
    struct type_printer<impl::gpu::device_policy>{
        static std::string print() {
            return std::string("device_policy");
        }
    };

    template <typename T, typename Policy>
    struct type_printer<allocator<T,Policy>>{
        static std::string print() {
            std::stringstream str;
            str << util::white("allocator") << "<" << type_printer<T>::print()
                << ", " << type_printer<Policy>::print() << ">";
            return str.str();
        }
    };
} // namespace util

// helper for generating an aligned allocator
template <class T, size_t alignment=impl::minimum_possible_alignment<T>()>
using aligned_allocator = allocator<T, impl::aligned_policy<alignment>>;

// For pinned and allocation set the default alignment to correspond to
// the alignment of 1024 bytes, because pinned memory is allocated at
// page boundaries. It is allocated at page boundaries (typically 4k),
// however in practice it will return pointers that are 1k aligned.
template <class T, size_t alignment=1024>
using pinned_allocator = allocator<T, impl::gpu::pinned_policy<alignment>>;

// use 256 as default alignment, because that is the default for cudaMalloc
template <class T, size_t alignment=256>
using gpu_allocator = allocator<T, impl::gpu::device_policy>;

} // namespace memory
} // namespace arb
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/delegates/gpu/gl/kernels/depthwise_conv.h"

#include <vector>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/delegates/gpu/common/operations.h"
#include "tensorflow/lite/delegates/gpu/gl/kernels/test_util.h"

using ::testing::FloatNear;
using ::testing::Pointwise;

namespace tflite {
namespace gpu {
namespace gl {
namespace {

TEST(DepthwiseConvTest, O4H1W1I2Strides1x1Dilation1x1) {
  TensorRef<BHWC> input;
  input.type = DataType::FLOAT32;
  input.ref = 0;
  input.shape = BHWC(1, 1, 1, 2);

  DepthwiseConvolution2DAttributes attr;
  Tensor<Linear, DataType::FLOAT32> bias;
  bias.shape.v = 4;
  bias.id = 1;
  bias.data = {1, 2, 3, 4};
  attr.bias = std::move(bias);

  Tensor<OHWI, DataType::FLOAT32> weights;
  weights.shape = OHWI(2, 1, 1, 2);
  weights.id = 2;
  weights.data = {1, 3, 2, 4};

  attr.weights = std::move(weights);

  attr.dilations = HW(1, 1);
  attr.padding.prepended = HW(0, 0);
  attr.padding.appended = HW(0, 0);
  attr.strides = HW(1, 1);

  TensorRef<BHWC> output;
  output.type = DataType::FLOAT32;
  output.ref = 3;
  output.shape = BHWC(1, 1, 1, 4);

  SingleOpModel model(
      {ToString(OperationType::CONVOLUTION_2D), std::move(attr)}, {input},
      {output});
  ASSERT_TRUE(model.PopulateTensor(0, {1, 3}));
  ASSERT_OK(model.Invoke(*NewDepthwiseConvolutionNodeShader()));
  EXPECT_THAT(model.GetOutput(0), Pointwise(FloatNear(1e-6), {2, 4, 12, 16}));
}

TEST(DepthwiseConvTest, O2H1W1I1Strides2x2Dilation1x1) {
  TensorRef<BHWC> input;
  input.type = DataType::FLOAT32;
  input.ref = 0;
  input.shape = BHWC(1, 3, 3, 1);

  DepthwiseConvolution2DAttributes attr;
  Tensor<Linear, DataType::FLOAT32> bias;
  bias.shape.v = 4;
  bias.id = 1;
  bias.data = {0, 0};
  attr.bias = std::move(bias);

  Tensor<OHWI, DataType::FLOAT32> weights;
  weights.shape = OHWI(2, 1, 1, 1);
  weights.id = 1;
  weights.data = {1, 3};

  attr.weights = std::move(weights);

  attr.dilations = HW(1, 1);
  attr.padding.prepended = HW(0, 0);
  attr.padding.appended = HW(0, 0);
  attr.strides = HW(2, 2);

  TensorRef<BHWC> output;
  output.type = DataType::FLOAT32;
  output.ref = 3;
  output.shape = BHWC(1, 2, 2, 2);

  SingleOpModel model(
      {ToString(OperationType::CONVOLUTION_2D), std::move(attr)}, {input},
      {output});
  ASSERT_TRUE(model.PopulateTensor(0, {1, 0, 1, 1, 0, 1, 1, 0, 1}));
  ASSERT_OK(model.Invoke(*NewDepthwiseConvolutionNodeShader()));
  EXPECT_THAT(model.GetOutput(0),
              Pointwise(FloatNear(1e-6), {1, 3, 1, 3, 1, 3, 1, 3}));
}

TEST(DepthwiseConvTest, O2H2W2I1Strides1x1Dilation2x2) {
  TensorRef<BHWC> input;
  input.type = DataType::FLOAT32;
  input.ref = 0;
  input.shape = BHWC(1, 3, 3, 1);

  DepthwiseConvolution2DAttributes attr;
  Tensor<Linear, DataType::FLOAT32> bias;
  bias.shape.v = 4;
  bias.id = 1;
  bias.data = {0, 0};
  attr.bias = std::move(bias);

  Tensor<OHWI, DataType::FLOAT32> weights;
  weights.shape = OHWI(2, 2, 2, 1);
  weights.id = 1;
  weights.data = {1, 2, 3, 4, 5, 6, 7, 8};

  attr.weights = std::move(weights);

  attr.dilations = HW(2, 2);
  attr.padding.prepended = HW(0, 0);
  attr.padding.appended = HW(0, 0);
  attr.strides = HW(1, 1);

  TensorRef<BHWC> output;
  output.type = DataType::FLOAT32;
  output.ref = 3;
  output.shape = BHWC(1, 1, 1, 2);

  SingleOpModel model(
      {ToString(OperationType::CONVOLUTION_2D), std::move(attr)}, {input},
      {output});
  ASSERT_TRUE(model.PopulateTensor(0, {1, 0, 1, 1, 0, 1, 1, 0, 1}));
  ASSERT_OK(model.Invoke(*NewDepthwiseConvolutionNodeShader()));
  EXPECT_THAT(model.GetOutput(0), Pointwise(FloatNear(1e-6), {10, 26}));
}

}  // namespace
}  // namespace gl
}  // namespace gpu
}  // namespace tflite
<commit_msg>Fix typo in depthwise conv unit tests.<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/delegates/gpu/gl/kernels/depthwise_conv.h"

#include <vector>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/delegates/gpu/common/operations.h"
#include "tensorflow/lite/delegates/gpu/gl/kernels/test_util.h"

using ::testing::FloatNear;
using ::testing::Pointwise;

namespace tflite {
namespace gpu {
namespace gl {
namespace {

TEST(DepthwiseConvTest, O4H1W1I2Strides1x1Dilation1x1) {
  TensorRef<BHWC> input;
  input.type = DataType::FLOAT32;
  input.ref = 0;
  input.shape = BHWC(1, 1, 1, 2);

  DepthwiseConvolution2DAttributes attr;
  Tensor<Linear, DataType::FLOAT32> bias;
  bias.shape.v = 4;
  bias.id = 1;
  bias.data = {1, 2, 3, 4};
  attr.bias = std::move(bias);

  Tensor<OHWI, DataType::FLOAT32> weights;
  weights.shape = OHWI(2, 1, 1, 2);
  weights.id = 2;
  weights.data = {1, 3, 2, 4};

  attr.weights = std::move(weights);

  attr.dilations = HW(1, 1);
  attr.padding.prepended = HW(0, 0);
  attr.padding.appended = HW(0, 0);
  attr.strides = HW(1, 1);

  TensorRef<BHWC> output;
  output.type = DataType::FLOAT32;
  output.ref = 3;
  output.shape = BHWC(1, 1, 1, 4);

  SingleOpModel model(
      {ToString(OperationType::DEPTHWISE_CONVOLUTION), std::move(attr)},
      {input}, {output});
  ASSERT_TRUE(model.PopulateTensor(0, {1, 3}));
  ASSERT_OK(model.Invoke(*NewDepthwiseConvolutionNodeShader()));
  EXPECT_THAT(model.GetOutput(0), Pointwise(FloatNear(1e-6), {2, 4, 12, 16}));
}

TEST(DepthwiseConvTest, O2H1W1I1Strides2x2Dilation1x1) {
  TensorRef<BHWC> input;
  input.type = DataType::FLOAT32;
  input.ref = 0;
  input.shape = BHWC(1, 3, 3, 1);

  DepthwiseConvolution2DAttributes attr;
  Tensor<Linear, DataType::FLOAT32> bias;
  bias.shape.v = 4;
  bias.id = 1;
  bias.data = {0, 0};
  attr.bias = std::move(bias);

  Tensor<OHWI, DataType::FLOAT32> weights;
  weights.shape = OHWI(2, 1, 1, 1);
  weights.id = 1;
  weights.data = {1, 3};

  attr.weights = std::move(weights);

  attr.dilations = HW(1, 1);
  attr.padding.prepended = HW(0, 0);
  attr.padding.appended = HW(0, 0);
  attr.strides = HW(2, 2);

  TensorRef<BHWC> output;
  output.type = DataType::FLOAT32;
  output.ref = 3;
  output.shape = BHWC(1, 2, 2, 2);

  SingleOpModel model(
      {ToString(OperationType::DEPTHWISE_CONVOLUTION), std::move(attr)},
      {input}, {output});
  ASSERT_TRUE(model.PopulateTensor(0, {1, 0, 1, 1, 0, 1, 1, 0, 1}));
  ASSERT_OK(model.Invoke(*NewDepthwiseConvolutionNodeShader()));
  EXPECT_THAT(model.GetOutput(0),
              Pointwise(FloatNear(1e-6), {1, 3, 1, 3, 1, 3, 1, 3}));
}

TEST(DepthwiseConvTest, O2H2W2I1Strides1x1Dilation2x2) {
  TensorRef<BHWC> input;
  input.type = DataType::FLOAT32;
  input.ref = 0;
  input.shape = BHWC(1, 3, 3, 1);

  DepthwiseConvolution2DAttributes attr;
  Tensor<Linear, DataType::FLOAT32> bias;
  bias.shape.v = 4;
  bias.id = 1;
  bias.data = {0, 0};
  attr.bias = std::move(bias);

  Tensor<OHWI, DataType::FLOAT32> weights;
  weights.shape = OHWI(2, 2, 2, 1);
  weights.id = 1;
  weights.data = {1, 2, 3, 4, 5, 6, 7, 8};

  attr.weights = std::move(weights);

  attr.dilations = HW(2, 2);
  attr.padding.prepended = HW(0, 0);
  attr.padding.appended = HW(0, 0);
  attr.strides = HW(1, 1);

  TensorRef<BHWC> output;
  output.type = DataType::FLOAT32;
  output.ref = 3;
  output.shape = BHWC(1, 1, 1, 2);

  SingleOpModel model(
      {ToString(OperationType::DEPTHWISE_CONVOLUTION), std::move(attr)},
      {input}, {output});
  ASSERT_TRUE(model.PopulateTensor(0, {1, 0, 1, 1, 0, 1, 1, 0, 1}));
  ASSERT_OK(model.Invoke(*NewDepthwiseConvolutionNodeShader()));
  EXPECT_THAT(model.GetOutput(0), Pointwise(FloatNear(1e-6), {10, 26}));
}

}  // namespace
}  // namespace gl
}  // namespace gpu
}  // namespace tflite
<|endoftext|>


<commit_before><commit_msg>FDKPRO-456: Margin and Profit are calculated uncorrect if open position partly<commit_after><|endoftext|>